blob: 12a25e2ffd682d82ccedfbe228f0dc92723a0922 [file] [log] [blame]
// KASAN: use-after-free Read in skb_dequeue
// https://syzkaller.appspot.com/bug?id=380acd1f7d59c28809f18bb577d645aab34d23b0
// status:fixed
// autogenerated by syzkaller (http://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
__attribute__((noreturn)) static void doexit(int status)
{
volatile unsigned i;
syscall(__NR_exit_group, status);
for (i = 0;; i++) {
}
}
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
const int kFailStatus = 67;
const int kRetryStatus = 69;
static void fail(const char* msg, ...)
{
int e = errno;
va_list args;
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
fprintf(stderr, " (errno %d)\n", e);
doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
}
#define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1)
#define BITMASK_LEN_OFF(type, bf_off, bf_len) \
(type)(BITMASK_LEN(type, (bf_len)) << (bf_off))
#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \
if ((bf_off) == 0 && (bf_len) == 0) { \
*(type*)(addr) = (type)(val); \
} else { \
type new_val = *(type*)(addr); \
new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \
new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \
*(type*)(addr) = new_val; \
}
struct csum_inet {
uint32_t acc;
};
static void csum_inet_init(struct csum_inet* csum)
{
csum->acc = 0;
}
static void csum_inet_update(struct csum_inet* csum, const uint8_t* data,
size_t length)
{
if (length == 0)
return;
size_t i;
for (i = 0; i < length - 1; i += 2)
csum->acc += *(uint16_t*)&data[i];
if (length & 1)
csum->acc += (uint16_t)data[length - 1];
while (csum->acc > 0xffff)
csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16);
}
static uint16_t csum_inet_digest(struct csum_inet* csum)
{
return ~csum->acc;
}
static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
{
if (a0 == 0xc || a0 == 0xb) {
char buf[128];
sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1,
(uint8_t)a2);
return open(buf, O_RDWR, 0);
} else {
char buf[1024];
char* hash;
strncpy(buf, (char*)a0, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(a1 % 10);
a1 /= 10;
}
return open(buf, a2, 0);
}
}
static void loop();
static void sandbox_common()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
setsid();
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 160 << 20;
setrlimit(RLIMIT_AS, &rlim);
rlim.rlim_cur = rlim.rlim_max = 8 << 20;
setrlimit(RLIMIT_MEMLOCK, &rlim);
rlim.rlim_cur = rlim.rlim_max = 136 << 20;
setrlimit(RLIMIT_FSIZE, &rlim);
rlim.rlim_cur = rlim.rlim_max = 1 << 20;
setrlimit(RLIMIT_STACK, &rlim);
rlim.rlim_cur = rlim.rlim_max = 0;
setrlimit(RLIMIT_CORE, &rlim);
if (unshare(CLONE_NEWNS)) {
}
if (unshare(CLONE_NEWIPC)) {
}
if (unshare(0x02000000)) {
}
if (unshare(CLONE_NEWUTS)) {
}
if (unshare(CLONE_SYSVSEM)) {
}
}
static int do_sandbox_none(void)
{
if (unshare(CLONE_NEWPID)) {
}
int pid = fork();
if (pid < 0)
fail("sandbox fork failed");
if (pid)
return pid;
sandbox_common();
if (unshare(CLONE_NEWNET)) {
}
loop();
doexit(1);
}
uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff};
void loop()
{
long res = 0;
res = syscall(__NR_socket, 0x11, 0x100000803, 0);
if (res != -1)
r[0] = res;
memcpy((void*)0x200000c0, "/dev/net/tun", 13);
res = syz_open_dev(0x200000c0, 0, 0x20000000002);
if (res != -1)
r[1] = res;
memcpy((void*)0x20000040,
"\x69\x66\x62\x30\x00\xfa\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00",
16);
*(uint16_t*)0x20000050 = 0x5001;
syscall(__NR_ioctl, r[1], 0x400454ca, 0x20000040);
*(uint32_t*)0x20001000 = 0x10000;
*(uint32_t*)0x20001004 = 4;
*(uint32_t*)0x20001008 = 0x100;
*(uint32_t*)0x2000100c = 0x400;
syscall(__NR_setsockopt, -1, 0x84, 0, 0x20001000, 6);
res = syscall(__NR_socket, 0x11, 3, 0);
if (res != -1)
r[2] = res;
*(uint32_t*)0x20788000 = 2;
syscall(__NR_setsockopt, r[2], 0x107, 0xf, 0x20788000, 4);
*(uint16_t*)0x20000480 = 0x11;
*(uint16_t*)0x20000482 = htobe16(3);
*(uint32_t*)0x20000484 = 0;
*(uint16_t*)0x20000488 = 1;
*(uint8_t*)0x2000048a = 0;
*(uint8_t*)0x2000048b = 6;
*(uint8_t*)0x2000048c = 0xaa;
*(uint8_t*)0x2000048d = 0xaa;
*(uint8_t*)0x2000048e = 0xaa;
*(uint8_t*)0x2000048f = 0xaa;
*(uint8_t*)0x20000490 = 0xaa;
*(uint8_t*)0x20000491 = 0xaa;
*(uint8_t*)0x20000492 = 0;
*(uint8_t*)0x20000493 = 0;
syscall(__NR_bind, r[2], 0x20000480, 0x14);
syscall(__NR_setsockopt, r[2], 0x107, 5, 0x20001000, 0xc5);
*(uint32_t*)0x20000100 = 0x20;
syscall(__NR_setsockopt, r[2], 0x107, 7, 0x20000100, 4);
memcpy((void*)0x20000000,
"\x69\x66\x62\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
16);
*(uint16_t*)0x20000010 = 0xa201;
syscall(__NR_ioctl, r[0], 0x8914, 0x20000000);
*(uint8_t*)0x20000200 = 0;
*(uint8_t*)0x20000201 = 3;
*(uint16_t*)0x20000202 = 0;
*(uint16_t*)0x20000204 = 8;
*(uint16_t*)0x20000206 = 0;
*(uint16_t*)0x20000208 = 0;
STORE_BY_BITMASK(uint8_t, 0x2000020a, 0, 0, 4);
STORE_BY_BITMASK(uint8_t, 0x2000020a, 6, 4, 4);
memcpy((void*)0x2000020b, "\xce\x38\x45", 3);
*(uint16_t*)0x2000020e = htobe16(0x14);
*(uint8_t*)0x20000210 = 0;
*(uint8_t*)0x20000211 = 0;
*(uint8_t*)0x20000212 = 0;
*(uint8_t*)0x20000213 = 0;
*(uint8_t*)0x20000214 = 0;
*(uint8_t*)0x20000215 = 0;
*(uint8_t*)0x20000216 = 0;
*(uint8_t*)0x20000217 = 0;
*(uint8_t*)0x20000218 = 0;
*(uint8_t*)0x20000219 = 0;
*(uint8_t*)0x2000021a = 0;
*(uint8_t*)0x2000021b = 0;
*(uint8_t*)0x2000021c = 0;
*(uint8_t*)0x2000021d = 0;
*(uint8_t*)0x2000021e = 0;
*(uint8_t*)0x2000021f = 0;
*(uint8_t*)0x20000220 = 0;
*(uint8_t*)0x20000221 = 0;
*(uint8_t*)0x20000222 = 0xfe;
*(uint8_t*)0x20000223 = 0x80;
*(uint8_t*)0x20000224 = 0;
*(uint8_t*)0x20000225 = 0;
*(uint8_t*)0x20000226 = 0;
*(uint8_t*)0x20000227 = 0;
*(uint8_t*)0x20000228 = 0;
*(uint8_t*)0x20000229 = 0;
*(uint8_t*)0x2000022a = 0;
*(uint8_t*)0x2000022b = 0;
*(uint8_t*)0x2000022c = 0;
*(uint8_t*)0x2000022d = 0;
*(uint8_t*)0x2000022e = 0;
*(uint8_t*)0x2000022f = 0;
*(uint8_t*)0x20000230 = 0;
*(uint8_t*)0x20000231 = 0;
*(uint16_t*)0x20000232 = htobe16(0);
*(uint16_t*)0x20000234 = htobe16(0);
*(uint32_t*)0x20000236 = 0x41424344;
*(uint32_t*)0x2000023a = 0x41424344;
STORE_BY_BITMASK(uint8_t, 0x2000023e, 0, 0, 1);
STORE_BY_BITMASK(uint8_t, 0x2000023e, 0, 1, 3);
STORE_BY_BITMASK(uint8_t, 0x2000023e, 5, 4, 4);
*(uint8_t*)0x2000023f = 0;
*(uint16_t*)0x20000240 = htobe16(0);
*(uint16_t*)0x20000242 = 0;
*(uint16_t*)0x20000244 = htobe16(0);
struct csum_inet csum_1;
csum_inet_init(&csum_1);
csum_inet_update(&csum_1, (const uint8_t*)0x20000212, 16);
csum_inet_update(&csum_1, (const uint8_t*)0x20000222, 16);
uint32_t csum_1_chunk_2 = 0x14000000;
csum_inet_update(&csum_1, (const uint8_t*)&csum_1_chunk_2, 4);
uint32_t csum_1_chunk_3 = 0x6000000;
csum_inet_update(&csum_1, (const uint8_t*)&csum_1_chunk_3, 4);
csum_inet_update(&csum_1, (const uint8_t*)0x20000232, 20);
*(uint16_t*)0x20000242 = csum_inet_digest(&csum_1);
syscall(__NR_write, r[1], 0x20000200, 0xfcfb);
}
int main()
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
int pid = do_sandbox_none();
int status = 0;
while (waitpid(pid, &status, __WALL) != pid) {
}
return 0;
}