sys/linux: add cgroup descriptions

This commit is contained in:
Dmitry Vyukov 2018-03-22 13:24:02 +01:00
parent 2e9d905410
commit 2675f92065
35 changed files with 1376 additions and 349 deletions

View File

@ -42,6 +42,12 @@ typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef SYZ_EXECUTOR
// Note: zircon max fd is 256.
const int kInPipeFd = 250; // remapped from stdin
const int kOutPipeFd = 251; // remapped from stdout
#endif
#if defined(__GNUC__)
#define SYSCALLAPI
#define NORETURN __attribute__((noreturn))

View File

@ -43,15 +43,20 @@
#include <sys/time.h>
#include <sys/wait.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) || defined(SYZ_SANDBOX_NAMESPACE) || \
defined(SYZ_ENABLE_CGROUPS)
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID)
#include <grp.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
#include <fcntl.h>
#include <linux/capability.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
#include <arpa/inet.h>
@ -120,11 +125,15 @@
#include <unistd.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_genetlink_get_family_id)
#include <errno.h>
#include <linux/genetlink.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
#include <sys/mount.h>
#endif
#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \
defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \
@ -791,6 +800,74 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin
#endif
#endif // #ifdef __NR_syz_kvm_setup_cpu
#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) || defined(SYZ_SANDBOX_NAMESPACE) || \
defined(SYZ_ENABLE_CGROUPS)
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
static void setup_cgroups()
{
if (mkdir("/syzcgroup", 0777)) {
debug("mkdir(/syzcgroup) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/unified", 0777)) {
debug("mkdir(/syzcgroup/unified) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/unified", "cgroup2", 0, NULL)) {
debug("mount(cgroup2) failed: %d\n", errno);
}
if (chmod("/syzcgroup/unified", 0777)) {
debug("chmod(/syzcgroup/unified) failed: %d\n", errno);
}
if (!write_file("/syzcgroup/unified/cgroup.subtree_control", "+cpu +memory +io +pids +rdma")) {
debug("write(cgroup.subtree_control) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/cpu", 0777)) {
debug("mkdir(/syzcgroup/cpu) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/cpu", "cgroup", 0, "cpuset,cpuacct,perf_event,hugetlb")) {
debug("mount(cgroup cpu) failed: %d\n", errno);
}
if (!write_file("/syzcgroup/cpu/cgroup.clone_children", "1")) {
debug("write(/syzcgroup/cpu/cgroup.clone_children) failed: %d\n", errno);
}
if (chmod("/syzcgroup/cpu", 0777)) {
debug("chmod(/syzcgroup/cpu) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/net", 0777)) {
debug("mkdir(/syzcgroup/net) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/net", "cgroup", 0, "net_cls,net_prio,devices,freezer")) {
debug("mount(cgroup net) failed: %d\n", errno);
}
if (chmod("/syzcgroup/net", 0777)) {
debug("chmod(/syzcgroup/net) failed: %d\n", errno);
}
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
static void loop();
@ -863,6 +940,9 @@ static int do_sandbox_none(void)
if (pid)
return pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
sandbox_common();
if (unshare(CLONE_NEWNET)) {
debug("unshare(CLONE_NEWNET): %d\n", errno);
@ -889,6 +969,9 @@ static int do_sandbox_setuid(void)
if (pid)
return pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
sandbox_common();
if (unshare(CLONE_NEWNET))
fail("unshare(CLONE_NEWNET)");
@ -916,29 +999,6 @@ static int do_sandbox_setuid(void)
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_FAULT_INJECTION)
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
close(fd);
return false;
}
close(fd);
return true;
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
static int real_uid;
static int real_gid;
@ -994,6 +1054,29 @@ static int namespace_sandbox_proc(void* arg)
if (mount("/sys/fs/selinux", selinux_path, NULL, mount_flags, NULL) && errno != ENOENT)
fail("mount(/sys/fs/selinux) failed");
}
if (mkdir("./syz-tmp/newroot/sys", 0700))
fail("mkdir failed");
if (mount(NULL, "./syz-tmp/newroot/sys", "sysfs", 0, NULL))
fail("mount(sysfs) failed");
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (mkdir("./syz-tmp/newroot/syzcgroup", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700))
fail("mkdir failed");
if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, mount_flags, NULL)) {
debug("mount(cgroup2, MS_BIND) failed: %d\n", errno);
}
if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, mount_flags, NULL)) {
debug("mount(cgroup/cpu, MS_BIND) failed: %d\n", errno);
}
if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, mount_flags, NULL)) {
debug("mount(cgroup/net, MS_BIND) failed: %d\n", errno);
}
#endif
if (mkdir("./syz-tmp/pivot", 0777))
fail("mkdir failed");
if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
@ -1036,6 +1119,9 @@ static int do_sandbox_namespace(void)
{
int pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
real_uid = getuid();
real_gid = getgid();
mprotect(sandbox_stack, 4096, PROT_NONE); // to catch stack underflows
@ -1554,58 +1640,185 @@ static int fault_injected(int fail_fd)
}
#endif
#if defined(SYZ_REPEAT)
static void test();
#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)
static void execute_one();
extern unsigned long long procid;
#if defined(SYZ_WAIT_REPEAT)
void loop()
#if defined(SYZ_EXECUTOR)
void reply_handshake();
void receive_execute(bool need_prog);
void reply_execute(int status);
extern uint32* output_data;
extern uint32* output_pos;
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_WAIT_REPEAT)
static void loop()
{
int iter;
#if defined(SYZ_RESET_NET_NAMESPACE)
#if defined(SYZ_EXECUTOR)
// Tell parent that we are ready to serve.
reply_handshake();
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_RESET_NET_NAMESPACE)
checkpoint_net_namespace();
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
char cgroupdir[64];
snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
char cgroupdir_cpu[64];
snprintf(cgroupdir_cpu, sizeof(cgroupdir_cpu), "/syzcgroup/cpu/syz%llu", procid);
char cgroupdir_net[64];
snprintf(cgroupdir_net, sizeof(cgroupdir_net), "/syzcgroup/net/syz%llu", procid);
#endif
int iter;
for (iter = 0;; iter++) {
#ifdef SYZ_USE_TMP_DIR
char cwdbuf[256];
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
// Create a new private work dir for this test (removed at the end of the loop).
char cwdbuf[32];
sprintf(cwdbuf, "./%d", iter);
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (mkdir(cgroupdir, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
}
if (mkdir(cgroupdir_cpu, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir_cpu, errno);
}
if (mkdir(cgroupdir_net, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir_net, errno);
}
#endif
#if defined(SYZ_EXECUTOR)
// TODO: consider moving the read into the child.
// Potentially it can speed up things a bit -- when the read finishes
// we already have a forked worker process.
receive_execute(false);
#endif
int pid = fork();
if (pid < 0)
fail("loop fork failed");
fail("clone failed");
if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
#ifdef SYZ_USE_TMP_DIR
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
if (chdir(cwdbuf))
fail("failed to chdir");
#endif
#ifdef SYZ_TUN_ENABLE
#if defined(SYZ_EXECUTOR)
close(kInPipeFd);
close(kOutPipeFd);
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (symlink(cgroupdir, "./cgroup")) {
debug("symlink(%s, ./cgroup) failed: %d\n", cgroupdir, errno);
}
if (symlink(cgroupdir_cpu, "./cgroup.cpu")) {
debug("symlink(%s, ./cgroup.cpu) failed: %d\n", cgroupdir_cpu, errno);
}
if (symlink(cgroupdir_net, "./cgroup.net")) {
debug("symlink(%s, ./cgroup.net) failed: %d\n", cgroupdir_net, errno);
}
int pid = getpid();
if (!write_file("./cgroup/cgroup.procs", "%d", pid)) {
debug("write(./cgroup/cgroup.procs) failed: %d\n", errno);
}
if (!write_file("./cgroup.cpu/cgroup.procs", "%d", pid)) {
debug("write(./cgroup.cpu/cgroup.procs) failed: %d\n", errno);
}
if (!write_file("./cgroup.net/cgroup.procs", "%d", pid)) {
debug("write(./cgroup.net/cgroup.procs) failed: %d\n", errno);
}
#endif
#if defined(SYZ_EXECUTOR)
if (flag_enable_tun) {
// Read all remaining packets from tun to better
// isolate consequently executing programs.
flush_tun();
}
output_pos = output_data;
#elif defined(SYZ_TUN_ENABLE)
flush_tun();
#endif
test();
execute_one();
debug("worker exiting\n");
doexit(0);
}
debug("spawned worker pid %d\n", pid);
// We used to use sigtimedwait(SIGCHLD) to wait for the subprocess.
// But SIGCHLD is also delivered when a process stops/continues,
// so it would require a loop with status analysis and timeout recalculation.
// SIGCHLD should also unblock the usleep below, so the spin loop
// should be as efficient as sigtimedwait.
int status = 0;
uint64 start = current_time_ms();
#if defined(SYZ_EXECUTOR)
uint64 last_executed = start;
uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
#endif
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) {
}
if (res == pid) {
debug("waitpid(%d)=%d\n", pid, res);
break;
}
usleep(1000);
#if defined(SYZ_EXECUTOR)
// Even though the test process executes exit at the end
// and execution time of each syscall is bounded by 20ms,
// this backup watchdog is necessary and its performance is important.
// The problem is that exit in the test processes can fail (sic).
// One observed scenario is that the test processes prohibits
// exit_group syscall using seccomp. Another observed scenario
// is that the test processes setups a userfaultfd for itself,
// then the main thread hangs when it wants to page in a page.
// Below we check if the test process still executes syscalls
// and kill it after 200ms of inactivity.
uint64 now = current_time_ms();
uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
if (executed_calls != now_executed) {
executed_calls = now_executed;
last_executed = now;
}
if ((now - start < 3 * 1000) && (now - last_executed < 500))
continue;
#else
if (current_time_ms() - start < 3 * 1000)
continue;
#endif
debug("waitpid(%d)=%d\n", pid, res);
debug("killing\n");
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
while (waitpid(-1, &status, __WALL) != pid) {
}
break;
}
#ifdef SYZ_USE_TMP_DIR
#if defined(SYZ_EXECUTOR)
status = WEXITSTATUS(status);
if (status == kFailStatus)
fail("child failed");
if (status == kErrorStatus)
error("child errored");
reply_execute(0);
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
remove_dir(cwdbuf);
#endif
#if defined(SYZ_RESET_NET_NAMESPACE)
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (rmdir(cgroupdir)) {
debug("rmdir(%s) failed: %d\n", cgroupdir, errno);
}
if (rmdir(cgroupdir_cpu)) {
debug("rmdir(%s) failed: %d\n", cgroupdir_cpu, errno);
}
if (rmdir(cgroupdir_net)) {
debug("rmdir(%s) failed: %d\n", cgroupdir_net, errno);
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_RESET_NET_NAMESPACE)
reset_net_namespace();
#endif
}
@ -1614,7 +1827,7 @@ void loop()
void loop()
{
while (1) {
test();
execute_one();
}
}
#endif

View File

@ -20,10 +20,6 @@
#define GOOS "unknown"
#endif
// Note: zircon max fd is 256.
const int kInPipeFd = 250; // remapped from stdin
const int kOutPipeFd = 251; // remapped from stdout
const int kMaxInput = 2 << 20;
const int kMaxOutput = 16 << 20;
const int kCoverSize = 64 << 10;
@ -67,7 +63,7 @@ bool flag_inject_fault;
int flag_fault_call;
int flag_fault_nth;
int flag_pid;
unsigned long long procid;
int running;
uint32 completed;
@ -226,7 +222,7 @@ void receive_handshake()
if (req.magic != kInMagic)
fail("bad handshake magic 0x%llx", req.magic);
parse_env_flags(req.flags);
flag_pid = req.pid;
procid = req.pid;
}
void reply_handshake()
@ -247,7 +243,7 @@ void receive_execute(bool need_prog)
if (req.prog_size > kMaxInput)
fail("bad execute prog size 0x%llx", req.prog_size);
parse_env_flags(req.env_flags);
flag_pid = req.pid;
procid = req.pid;
flag_collect_cover = req.exec_flags & (1 << 0);
flag_dedup_cover = req.exec_flags & (1 << 1);
flag_inject_fault = req.exec_flags & (1 << 2);
@ -258,8 +254,8 @@ void receive_execute(bool need_prog)
flag_fault_nth = req.fault_nth;
if (!flag_threaded)
flag_collide = false;
debug("exec opts: pid=%d threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu\n",
flag_pid, flag_threaded, flag_collide, flag_collect_cover, flag_collect_comps,
debug("exec opts: pid=%llu threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu\n",
procid, flag_threaded, flag_collide, flag_collect_cover, flag_collect_comps,
flag_dedup_cover, flag_inject_fault, flag_fault_call, flag_fault_nth,
req.prog_size);
if (req.prog_size == 0) {
@ -754,7 +750,7 @@ uint64 read_const_arg(uint64** input_posp, uint64* size_p, uint64* bf_off_p, uin
*bf_off_p = (meta >> 16) & 0xff;
*bf_len_p = (meta >> 24) & 0xff;
uint64 pid_stride = meta >> 32;
val += pid_stride * flag_pid;
val += pid_stride * procid;
if (be) {
switch (*size_p) {
case 2:

View File

@ -119,103 +119,6 @@ int main(int argc, char** argv)
return 1;
}
void loop()
{
// Tell parent that we are ready to serve.
reply_handshake();
checkpoint_net_namespace();
for (int iter = 0;; iter++) {
// Create a new private work dir for this test (removed at the end of the loop).
char cwdbuf[256];
sprintf(cwdbuf, "./%d", iter);
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
// TODO: consider moving the read into the child.
// Potentially it can speed up things a bit -- when the read finishes
// we already have a forked worker process.
receive_execute(false);
int pid = fork();
if (pid < 0)
fail("clone failed");
if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
if (chdir(cwdbuf))
fail("failed to chdir");
close(kInPipeFd);
close(kOutPipeFd);
if (flag_enable_tun) {
// Read all remaining packets from tun to better
// isolate consequently executing programs.
flush_tun();
}
output_pos = output_data;
execute_one();
debug("worker exiting\n");
doexit(0);
}
debug("spawned worker pid %d\n", pid);
// We used to use sigtimedwait(SIGCHLD) to wait for the subprocess.
// But SIGCHLD is also delivered when a process stops/continues,
// so it would require a loop with status analysis and timeout recalculation.
// SIGCHLD should also unblock the usleep below, so the spin loop
// should be as efficient as sigtimedwait.
int status = 0;
uint64 start = current_time_ms();
uint64 last_executed = start;
uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
for (;;) {
int res = waitpid(-1, &status, __WALL | WNOHANG);
int errno0 = errno;
if (res == pid) {
debug("waitpid(%d)=%d (%d)\n", pid, res, errno0);
break;
}
usleep(1000);
// Even though the test process executes exit at the end
// and execution time of each syscall is bounded by 20ms,
// this backup watchdog is necessary and its performance is important.
// The problem is that exit in the test processes can fail (sic).
// One observed scenario is that the test processes prohibits
// exit_group syscall using seccomp. Another observed scenario
// is that the test processes setups a userfaultfd for itself,
// then the main thread hangs when it wants to page in a page.
// Below we check if the test process still executes syscalls
// and kill it after 200ms of inactivity.
uint64 now = current_time_ms();
uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
if (executed_calls != now_executed) {
executed_calls = now_executed;
last_executed = now;
}
if ((now - start < 3 * 1000) && (now - last_executed < 500))
continue;
debug("waitpid(%d)=%d (%d)\n", pid, res, errno0);
debug("killing\n");
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (;;) {
int res = waitpid(-1, &status, __WALL);
debug("waitpid(%d)=%d (%d)\n", pid, res, errno);
if (res == pid)
break;
}
break;
}
status = WEXITSTATUS(status);
if (status == kFailStatus)
fail("child failed");
if (status == kErrorStatus)
error("child errored");
reply_execute(0);
remove_dir(cwdbuf);
reset_net_namespace();
}
}
long execute_syscall(call_t* c, long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8)
{
if (c->call)

View File

@ -2,11 +2,11 @@
#if defined(__i386__) || 0
#define GOARCH "386"
#define SYZ_REVISION "b0cca0943b5017ba63ed5e3b325251612d061f21"
#define SYZ_REVISION "c01f41f1487f5d5a5b0104b876d11c9af1090248"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1613;
unsigned syscall_count = 1626;
call_t syscalls[] = {
{"accept4", 364},
{"accept4$alg", 364},
@ -991,6 +991,7 @@ call_t syscalls[] = {
{"mincore", 218},
{"mkdir", 39},
{"mkdirat", 296},
{"mkdirat$cgroup", 296},
{"mknod", 14},
{"mknod$loop", 14},
{"mknodat", 297},
@ -1027,6 +1028,13 @@ call_t syscalls[] = {
{"openat$audio", 295},
{"openat$autofs", 295},
{"openat$capi20", 295},
{"openat$cgroup", 295},
{"openat$cgroup_int", 295},
{"openat$cgroup_procs", 295},
{"openat$cgroup_ro", 295},
{"openat$cgroup_root", 295},
{"openat$cgroup_subtree", 295},
{"openat$cgroup_type", 295},
{"openat$cuse", 295},
{"openat$dir", 295},
{"openat$dsp", 295},
@ -1080,6 +1088,7 @@ call_t syscalls[] = {
{"openat$zygote", 295},
{"pause", 29},
{"perf_event_open", 336},
{"perf_event_open$cgroup", 336},
{"personality", 136},
{"pipe", 42},
{"pipe2", 331},
@ -1607,6 +1616,10 @@ call_t syscalls[] = {
{"wait4", 114},
{"waitid", 284},
{"write", 4},
{"write$cgroup_int", 4},
{"write$cgroup_pid", 4},
{"write$cgroup_subtree", 4},
{"write$cgroup_type", 4},
{"write$evdev", 4},
{"write$eventfd", 4},
{"write$fuse", 4},
@ -1627,11 +1640,11 @@ call_t syscalls[] = {
#if defined(__x86_64__) || 0
#define GOARCH "amd64"
#define SYZ_REVISION "c4e271d66e2dfd758cf369682d72bbf3590dedd0"
#define SYZ_REVISION "b9c8e658cfa4e7d66e21b0a6c1fcddfe61acbeb2"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1665;
unsigned syscall_count = 1678;
call_t syscalls[] = {
{"accept", 43},
{"accept$alg", 43},
@ -2630,6 +2643,7 @@ call_t syscalls[] = {
{"mincore", 27},
{"mkdir", 83},
{"mkdirat", 258},
{"mkdirat$cgroup", 258},
{"mknod", 133},
{"mknod$loop", 133},
{"mknodat", 259},
@ -2676,6 +2690,13 @@ call_t syscalls[] = {
{"openat$audio", 257},
{"openat$autofs", 257},
{"openat$capi20", 257},
{"openat$cgroup", 257},
{"openat$cgroup_int", 257},
{"openat$cgroup_procs", 257},
{"openat$cgroup_ro", 257},
{"openat$cgroup_root", 257},
{"openat$cgroup_subtree", 257},
{"openat$cgroup_type", 257},
{"openat$cuse", 257},
{"openat$dir", 257},
{"openat$dsp", 257},
@ -2729,6 +2750,7 @@ call_t syscalls[] = {
{"openat$zygote", 257},
{"pause", 34},
{"perf_event_open", 298},
{"perf_event_open$cgroup", 298},
{"personality", 135},
{"pipe", 22},
{"pipe2", 293},
@ -3284,6 +3306,10 @@ call_t syscalls[] = {
{"wait4", 61},
{"waitid", 247},
{"write", 1},
{"write$cgroup_int", 1},
{"write$cgroup_pid", 1},
{"write$cgroup_subtree", 1},
{"write$cgroup_type", 1},
{"write$evdev", 1},
{"write$eventfd", 1},
{"write$fuse", 1},
@ -3304,11 +3330,11 @@ call_t syscalls[] = {
#if defined(__arm__) || 0
#define GOARCH "arm"
#define SYZ_REVISION "07cef835f8b609cd2ffca0b97f77fa531c570b71"
#define SYZ_REVISION "e7d1c116b96d76e3529774adf2b448f8717b76eb"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1610;
unsigned syscall_count = 1623;
call_t syscalls[] = {
{"accept", 285},
{"accept$alg", 285},
@ -4264,6 +4290,7 @@ call_t syscalls[] = {
{"mincore", 219},
{"mkdir", 39},
{"mkdirat", 323},
{"mkdirat$cgroup", 323},
{"mknod", 14},
{"mknod$loop", 14},
{"mknodat", 324},
@ -4306,6 +4333,13 @@ call_t syscalls[] = {
{"openat$audio", 322},
{"openat$autofs", 322},
{"openat$capi20", 322},
{"openat$cgroup", 322},
{"openat$cgroup_int", 322},
{"openat$cgroup_procs", 322},
{"openat$cgroup_ro", 322},
{"openat$cgroup_root", 322},
{"openat$cgroup_subtree", 322},
{"openat$cgroup_type", 322},
{"openat$cuse", 322},
{"openat$dir", 322},
{"openat$dsp", 322},
@ -4359,6 +4393,7 @@ call_t syscalls[] = {
{"openat$zygote", 322},
{"pause", 29},
{"perf_event_open", 364},
{"perf_event_open$cgroup", 364},
{"personality", 136},
{"pipe", 42},
{"pipe2", 359},
@ -4906,6 +4941,10 @@ call_t syscalls[] = {
{"wait4", 114},
{"waitid", 280},
{"write", 4},
{"write$cgroup_int", 4},
{"write$cgroup_pid", 4},
{"write$cgroup_subtree", 4},
{"write$cgroup_type", 4},
{"write$evdev", 4},
{"write$eventfd", 4},
{"write$fuse", 4},
@ -4926,11 +4965,11 @@ call_t syscalls[] = {
#if defined(__aarch64__) || 0
#define GOARCH "arm64"
#define SYZ_REVISION "cac26d4197832d1b50b8b6ea469c8061b7405bc4"
#define SYZ_REVISION "43a2d759c153cf5c6b39a47c64efd7abcf669c26"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1594;
unsigned syscall_count = 1607;
call_t syscalls[] = {
{"accept", 202},
{"accept$alg", 202},
@ -5886,6 +5925,7 @@ call_t syscalls[] = {
{"migrate_pages", 238},
{"mincore", 232},
{"mkdirat", 34},
{"mkdirat$cgroup", 34},
{"mknodat", 33},
{"mlock", 228},
{"mlock2", 284},
@ -5924,6 +5964,13 @@ call_t syscalls[] = {
{"openat$audio", 56},
{"openat$autofs", 56},
{"openat$capi20", 56},
{"openat$cgroup", 56},
{"openat$cgroup_int", 56},
{"openat$cgroup_procs", 56},
{"openat$cgroup_ro", 56},
{"openat$cgroup_root", 56},
{"openat$cgroup_subtree", 56},
{"openat$cgroup_type", 56},
{"openat$cuse", 56},
{"openat$dir", 56},
{"openat$dsp", 56},
@ -5976,6 +6023,7 @@ call_t syscalls[] = {
{"openat$xenevtchn", 56},
{"openat$zygote", 56},
{"perf_event_open", 241},
{"perf_event_open$cgroup", 241},
{"personality", 92},
{"pipe2", 59},
{"pivot_root", 41},
@ -6512,6 +6560,10 @@ call_t syscalls[] = {
{"wait4", 260},
{"waitid", 95},
{"write", 64},
{"write$cgroup_int", 64},
{"write$cgroup_pid", 64},
{"write$cgroup_subtree", 64},
{"write$cgroup_type", 64},
{"write$evdev", 64},
{"write$eventfd", 64},
{"write$fuse", 64},
@ -6532,11 +6584,11 @@ call_t syscalls[] = {
#if defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || 0
#define GOARCH "ppc64le"
#define SYZ_REVISION "d32421a63a0dd72f857a8cb4cdc483487132c60a"
#define SYZ_REVISION "b84bf7ffe358a4f0f2e3375c1421e3e3dd5da519"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1584;
unsigned syscall_count = 1597;
call_t syscalls[] = {
{"accept", 330},
{"accept$alg", 330},
@ -7495,6 +7547,7 @@ call_t syscalls[] = {
{"mincore", 206},
{"mkdir", 39},
{"mkdirat", 287},
{"mkdirat$cgroup", 287},
{"mknod", 14},
{"mknod$loop", 14},
{"mknodat", 288},
@ -7531,6 +7584,13 @@ call_t syscalls[] = {
{"openat$audio", 286},
{"openat$autofs", 286},
{"openat$capi20", 286},
{"openat$cgroup", 286},
{"openat$cgroup_int", 286},
{"openat$cgroup_procs", 286},
{"openat$cgroup_ro", 286},
{"openat$cgroup_root", 286},
{"openat$cgroup_subtree", 286},
{"openat$cgroup_type", 286},
{"openat$cuse", 286},
{"openat$dir", 286},
{"openat$dsp", 286},
@ -7584,6 +7644,7 @@ call_t syscalls[] = {
{"openat$zygote", 286},
{"pause", 29},
{"perf_event_open", 319},
{"perf_event_open$cgroup", 319},
{"personality", 136},
{"pipe", 42},
{"pipe2", 317},
@ -8108,6 +8169,10 @@ call_t syscalls[] = {
{"wait4", 114},
{"waitid", 272},
{"write", 4},
{"write$cgroup_int", 4},
{"write$cgroup_pid", 4},
{"write$cgroup_subtree", 4},
{"write$cgroup_type", 4},
{"write$evdev", 4},
{"write$eventfd", 4},
{"write$fuse", 4},

View File

@ -8,10 +8,6 @@
#include <sys/utsname.h>
void loop()
{
} // to prevent warning: void loop() used but never defined
extern "C" int test_copyin()
{
unsigned char x[4] = {};

View File

@ -78,6 +78,11 @@ typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef SYZ_EXECUTOR
const int kInPipeFd = 250;
const int kOutPipeFd = 251;
#endif
#if defined(__GNUC__)
#define SYSCALLAPI
#define NORETURN __attribute__((noreturn))

View File

@ -89,6 +89,9 @@ func defineList(p *prog.Prog, opts Options) ([]string, error) {
if opts.EnableTun {
defines = append(defines, "SYZ_TUN_ENABLE")
}
if opts.EnableCgroups {
defines = append(defines, "SYZ_ENABLE_CGROUPS")
}
if opts.UseTmpDir {
defines = append(defines, "SYZ_USE_TMP_DIR")
}

View File

@ -63,8 +63,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
}
ctx.printf("};\n")
}
if opts.Procs > 1 {
ctx.printf("uint64_t procid;\n")
if opts.Procs > 1 || opts.EnableCgroups {
ctx.printf("unsigned long long procid;\n")
}
if !opts.Repeat {
@ -93,7 +93,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
}
ctx.print("\treturn 0;\n}\n")
} else {
ctx.generateTestFunc(calls, len(vars) != 0, "test")
ctx.generateTestFunc(calls, len(vars) != 0, "execute_one")
if opts.Procs <= 1 {
ctx.print("int main()\n{\n")
for _, c := range mmapCalls {

View File

@ -89,6 +89,7 @@ func TestGenerateOptions(t *testing.T) {
permutations = allPermutations
}
for i, opts := range permutations {
opts := opts
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
target, rs, iters := initTest(t)
t.Logf("opts: %+v", opts)

View File

@ -69,6 +69,11 @@ typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef SYZ_EXECUTOR
const int kInPipeFd = 250;
const int kOutPipeFd = 251;
#endif
#if defined(__GNUC__)
#define SYSCALLAPI
#define NORETURN __attribute__((noreturn))

View File

@ -44,15 +44,20 @@ var commonHeaderLinux = `
#include <sys/time.h>
#include <sys/wait.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) || defined(SYZ_SANDBOX_NAMESPACE) || \
defined(SYZ_ENABLE_CGROUPS)
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID)
#include <grp.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
#include <fcntl.h>
#include <linux/capability.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE)
#include <arpa/inet.h>
@ -121,11 +126,15 @@ var commonHeaderLinux = `
#include <unistd.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_genetlink_get_family_id)
#include <errno.h>
#include <linux/genetlink.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
#include <sys/mount.h>
#endif
#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \
defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \
@ -176,6 +185,11 @@ typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef SYZ_EXECUTOR
const int kInPipeFd = 250;
const int kOutPipeFd = 251;
#endif
#if defined(__GNUC__)
#define SYSCALLAPI
#define NORETURN __attribute__((noreturn))
@ -1857,6 +1871,74 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin
#endif
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) || defined(SYZ_SANDBOX_NAMESPACE) || \
defined(SYZ_ENABLE_CGROUPS)
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
static void setup_cgroups()
{
if (mkdir("/syzcgroup", 0777)) {
debug("mkdir(/syzcgroup) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/unified", 0777)) {
debug("mkdir(/syzcgroup/unified) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/unified", "cgroup2", 0, NULL)) {
debug("mount(cgroup2) failed: %d\n", errno);
}
if (chmod("/syzcgroup/unified", 0777)) {
debug("chmod(/syzcgroup/unified) failed: %d\n", errno);
}
if (!write_file("/syzcgroup/unified/cgroup.subtree_control", "+cpu +memory +io +pids +rdma")) {
debug("write(cgroup.subtree_control) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/cpu", 0777)) {
debug("mkdir(/syzcgroup/cpu) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/cpu", "cgroup", 0, "cpuset,cpuacct,perf_event,hugetlb")) {
debug("mount(cgroup cpu) failed: %d\n", errno);
}
if (!write_file("/syzcgroup/cpu/cgroup.clone_children", "1")) {
debug("write(/syzcgroup/cpu/cgroup.clone_children) failed: %d\n", errno);
}
if (chmod("/syzcgroup/cpu", 0777)) {
debug("chmod(/syzcgroup/cpu) failed: %d\n", errno);
}
if (mkdir("/syzcgroup/net", 0777)) {
debug("mkdir(/syzcgroup/net) failed: %d\n", errno);
}
if (mount("none", "/syzcgroup/net", "cgroup", 0, "net_cls,net_prio,devices,freezer")) {
debug("mount(cgroup net) failed: %d\n", errno);
}
if (chmod("/syzcgroup/net", 0777)) {
debug("chmod(/syzcgroup/net) failed: %d\n", errno);
}
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE)
static void loop();
@ -1921,6 +2003,9 @@ static int do_sandbox_none(void)
if (pid)
return pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
sandbox_common();
if (unshare(CLONE_NEWNET)) {
debug("unshare(CLONE_NEWNET): %d\n", errno);
@ -1946,6 +2031,9 @@ static int do_sandbox_setuid(void)
if (pid)
return pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
sandbox_common();
if (unshare(CLONE_NEWNET))
fail("unshare(CLONE_NEWNET)");
@ -1969,29 +2057,6 @@ static int do_sandbox_setuid(void)
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_FAULT_INJECTION)
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
close(fd);
return false;
}
close(fd);
return true;
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE)
static int real_uid;
static int real_gid;
@ -2038,6 +2103,29 @@ static int namespace_sandbox_proc(void* arg)
if (mount("/sys/fs/selinux", selinux_path, NULL, mount_flags, NULL) && errno != ENOENT)
fail("mount(/sys/fs/selinux) failed");
}
if (mkdir("./syz-tmp/newroot/sys", 0700))
fail("mkdir failed");
if (mount(NULL, "./syz-tmp/newroot/sys", "sysfs", 0, NULL))
fail("mount(sysfs) failed");
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (mkdir("./syz-tmp/newroot/syzcgroup", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700))
fail("mkdir failed");
if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700))
fail("mkdir failed");
if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, mount_flags, NULL)) {
debug("mount(cgroup2, MS_BIND) failed: %d\n", errno);
}
if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, mount_flags, NULL)) {
debug("mount(cgroup/cpu, MS_BIND) failed: %d\n", errno);
}
if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, mount_flags, NULL)) {
debug("mount(cgroup/net, MS_BIND) failed: %d\n", errno);
}
#endif
if (mkdir("./syz-tmp/pivot", 0777))
fail("mkdir failed");
if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
@ -2076,6 +2164,9 @@ static int do_sandbox_namespace(void)
{
int pid;
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
setup_cgroups();
#endif
real_uid = getuid();
real_gid = getgid();
mprotect(sandbox_stack, 4096, PROT_NONE);
@ -2577,58 +2668,163 @@ static int fault_injected(int fail_fd)
}
#endif
#if defined(SYZ_REPEAT)
static void test();
#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)
static void execute_one();
extern unsigned long long procid;
#if defined(SYZ_WAIT_REPEAT)
void loop()
#if defined(SYZ_EXECUTOR)
void reply_handshake();
void receive_execute(bool need_prog);
void reply_execute(int status);
extern uint32* output_data;
extern uint32* output_pos;
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_WAIT_REPEAT)
static void loop()
{
int iter;
#if defined(SYZ_RESET_NET_NAMESPACE)
#if defined(SYZ_EXECUTOR)
reply_handshake();
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_RESET_NET_NAMESPACE)
checkpoint_net_namespace();
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
char cgroupdir[64];
snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
char cgroupdir_cpu[64];
snprintf(cgroupdir_cpu, sizeof(cgroupdir_cpu), "/syzcgroup/cpu/syz%llu", procid);
char cgroupdir_net[64];
snprintf(cgroupdir_net, sizeof(cgroupdir_net), "/syzcgroup/net/syz%llu", procid);
#endif
int iter;
for (iter = 0;; iter++) {
#ifdef SYZ_USE_TMP_DIR
char cwdbuf[256];
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
char cwdbuf[32];
sprintf(cwdbuf, "./%d", iter);
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (mkdir(cgroupdir, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
}
if (mkdir(cgroupdir_cpu, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir_cpu, errno);
}
if (mkdir(cgroupdir_net, 0777)) {
debug("mkdir(%s) failed: %d\n", cgroupdir_net, errno);
}
#endif
#if defined(SYZ_EXECUTOR)
receive_execute(false);
#endif
int pid = fork();
if (pid < 0)
fail("loop fork failed");
fail("clone failed");
if (pid == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
#ifdef SYZ_USE_TMP_DIR
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
if (chdir(cwdbuf))
fail("failed to chdir");
#endif
#ifdef SYZ_TUN_ENABLE
#if defined(SYZ_EXECUTOR)
close(kInPipeFd);
close(kOutPipeFd);
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (symlink(cgroupdir, "./cgroup")) {
debug("symlink(%s, ./cgroup) failed: %d\n", cgroupdir, errno);
}
if (symlink(cgroupdir_cpu, "./cgroup.cpu")) {
debug("symlink(%s, ./cgroup.cpu) failed: %d\n", cgroupdir_cpu, errno);
}
if (symlink(cgroupdir_net, "./cgroup.net")) {
debug("symlink(%s, ./cgroup.net) failed: %d\n", cgroupdir_net, errno);
}
int pid = getpid();
if (!write_file("./cgroup/cgroup.procs", "%d", pid)) {
debug("write(./cgroup/cgroup.procs) failed: %d\n", errno);
}
if (!write_file("./cgroup.cpu/cgroup.procs", "%d", pid)) {
debug("write(./cgroup.cpu/cgroup.procs) failed: %d\n", errno);
}
if (!write_file("./cgroup.net/cgroup.procs", "%d", pid)) {
debug("write(./cgroup.net/cgroup.procs) failed: %d\n", errno);
}
#endif
#if defined(SYZ_EXECUTOR)
if (flag_enable_tun) {
flush_tun();
}
output_pos = output_data;
#elif defined(SYZ_TUN_ENABLE)
flush_tun();
#endif
test();
execute_one();
debug("worker exiting\n");
doexit(0);
}
debug("spawned worker pid %d\n", pid);
int status = 0;
uint64 start = current_time_ms();
#if defined(SYZ_EXECUTOR)
uint64 last_executed = start;
uint32 executed_calls = __atomic_load_n(output_data, __ATOMIC_RELAXED);
#endif
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) {
}
if (res == pid) {
debug("waitpid(%d)=%d\n", pid, res);
break;
}
usleep(1000);
#if defined(SYZ_EXECUTOR)
uint64 now = current_time_ms();
uint32 now_executed = __atomic_load_n(output_data, __ATOMIC_RELAXED);
if (executed_calls != now_executed) {
executed_calls = now_executed;
last_executed = now;
}
if ((now - start < 3 * 1000) && (now - last_executed < 500))
continue;
#else
if (current_time_ms() - start < 3 * 1000)
continue;
#endif
debug("waitpid(%d)=%d\n", pid, res);
debug("killing\n");
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
while (waitpid(-1, &status, __WALL) != pid) {
}
break;
}
#ifdef SYZ_USE_TMP_DIR
#if defined(SYZ_EXECUTOR)
status = WEXITSTATUS(status);
if (status == kFailStatus)
fail("child failed");
if (status == kErrorStatus)
error("child errored");
reply_execute(0);
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
remove_dir(cwdbuf);
#endif
#if defined(SYZ_RESET_NET_NAMESPACE)
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
if (rmdir(cgroupdir)) {
debug("rmdir(%s) failed: %d\n", cgroupdir, errno);
}
if (rmdir(cgroupdir_cpu)) {
debug("rmdir(%s) failed: %d\n", cgroupdir_cpu, errno);
}
if (rmdir(cgroupdir_net)) {
debug("rmdir(%s) failed: %d\n", cgroupdir_net, errno);
}
#endif
#if defined(SYZ_EXECUTOR) || defined(SYZ_RESET_NET_NAMESPACE)
reset_net_namespace();
#endif
}
@ -2637,7 +2833,7 @@ void loop()
void loop()
{
while (1) {
test();
execute_one();
}
}
#endif

View File

@ -69,6 +69,11 @@ typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef SYZ_EXECUTOR
const int kInPipeFd = 250;
const int kOutPipeFd = 251;
#endif
#if defined(__GNUC__)
#define SYSCALLAPI
#define NORETURN __attribute__((noreturn))

View File

@ -23,11 +23,12 @@ type Options struct {
FaultNth int
// These options allow for a more fine-tuned control over the generated C code.
EnableTun bool
UseTmpDir bool
HandleSegv bool
WaitRepeat bool
Debug bool
EnableTun bool
UseTmpDir bool
EnableCgroups bool
HandleSegv bool
WaitRepeat bool
Debug bool
// Generate code for use with repro package to prints log messages,
// which allows to distinguish between a hang and an absent crash.
@ -55,6 +56,15 @@ func (opts Options) Check() error {
// which will fail if procs>1 and on second run of the program.
return errors.New("Sandbox=namespace without UseTmpDir")
}
if opts.EnableTun && opts.Sandbox == "" {
return errors.New("EnableTun without sandbox")
}
if opts.EnableCgroups && opts.Sandbox == "" {
return errors.New("EnableCgroups without sandbox")
}
if opts.EnableCgroups && !opts.UseTmpDir {
return errors.New("EnableCgroups without UseTmpDir")
}
return nil
}
@ -72,14 +82,30 @@ func DeserializeOptions(data []byte) (Options, error) {
&opts.Threaded, &opts.Collide, &opts.Repeat, &opts.Procs, &opts.Sandbox,
&opts.Fault, &opts.FaultCall, &opts.FaultNth, &opts.EnableTun, &opts.UseTmpDir,
&opts.HandleSegv, &opts.WaitRepeat, &opts.Debug, &opts.Repro)
if err != nil {
return opts, fmt.Errorf("failed to parse repro options: %v", err)
if err == nil {
if want := 14; n != want {
return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
}
if opts.Sandbox == "empty" {
opts.Sandbox = ""
}
return opts, nil
}
if want := 14; n != want {
return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
n, err = fmt.Sscanf(string(data),
"{Threaded:%t Collide:%t Repeat:%t Procs:%d Sandbox:%s"+
" Fault:%t FaultCall:%d FaultNth:%d EnableTun:%t UseTmpDir:%t"+
" EnableCgroups:%t HandleSegv:%t WaitRepeat:%t Debug:%t Repro:%t}",
&opts.Threaded, &opts.Collide, &opts.Repeat, &opts.Procs, &opts.Sandbox,
&opts.Fault, &opts.FaultCall, &opts.FaultNth, &opts.EnableTun, &opts.UseTmpDir,
&opts.EnableCgroups, &opts.HandleSegv, &opts.WaitRepeat, &opts.Debug, &opts.Repro)
if err == nil {
if want := 15; n != want {
return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
}
if opts.Sandbox == "empty" {
opts.Sandbox = ""
}
return opts, nil
}
if opts.Sandbox == "empty" {
opts.Sandbox = ""
}
return opts, nil
return opts, err
}

View File

@ -29,36 +29,55 @@ func TestParseOptionsCanned(t *testing.T) {
// so we need to be able to parse old formats.
canned := map[string]Options{
"{Threaded:true Collide:true Repeat:true Procs:1 Sandbox:none Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": Options{
Threaded: true,
Collide: true,
Repeat: true,
Procs: 1,
Sandbox: "none",
Fault: false,
FaultCall: -1,
FaultNth: 0,
EnableTun: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Debug: false,
Repro: false,
Threaded: true,
Collide: true,
Repeat: true,
Procs: 1,
Sandbox: "none",
Fault: false,
FaultCall: -1,
FaultNth: 0,
EnableTun: true,
UseTmpDir: true,
EnableCgroups: false,
HandleSegv: true,
WaitRepeat: true,
Debug: false,
Repro: false,
},
"{Threaded:true Collide:true Repeat:true Procs:1 Sandbox: Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": Options{
Threaded: true,
Collide: true,
Repeat: true,
Procs: 1,
Sandbox: "",
Fault: false,
FaultCall: -1,
FaultNth: 0,
EnableTun: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Debug: false,
Repro: false,
Threaded: true,
Collide: true,
Repeat: true,
Procs: 1,
Sandbox: "",
Fault: false,
FaultCall: -1,
FaultNth: 0,
EnableTun: true,
UseTmpDir: true,
EnableCgroups: false,
HandleSegv: true,
WaitRepeat: true,
Debug: false,
Repro: false,
},
"{Threaded:false Collide:true Repeat:true Procs:1 Sandbox:namespace Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true EnableCgroups:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": Options{
Threaded: false,
Collide: true,
Repeat: true,
Procs: 1,
Sandbox: "namespace",
Fault: false,
FaultCall: -1,
FaultNth: 0,
EnableTun: true,
UseTmpDir: true,
EnableCgroups: true,
HandleSegv: true,
WaitRepeat: true,
Debug: false,
Repro: false,
},
}
for data, want := range canned {
@ -76,7 +95,15 @@ func allOptionsSingle() []Options {
var opts []Options
fields := reflect.TypeOf(Options{}).NumField()
for i := 0; i < fields; i++ {
opts = append(opts, enumerateField(Options{}, i)...)
// Because of constraints on options, we need some defaults
// (e.g. no collide without threaded).
opt := Options{
Threaded: true,
Repeat: true,
Sandbox: "none",
UseTmpDir: true,
}
opts = append(opts, enumerateField(opt, i)...)
}
return opts
}

View File

@ -155,7 +155,7 @@ func isSupportedSocket(c *prog.Syscall) bool {
func isSupportedOpenAt(c *prog.Syscall) bool {
fname, ok := extractStringConst(c.Args[1])
if !ok {
if !ok || len(fname) == 0 || fname[0] != '/' {
return true
}
fd, err := syscall.Open(fname, syscall.O_RDONLY, 0)

View File

@ -41,6 +41,7 @@ for i in {0..31}; do
echo "KERNEL==\"binder$i\", NAME=\"binder$i\", MODE=\"0666\"" | \
tee -a disk.mnt/etc/udev/50-binder.rules
done
echo 'SELINUX=disabled' | sudo tee disk.mnt/etc/selinux/config
echo "kernel.printk = 7 4 1 3" | sudo tee -a disk.mnt/etc/sysctl.conf
echo "debug.exception-trace = 0" | sudo tee -a disk.mnt/etc/sysctl.conf

View File

@ -291,16 +291,17 @@ func (ctx *context) extractProg(entries []*prog.LogEntry) (*Result, error) {
func (ctx *context) createDefaultOps() csource.Options {
opts := csource.Options{
Threaded: true,
Collide: true,
Repeat: true,
Procs: ctx.cfg.Procs,
Sandbox: ctx.cfg.Sandbox,
EnableTun: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Repro: true,
Threaded: true,
Collide: true,
Repeat: true,
Procs: ctx.cfg.Procs,
Sandbox: ctx.cfg.Sandbox,
EnableTun: true,
EnableCgroups: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Repro: true,
}
return opts
}
@ -816,6 +817,8 @@ var cSimplifies = append(progSimplifies, []Simplify{
return false
}
opts.Sandbox = ""
opts.EnableTun = false
opts.EnableCgroups = false
return true
},
func(opts *csource.Options) bool {
@ -826,7 +829,14 @@ var cSimplifies = append(progSimplifies, []Simplify{
return true
},
func(opts *csource.Options) bool {
if !opts.UseTmpDir || opts.Sandbox == "namespace" {
if !opts.EnableCgroups {
return false
}
opts.EnableCgroups = false
return true
},
func(opts *csource.Options) bool {
if !opts.UseTmpDir || opts.Sandbox == "namespace" || opts.EnableCgroups {
return false
}
opts.UseTmpDir = false

View File

@ -67,16 +67,17 @@ func TestBisect(t *testing.T) {
func TestSimplifies(t *testing.T) {
opts := csource.Options{
Threaded: true,
Collide: true,
Repeat: true,
Procs: 10,
Sandbox: "namespace",
EnableTun: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Repro: true,
Threaded: true,
Collide: true,
Repeat: true,
Procs: 10,
Sandbox: "namespace",
EnableTun: true,
EnableCgroups: true,
UseTmpDir: true,
HandleSegv: true,
WaitRepeat: true,
Repro: true,
}
var check func(opts csource.Options, i int)
check = func(opts csource.Options, i int) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -267,8 +267,7 @@ bpf_obj_get {
}
bpf_attach_arg {
# TODO: this must be cgroup fd (obtained by opening cgroup dir)
target_fd fd
target_fd fd_cgroup
attach_bpf_fd fd_bpf_prog
type flags[bpf_attach_type, int32]
flags flags[bpf_attach_flags, int32]
@ -331,8 +330,7 @@ bpf_map_info {
} [align_8]
bpf_prog_query {
# TODO: this must be cgroup fd (obtained by opening cgroup dir)
target_fd fd
target_fd fd_cgroup
attach_type flags[bpf_prog_query_attach_type, int32]
query_flags flags[bpf_prog_query_flags, int32]
attach_flags int32

56
sys/linux/cgroup.txt Normal file
View File

@ -0,0 +1,56 @@
# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
include <uapi/linux/fcntl.h>
resource fd_cgroup[fd]
resource fd_cgroup_type[fd]
resource fd_cgroup_subtree[fd]
resource fd_cgroup_int[fd]
resource fd_cgroup_pid[fd]
openat$cgroup_root(fd const[AT_FDCWD], file ptr[in, string[cgroup_dirs]], flags const[CGROUP_OPEN_FLAGS], mode const[0]) fd_cgroup
openat$cgroup(fd fd_cgroup, file ptr[in, string[cgroup_names]], flags const[CGROUP_OPEN_FLAGS], mode const[0]) fd_cgroup
mkdirat$cgroup(fd fd_cgroup, path ptr[in, string[cgroup_names]], mode flags[open_mode])
openat$cgroup_ro(fd fd_cgroup, file ptr[in, string[cgroup_ctrl_read]], flags const[O_RDONLY], mode const[0]) fd
openat$cgroup_int(fd fd_cgroup, file ptr[in, string[cgroup_ctrl_int]], flags const[O_RDWR], mode const[0]) fd_cgroup_int
openat$cgroup_procs(fd fd_cgroup, file ptr[in, string[cgroup_proc_files]], flags const[O_RDWR], mode const[0]) fd_cgroup_pid
openat$cgroup_subtree(fd fd_cgroup, file ptr[in, string["cgroup.subtree_control"]], flags const[O_RDWR], mode const[0]) fd_cgroup_subtree
openat$cgroup_type(fd fd_cgroup, file ptr[in, string["cgroup.type"]], flags const[O_RDWR], mode const[0]) fd_cgroup_type
write$cgroup_int(fd fd_cgroup_int, buf ptr[in, cgroup_int], len bytesize[buf])
write$cgroup_pid(fd fd_cgroup_pid, buf ptr[in, cgroup_pid], len bytesize[buf])
write$cgroup_subtree(fd fd_cgroup_subtree, buf ptr[in, cgroup_subtree], len bytesize[buf])
write$cgroup_type(fd fd_cgroup_type, buf ptr[in, string["threaded"]], len bytesize[buf])
cgroup_int {
digits array[flags[cgroup_digits, int8]]
} [packed]
# TODO: these are bad pid's. We need something like sprintf["%v", pid].
cgroup_pid {
digits array[int8[48:57]]
} [packed]
cgroup_subtree {
controls array[cgroup_control]
} [packed]
cgroup_control {
sign flags[cgroup_control_signs, int8]
subsys stringnoz[cgroup_subsystems]
sp const[32, int8]
} [packed]
cgroup_dirs = "./cgroup", "./cgroup.cpu", "./cgroup.net"
cgroup_names = "syz0", "syz1"
cgroup_paths = "./cgroup", "./cgroup.cpu", "./cgroup.net", "./cgroup/syz0", "./cgroup.cpu/syz0", "./cgroup.net/syz0", "./cgroup/syz1", "./cgroup.cpu/syz1", "./cgroup.net/syz1"
# '+', '-'
cgroup_control_signs = 43, 45
# '+', '-', ',', '/', ';' and digits
cgroup_digits = 0, 43, 45, 44, 47, 58, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
cgroup_subsystems = "cpu", "memory", "io", "pids", "rdma"
cgroup_proc_files = "cgroup.procs", "cgroup.threads", "tasks"
cgroup_ctrl_read = "cgroup.controllers", "cgroup.events", "cgroup.stat", "cpu.stat", "cpu.stat", "io.stat", "memory.current", "memory.events", "memory.stat", "memory.swap.current", "pids.current", "pids.events", "rdma.current", "cpuacct.stat", "cpuacct.usage_all", "cpuacct.usage_percpu", "cpuacct.usage_percpu_sys", "cpuacct.usage_percpu_user", "cpuacct.usage_sys", "cpuacct.usage_user", "cpuset.effective_cpus", "cpuset.effective_mems", "cpuset.memory_pressure", "hugetlb.2MB.usage_in_bytes"
cgroup_ctrl_int = "cgroup.max.depth", "cgroup.max.descendants", "cpu.weight", "cpu.weight.nice", "io.bfq.weight", "io.max", "io.weight", "memory.high", "memory.low", "memory.max", "memory.swap.max", "pids.max", "rdma.max", "cgroup.clone_children", "cpuacct.usage", "cpuset.cpu_exclusive", "cpuset.cpus", "cpuset.mem_exclusive", "cpuset.mem_hardwall", "cpuset.memory_migrate", "cpuset.memory_spread_page", "cpuset.memory_spread_slab", "cpuset.mems", "cpuset.sched_load_balance", "cpuset.sched_relax_domain_level", "hugetlb.2MB.failcnt", "hugetlb.2MB.limit_in_bytes", "hugetlb.2MB.max_usage_in_bytes", "notify_on_release"
define CGROUP_OPEN_FLAGS O_RDWR | O_PATH

View File

@ -0,0 +1,8 @@
# AUTOGENERATED FILE
AT_FDCWD = 18446744073709551516
CGROUP_OPEN_FLAGS = 2097154
O_RDONLY = 0
O_RDWR = 2
__NR_mkdirat = 296
__NR_openat = 295
__NR_write = 4

View File

@ -0,0 +1,8 @@
# AUTOGENERATED FILE
AT_FDCWD = 18446744073709551516
CGROUP_OPEN_FLAGS = 2097154
O_RDONLY = 0
O_RDWR = 2
__NR_mkdirat = 258
__NR_openat = 257
__NR_write = 1

View File

@ -0,0 +1,8 @@
# AUTOGENERATED FILE
AT_FDCWD = 18446744073709551516
CGROUP_OPEN_FLAGS = 2097154
O_RDONLY = 0
O_RDWR = 2
__NR_mkdirat = 323
__NR_openat = 322
__NR_write = 4

View File

@ -0,0 +1,8 @@
# AUTOGENERATED FILE
AT_FDCWD = 18446744073709551516
CGROUP_OPEN_FLAGS = 2097154
O_RDONLY = 0
O_RDWR = 2
__NR_mkdirat = 34
__NR_openat = 56
__NR_write = 64

View File

@ -0,0 +1,8 @@
# AUTOGENERATED FILE
AT_FDCWD = 18446744073709551516
CGROUP_OPEN_FLAGS = 2097154
O_RDONLY = 0
O_RDWR = 2
__NR_mkdirat = 287
__NR_openat = 286
__NR_write = 4

View File

@ -195,8 +195,7 @@ xt_cgroup_info_v1 {
has_classid bool8
invert_path bool8
invert_classid bool8
# TODO: this is some "cgroup path"
path array[int8, PATH_MAX]
path string[cgroup_paths, PATH_MAX]
# TODO: again "cgroup classid"
classid int32
priv intptr

View File

@ -6,8 +6,8 @@ include <linux/hw_breakpoint.h>
resource fd_perf[fd]
# TODO: pid is cgroup fd if ERF_FLAG_PID_CGROUP is set.
perf_event_open(attr ptr[in, perf_event_attr], pid pid, cpu intptr, group fd_perf, flags flags[perf_flags]) fd_perf
perf_event_open(attr ptr[in, perf_event_attr], pid pid, cpu intptr[0:16], group fd_perf, flags flags[perf_flags]) fd_perf
perf_event_open$cgroup(attr ptr[in, perf_event_attr], fd fd_cgroup, cpu intptr[0:16], group fd_perf, flags flags[perf_flags]) fd_perf
ioctl$PERF_EVENT_IOC_ENABLE(fd fd_perf, cmd const[PERF_EVENT_IOC_ENABLE], flags intptr)
ioctl$PERF_EVENT_IOC_DISABLE(fd fd_perf, cmd const[PERF_EVENT_IOC_DISABLE], flags intptr)
@ -21,7 +21,8 @@ ioctl$PERF_EVENT_IOC_SET_BPF(fd fd_perf, cmd const[PERF_EVENT_IOC_SET_BPF], prog
ioctl$PERF_EVENT_IOC_PAUSE_OUTPUT(fd fd_perf, cmd const[PERF_EVENT_IOC_PAUSE_OUTPUT], arg boolptr)
ioctl$PERF_EVENT_IOC_QUERY_BPF(fd fd_perf, cmd const[PERF_EVENT_IOC_QUERY_BPF], arg ptr[in, perf_event_query_bpf])
perf_flags = PERF_FLAG_FD_NO_GROUP, PERF_FLAG_FD_OUTPUT, PERF_FLAG_PID_CGROUP, PERF_FLAG_FD_CLOEXEC
perf_flags = PERF_FLAG_FD_NO_GROUP, PERF_FLAG_FD_OUTPUT, PERF_FLAG_FD_CLOEXEC
perf_flags_cgroup = PERF_FLAG_FD_NO_GROUP, PERF_FLAG_FD_OUTPUT, PERF_FLAG_PID_CGROUP, PERF_FLAG_FD_CLOEXEC
perf_event_type = PERF_TYPE_HARDWARE, PERF_TYPE_SOFTWARE, PERF_TYPE_TRACEPOINT, PERF_TYPE_HW_CACHE, PERF_TYPE_RAW, PERF_TYPE_BREAKPOINT
perf_bp_type = HW_BREAKPOINT_EMPTY, HW_BREAKPOINT_R, HW_BREAKPOINT_W, HW_BREAKPOINT_X
perf_sample_type = PERF_SAMPLE_IP, PERF_SAMPLE_TID, PERF_SAMPLE_TIME, PERF_SAMPLE_ADDR, PERF_SAMPLE_READ, PERF_SAMPLE_CALLCHAIN, PERF_SAMPLE_ID, PERF_SAMPLE_CPU, PERF_SAMPLE_PERIOD, PERF_SAMPLE_STREAM_ID, PERF_SAMPLE_RAW, PERF_SAMPLE_BRANCH_STACK, PERF_SAMPLE_REGS_USER, PERF_SAMPLE_STACK_USER, PERF_SAMPLE_WEIGHT, PERF_SAMPLE_DATA_SRC, PERF_SAMPLE_IDENTIFIER, PERF_SAMPLE_TRANSACTION, PERF_SAMPLE_REGS_INTR, PERF_SAMPLE_PHYS_ADDR

File diff suppressed because one or more lines are too long

View File

@ -80,6 +80,9 @@ for i in {0..31}; do
echo "KERNEL==\"binder$i\", NAME=\"binder$i\", MODE=\"0666\"" | \
tee -a disk.mnt/etc/udev/50-binder.rules
done
# We disable selinux for now because the default policy on wheezy prevents
# mounting of cgroup2 (and stretch we don't know how to configure yet).
echo 'SELINUX=disabled' | sudo tee disk.mnt/etc/selinux/config
# sysctls
echo "kernel.printk = 7 4 1 3" | sudo tee -a disk.mnt/etc/sysctl.conf

View File

@ -7,33 +7,34 @@
set -eux
# Create a minimal Debian-wheezy distributive as a directory.
sudo rm -rf wheezy
mkdir -p wheezy
sudo debootstrap --include=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default wheezy wheezy
RELEASE=wheezy
DIR=wheezy
#sudo rm -rf $DIR
#mkdir -p $DIR
#sudo debootstrap --include=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default $RELEASE $DIR
# Set some defaults and enable promtless ssh to the machine for root.
sudo sed -i '/^root/ { s/:x:/::/ }' wheezy/etc/passwd
echo 'T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100' | sudo tee -a wheezy/etc/inittab
printf '\nauto eth0\niface eth0 inet dhcp\n' | sudo tee -a wheezy/etc/network/interfaces
echo 'debugfs /sys/kernel/debug debugfs defaults 0 0' | sudo tee -a wheezy/etc/fstab
echo "kernel.printk = 7 4 1 3" | sudo tee -a wheezy/etc/sysctl.conf
echo 'debug.exception-trace = 0' | sudo tee -a wheezy/etc/sysctl.conf
echo "net.core.bpf_jit_enable = 1" | sudo tee -a wheezy/etc/sysctl.conf
echo "net.core.bpf_jit_harden = 2" | sudo tee -a wheezy/etc/sysctl.conf
echo "net.ipv4.ping_group_range = 0 65535" | sudo tee -a wheezy/etc/sysctl.conf
echo -en "127.0.0.1\tlocalhost\n" | sudo tee wheezy/etc/hosts
echo "nameserver 8.8.8.8" | sudo tee -a wheezy/etc/resolve.conf
echo "syzkaller" | sudo tee wheezy/etc/hostname
sudo mkdir -p wheezy/root/.ssh/
rm -rf ssh
mkdir -p ssh
ssh-keygen -f ssh/id_rsa -t rsa -N ''
cat ssh/id_rsa.pub | sudo tee wheezy/root/.ssh/authorized_keys
sudo sed -i '/^root/ { s/:x:/::/ }' $DIR/etc/passwd
echo 'T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100' | sudo tee -a $DIR/etc/inittab
printf '\nauto eth0\niface eth0 inet dhcp\n' | sudo tee -a $DIR/etc/network/interfaces
echo 'debugfs /sys/kernel/debug debugfs defaults 0 0' | sudo tee -a $DIR/etc/fstab
echo 'SELINUX=disabled' | sudo tee $DIR/etc/selinux/config
echo "kernel.printk = 7 4 1 3" | sudo tee -a $DIR/etc/sysctl.conf
echo 'debug.exception-trace = 0' | sudo tee -a $DIR/etc/sysctl.conf
echo "net.core.bpf_jit_enable = 1" | sudo tee -a $DIR/etc/sysctl.conf
echo "net.core.bpf_jit_harden = 2" | sudo tee -a $DIR/etc/sysctl.conf
echo "net.ipv4.ping_group_range = 0 65535" | sudo tee -a $DIR/etc/sysctl.conf
echo -en "127.0.0.1\tlocalhost\n" | sudo tee $DIR/etc/hosts
echo "nameserver 8.8.8.8" | sudo tee -a $DIR/etc/resolve.conf
echo "syzkaller" | sudo tee $DIR/etc/hostname
ssh-keygen -f $RELEASE.id_rsa -t rsa -N ''
sudo mkdir -p $DIR/root/.ssh/
cat $RELEASE.id_rsa.pub | sudo tee $DIR/root/.ssh/authorized_keys
# Build a disk image
dd if=/dev/zero of=wheezy.img bs=1M seek=2047 count=1
sudo mkfs.ext4 -F wheezy.img
sudo mkdir -p /mnt/wheezy
sudo mount -o loop wheezy.img /mnt/wheezy
sudo cp -a wheezy/. /mnt/wheezy/.
sudo umount /mnt/wheezy
dd if=/dev/zero of=$RELEASE.img bs=1M seek=2047 count=1
sudo mkfs.ext4 -F $RELEASE.img
sudo mkdir -p /mnt/$DIR
sudo mount -o loop $RELEASE.img /mnt/$DIR
sudo cp -a $DIR/. /mnt/$DIR/.
sudo umount /mnt/$DIR