blob: ec8770ee0099275d12656212b99f864970cf7d7d [file] [log] [blame]
// general protection fault in loopback_pos_update
// https://syzkaller.appspot.com/bug?id=ac6955dae93e824d682bb5112d4e8fee21020e1a
// status:fixed
// autogenerated by syzkaller (http://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/futex.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
__attribute__((noreturn)) static void doexit(int status)
{
volatile unsigned i;
syscall(__NR_exit_group, status);
for (i = 0;; i++) {
}
}
#include <stdint.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);
}
static uint64_t current_time_ms()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
fail("clock_gettime failed");
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
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));
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(a1 % 10);
a1 /= 10;
}
return open(buf, a2, 0);
}
}
static void test();
void loop()
{
int iter;
for (iter = 0;; iter++) {
int pid = fork();
if (pid < 0)
fail("loop fork failed");
if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
test();
doexit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
int res = waitpid(-1, &status, __WALL | WNOHANG);
if (res == pid)
break;
usleep(1000);
if (current_time_ms() - start > 5 * 1000) {
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
while (waitpid(-1, &status, __WALL) != pid) {
}
break;
}
}
}
}
struct thread_t {
int created, running, call;
pthread_t th;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static int collide;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
__atomic_store_n(&th->running, 0, __ATOMIC_RELEASE);
syscall(SYS_futex, &th->running, FUTEX_WAKE);
}
return 0;
}
static void execute(int num_calls)
{
int call, thread;
running = 0;
for (call = 0; call < num_calls; call++) {
for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
pthread_create(&th->th, &attr, thr, th);
}
if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) {
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
__atomic_store_n(&th->running, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &th->running, FUTEX_WAKE);
if (collide && call % 2)
break;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 20 * 1000 * 1000;
syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts);
if (running)
usleep((call == num_calls - 1) ? 10000 : 1000);
break;
}
}
}
}
#ifndef __NR_ioctl
#define __NR_ioctl 54
#endif
#ifndef __NR_write
#define __NR_write 4
#endif
#ifndef __NR_writev
#define __NR_writev 146
#endif
#ifndef __NR_fcntl
#define __NR_fcntl 55
#endif
#ifndef __NR_readv
#define __NR_readv 145
#endif
#ifndef __NR_mmap
#define __NR_mmap 192
#endif
#ifndef __NR_getsockopt
#define __NR_getsockopt 365
#endif
#ifndef __NR_sendmmsg
#define __NR_sendmmsg 345
#endif
#ifndef __NR_setsockopt
#define __NR_setsockopt 366
#endif
#ifndef __NR_prctl
#define __NR_prctl 172
#endif
#ifndef __NR_read
#define __NR_read 3
#endif
#undef __NR_mmap
#define __NR_mmap __NR_mmap2
long r[3];
uint64_t procid;
void execute_call(int call)
{
switch (call) {
case 0:
syscall(__NR_mmap, 0x20000000, 0xfff000, 3, 0x32, -1, 0);
break;
case 1:
memcpy((void*)0x20000000, "/dev/adsp#", 11);
r[0] = syz_open_dev(0x20000000, 1, 0x80801);
break;
case 2:
*(uint32_t*)0x20005ff0 = 0;
*(uint32_t*)0x20005ff4 = 0x50;
*(uint32_t*)0x20005ff8 = 3;
*(uint32_t*)0x20005ffc = 2;
*(uint32_t*)0x20000ffc = 0x10;
if (syscall(__NR_getsockopt, r[0], 0x84, 0, 0x20005ff0, 0x20000ffc) != -1)
r[1] = *(uint32_t*)0x20005ff0;
break;
case 3:
*(uint32_t*)0x20006f90 = 0;
*(uint32_t*)0x20006f94 = 0;
*(uint32_t*)0x20006f98 = 0x20006000;
*(uint32_t*)0x20006f9c = 5;
*(uint32_t*)0x20006fa0 = 0x20006fe8;
*(uint32_t*)0x20006fa4 = 0x10;
*(uint32_t*)0x20006fa8 = 0x4011;
*(uint32_t*)0x20006fac = 0;
*(uint32_t*)0x20006fb0 = 0;
*(uint32_t*)0x20006fb4 = 0x20004fd0;
*(uint32_t*)0x20006fb8 = 3;
*(uint32_t*)0x20006fbc = 0x20001f88;
*(uint32_t*)0x20006fc0 = 0x50;
*(uint32_t*)0x20006fc4 = 0xc844;
*(uint32_t*)0x20006000 = 0x20006ff0;
*(uint32_t*)0x20006004 = 0;
*(uint32_t*)0x20006008 = 0x20006000;
*(uint32_t*)0x2000600c = 0;
*(uint32_t*)0x20006010 = 0x20006fdd;
*(uint32_t*)0x20006014 = 0;
*(uint32_t*)0x20006018 = 0x20006fe7;
*(uint32_t*)0x2000601c = 0;
*(uint32_t*)0x20006020 = 0x20006000;
*(uint32_t*)0x20006024 = 0xc3;
memcpy((void*)0x20006000,
"\x5c\x0d\x30\x13\xc6\x75\xa3\xb7\xf4\x8e\x5e\x45\x11\x01\xdd\xe9"
"\x93\xe2\x77\x33\xb6\x5b\x7f\x13\x57\x39\xf9\x8b\x26\x35\xf1\x6a"
"\x83\x2c\x37\x70\xac\xe9\xd1\x7d\xde\xcd\x1d\x42\x25\x94\x4c\xbb"
"\x53\x4c\x7d\x83\x2b\xb6\xab\xaf\xd5\x46\xfc\x9a\x5b\xac\xb0\xf9"
"\xda\xf2\xf6\x55\x5c\x41\xf6\x1f\x90\xf7\xf3\xfc\x7a\xa0\x2d\x8e"
"\xf1\xe1\xb6\xbd\xf5\x12\x64\xde\x45\x1d\x6e\x1b\xd3\x40\x9a\x04"
"\xe7\x20\xff\xaf\xef\x68\xa4\x20\x1d\x0d\xe6\x67\x6b\x50\x1f\x7a"
"\x08\x0d\x73\xfe\x8d\x8f\x42\x42\xbb\x31\x29\x84\x6f\x2a\x06\x1c"
"\xd6\x17\xfd\xaf\x00\x9d\x89\x2a\x94\xb6\xaa\x09\x7c\x7f\x43\x3e"
"\xf7\xc7\x3b\x5a\x14\x73\x9e\x17\x50\xc7\xc9\xe2\x17\xcb\xec\xf6"
"\xeb\x30\x63\xa6\x4a\x2a\x58\x30\x84\x47\x55\x01\xac\x61\x1b\x25"
"\xab\x59\x69\x7f\x4e\x81\xf0\xe8\x3b\x60\xe6\xb8\x26\x9b\x6d\x1c"
"\x31\xd1\x35",
195);
*(uint32_t*)0x20006fe8 = 0x10;
*(uint32_t*)0x20006fec = 0x117;
*(uint32_t*)0x20006ff0 = 4;
*(uint32_t*)0x20006ff4 = 0x332;
*(uint32_t*)0x20004fd0 = 0x20006000;
*(uint32_t*)0x20004fd4 = 0;
*(uint32_t*)0x20004fd8 = 0x20005f98;
*(uint32_t*)0x20004fdc = 0;
*(uint32_t*)0x20004fe0 = 0x20006f80;
*(uint32_t*)0x20004fe4 = 0;
*(uint32_t*)0x20001f88 = 0x10;
*(uint32_t*)0x20001f8c = 0x117;
*(uint32_t*)0x20001f90 = 3;
*(uint32_t*)0x20001f94 = 1;
*(uint32_t*)0x20001f98 = 0x10;
*(uint32_t*)0x20001f9c = 0x117;
*(uint32_t*)0x20001fa0 = 4;
*(uint32_t*)0x20001fa4 = 0x1ff;
*(uint32_t*)0x20001fa8 = 0x10;
*(uint32_t*)0x20001fac = 0x117;
*(uint32_t*)0x20001fb0 = 3;
*(uint32_t*)0x20001fb4 = 1;
*(uint32_t*)0x20001fb8 = 0x10;
*(uint32_t*)0x20001fbc = 0x117;
*(uint32_t*)0x20001fc0 = 4;
*(uint32_t*)0x20001fc4 = 9;
*(uint32_t*)0x20001fc8 = 0x10;
*(uint32_t*)0x20001fcc = 0x117;
*(uint32_t*)0x20001fd0 = 4;
*(uint32_t*)0x20001fd4 = 6;
syscall(__NR_sendmmsg, r[0], 0x20006f90, 2, 1);
break;
case 4:
*(uint32_t*)0x20004ffc = r[1];
syscall(__NR_setsockopt, r[0], 0x84, 0xd, 0x20004ffc, 4);
break;
case 5:
*(uint32_t*)0x20001ff4 = 0x6238;
*(uint32_t*)0x20001ff8 = 4;
*(uint32_t*)0x20001ffc = 6;
syscall(__NR_ioctl, r[0], 0xc008551c, 0x20001ff4);
break;
case 6:
*(uint16_t*)0x20000ff0 = 3;
*(uint32_t*)0x20000ff4 = 0x20000000;
*(uint16_t*)0x20000000 = 0;
*(uint8_t*)0x20000002 = -1;
*(uint8_t*)0x20000003 = 7;
*(uint32_t*)0x20000004 = 7;
*(uint16_t*)0x20000008 = 8;
*(uint8_t*)0x2000000a = 1;
*(uint8_t*)0x2000000b = 0x20;
*(uint32_t*)0x2000000c = 2;
*(uint16_t*)0x20000010 = 0xfffe;
*(uint8_t*)0x20000012 = 1;
*(uint8_t*)0x20000013 = 0x65;
*(uint32_t*)0x20000014 = 0x8000;
syscall(__NR_prctl, 0x16, 0, 0x20000ff0);
break;
case 7:
syscall(__NR_writev, r[0], 0x20004fe0, 1);
break;
case 8:
syscall(__NR_setsockopt, r[0], 0, 0x27, 0x20007fdc, 0);
break;
case 9:
*(uint64_t*)0x20000ff8 = 0;
syscall(__NR_write, r[0], 0x20000ff8, 0xffffffa1);
break;
case 10:
*(uint64_t*)0x20003ff8 = 5;
syscall(__NR_fcntl, r[0], 0x40c, 0x20003ff8);
break;
case 11:
memcpy((void*)0x20008000, "/dev/dsp#", 10);
r[2] = syz_open_dev(0x20008000, 1, 0);
break;
case 12:
syscall(__NR_fcntl, r[2], 0xa, 0xc);
break;
case 13:
*(uint32_t*)0x2054bff0 = 0x20006f07;
*(uint32_t*)0x2054bff4 = 0xf9;
syscall(__NR_readv, r[2], 0x2054bff0, 1);
break;
case 14:
syscall(__NR_read, r[2], 0x20ec0000, 0);
break;
}
}
void test()
{
memset(r, -1, sizeof(r));
execute(15);
collide = 1;
execute(15);
}
int main()
{
for (procid = 0; procid < 8; procid++) {
if (fork() == 0) {
for (;;) {
loop();
}
}
}
sleep(1000000);
return 0;
}