diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/android/android_seccomp.h | 7 | ||||
| -rw-r--r-- | executor/common_bsd.h | 17 | ||||
| -rw-r--r-- | executor/common_fuchsia.h | 3 | ||||
| -rw-r--r-- | executor/common_linux.h | 176 | ||||
| -rw-r--r-- | executor/common_usb_netbsd.h | 20 | ||||
| -rw-r--r-- | executor/cov_filter.h | 2 | ||||
| -rw-r--r-- | executor/executor.cc | 119 | ||||
| -rw-r--r-- | executor/executor_bsd.h | 2 | ||||
| -rw-r--r-- | executor/executor_fuchsia.h | 2 | ||||
| -rw-r--r-- | executor/executor_linux.h | 2 | ||||
| -rw-r--r-- | executor/style_test.go | 10 |
11 files changed, 183 insertions, 177 deletions
diff --git a/executor/android/android_seccomp.h b/executor/android/android_seccomp.h index d8df52792..f3febac2c 100644 --- a/executor/android/android_seccomp.h +++ b/executor/android/android_seccomp.h @@ -46,7 +46,7 @@ typedef struct Filter_t { static void push_back(Filter* filter_array, struct sock_filter filter) { if (filter_array->count == kFilterMaxSize) - fail("can't add another syscall to seccomp filter: count %zu", filter_array->count); + failmsg("can't add another syscall to seccomp filter", "count=%zu", filter_array->count); filter_array->data[filter_array->count++] = filter; } @@ -79,9 +79,8 @@ static void install_filter(const Filter* f) (struct sock_filter*)&f->data[0], }; // This assumes either the current process has CAP_SYS_ADMIN, or PR_SET_NO_NEW_PRIVS bit is set. - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) { - fail("Could not set seccomp filter of size %zu", f->count); - } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) + failmsg("could not set seccomp filter", "size=%zu", f->count); } // Modified from the orignal Android code as we don't need dual arch support diff --git a/executor/common_bsd.h b/executor/common_bsd.h index 7ccd1053f..1bed0cf3c 100644 --- a/executor/common_bsd.h +++ b/executor/common_bsd.h @@ -33,7 +33,7 @@ static void setup_usb(void) char path[1024]; snprintf(path, sizeof(path), "/dev/%s", ent->d_name); if (chmod(path, 0666)) - fail("failed to chmod %s", path); + failmsg("failed to chmod vhci", "path=%s", path); } closedir(dir); @@ -61,7 +61,7 @@ static int inject_fault(int nth) en.mode = 0; // FAULT_MODE_NTH_ONESHOT en.nth = nth + 2; // FAULT_NTH_MIN if (ioctl(fd, FAULT_IOC_ENABLE, &en) != 0) - fail("FAULT_IOC_ENABLE failed with nth=%d", nth); + failmsg("FAULT_IOC_ENABLE failed", "nth=%d", nth); return fd; } @@ -149,7 +149,7 @@ static void vsnprintf_check(char* str, size_t size, const char* format, va_list if (rv < 0) fail("vsnprintf failed"); if ((size_t)rv >= size) - fail("vsnprintf: string '%s...' doesn't fit into buffer", str); + failmsg("vsnprintf: string doesn't fit into buffer", "string='%s'", str); } static void snprintf_check(char* str, size_t size, const char* format, ...) @@ -179,7 +179,7 @@ static void execute_command(bool panic, const char* format, ...) int rv = system(command); if (rv) { if (panic) - fail("command '%s' failed: %d", &command[0], rv); + failmsg("command failed", "command=%s: %d", &command[0], rv); debug("command '%s': %d\n", &command[0], rv); } } @@ -191,9 +191,8 @@ static void initialize_tun(int tun_id) return; #endif // SYZ_EXECUTOR - if (tun_id < 0 || tun_id >= MAX_TUN) { - fail("tun_id out of range %d", tun_id); - } + if (tun_id < 0 || tun_id >= MAX_TUN) + failmsg("tun_id out of range", "tun_id=%d", tun_id); char tun_device[sizeof(TUN_DEVICE)]; snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id); @@ -219,7 +218,7 @@ static void initialize_tun(int tun_id) #endif if (tunfd == -1) { #if SYZ_EXECUTOR - fail("tun: can't open %s", tun_device); + failmsg("tun: can't open device", "device=%s", tun_device); #else printf("tun: can't open %s: errno=%d\n", tun_device, errno); return; @@ -300,7 +299,7 @@ static int read_tun(char* data, int size) if (rv < 0) { if (errno == EAGAIN) return -1; - fail("tun: read failed with %d", rv); + fail("tun: read failed"); } return rv; } diff --git a/executor/common_fuchsia.h b/executor/common_fuchsia.h index 6576e83f0..607518178 100644 --- a/executor/common_fuchsia.h +++ b/executor/common_fuchsia.h @@ -119,7 +119,8 @@ static void install_segv_handler(void) zx_status_t status; zx_handle_t exception_channel; if ((status = zx_task_create_exception_channel(zx_process_self(), 0, &exception_channel)) != ZX_OK) - fail("zx_task_create_exception_channel failed: %s (%d)", zx_status_get_string(status), status); + failmsg("zx_task_create_exception_channel failed", + "status=%s (%d)", zx_status_get_string(status), status); pthread_t th; if (pthread_create(&th, 0, ex_handler, (void*)(long)exception_channel)) fail("pthread_create failed"); diff --git a/executor/common_linux.h b/executor/common_linux.h index a6a117c5b..1d3500a57 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -186,7 +186,7 @@ static int netlink_send_ext(struct nlmsg* nlmsg, int sock, ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr)); if (n != (ssize_t)hdr->nlmsg_len) { if (dofail) - fail("netlink_send_ext: short netlink write: %zd/%d", n, hdr->nlmsg_len); + failmsg("netlink_send_ext: short netlink write", "wrote=%zd, want=%d", n, hdr->nlmsg_len); debug("netlink_send_ext: short netlink write: %zd/%d errno=%d\n", n, hdr->nlmsg_len, errno); return -1; } @@ -195,14 +195,14 @@ static int netlink_send_ext(struct nlmsg* nlmsg, int sock, *reply_len = 0; if (n < 0) { if (dofail) - fail("netlink_send_ext: netlink read failed: %zd", n); - debug("netlink_send_ext: netlink read failed: %zd errno=%d\n", n, errno); + fail("netlink_send_ext: netlink read failed"); + debug("netlink_send_ext: netlink read failed: errno=%d\n", errno); return -1; } if (n < (ssize_t)sizeof(struct nlmsghdr)) { errno = EINVAL; if (dofail) - fail("netlink_send_ext: short netlink read: %zd", n); + failmsg("netlink_send_ext: short netlink read", "read=%zd", n); debug("netlink_send_ext: short netlink read: %zd\n", n); return -1; } @@ -215,14 +215,14 @@ static int netlink_send_ext(struct nlmsg* nlmsg, int sock, if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) { errno = EINVAL; if (dofail) - fail("netlink_send_ext: short netlink read: %zd", n); + failmsg("netlink_send_ext: short netlink read", "read=%zd", n); debug("netlink_send_ext: short netlink read: %zd\n", n); return -1; } if (hdr->nlmsg_type != NLMSG_ERROR) { errno = EINVAL; if (dofail) - fail("netlink_send_ext: short netlink ack: %d", hdr->nlmsg_type); + failmsg("netlink_send_ext: bad netlink ack type", "type=%d", hdr->nlmsg_type); debug("netlink_send_ext: short netlink ack: %d\n", hdr->nlmsg_type); return -1; } @@ -1011,7 +1011,7 @@ static void initialize_wifi_devices(void) mac_addr[5] = device_id; int ret = hwsim80211_create_device(&nlmsg, sock, hwsim_family_id, mac_addr); if (ret < 0) - fail("initialize_wifi_devices: failed to create device #%d", device_id); + failmsg("initialize_wifi_devices: failed to create device", "device=%d", device_id); // For each device, unless HWSIM_ATTR_NO_VIF is passed, a network interface is created // automatically. Such interfaces are named "wlan0", "wlan1" and so on. @@ -1019,7 +1019,7 @@ static void initialize_wifi_devices(void) interface[4] += device_id; if (nl80211_setup_ibss_interface(&nlmsg, sock, nl80211_family_id, interface, &ibss_props) < 0) - fail("initialize_wifi_devices: failed set up IBSS network for #%d", device_id); + failmsg("initialize_wifi_devices: failed set up IBSS network", "device=%d", device_id); } // Wait for all devices to join the IBSS network @@ -1028,7 +1028,8 @@ static void initialize_wifi_devices(void) interface[4] += device_id; int ret = await_ifla_operstate(&nlmsg, interface, IF_OPER_UP); if (ret < 0) - fail("initialize_wifi_devices: get_ifla_operstate failed for #%d, ret %d", device_id, ret); + failmsg("initialize_wifi_devices: get_ifla_operstate failed", + "device=%d, ret=%d", device_id, ret); } close(sock); @@ -1561,7 +1562,7 @@ static int read_tun(char* data, int size) // Tun sometimes returns EBADFD, unclear if it's a kernel bug or not. if (errno == EAGAIN || errno == EBADFD) return -1; - fail("tun: read failed with %d", rv); + fail("tun read failed"); } return rv; } @@ -1856,8 +1857,6 @@ static long syz_io_uring_submit(volatile long a0, volatile long a1, volatile lon static long syz_usbip_server_init(volatile long a0) { - int socket_pair[2]; - char buffer[100]; // port_alloc[0] corresponds to ports which can be used by usb2 and // port_alloc[1] corresponds to ports which can be used by usb3. static int port_alloc[2]; @@ -1865,9 +1864,9 @@ static long syz_usbip_server_init(volatile long a0) int speed = (int)a0; bool usb3 = (speed == USB_SPEED_SUPER); - int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair); - if (rc < 0) - fail("syz_usbip_server_init : socketpair failed: %d", rc); + int socket_pair[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) + fail("syz_usbip_server_init: socketpair failed"); int client_fd = socket_pair[0]; int server_fd = socket_pair[1]; @@ -1887,6 +1886,7 @@ static long syz_usbip_server_init(volatile long a0) // Under normal USB/IP usage, devid represents the device ID on the server. // When fuzzing with syzkaller we don't have an actual server or an actual device, so use 0 for devid. + char buffer[100]; sprintf(buffer, "%d %d %s %d", port_num, client_fd, "0", speed); write_file("/sys/devices/platform/vhci_hcd.0/attach", buffer); @@ -2495,7 +2495,7 @@ static bool process_command_pkt(int fd, char* buf, ssize_t buf_size) struct hci_command_hdr* hdr = (struct hci_command_hdr*)buf; if (buf_size < (ssize_t)sizeof(struct hci_command_hdr) || hdr->plen != buf_size - sizeof(struct hci_command_hdr)) { - fail("invalid size: %zx", buf_size); + failmsg("process_command_pkt: invalid size", "suze=%zx", buf_size); } switch (hdr->opcode) { @@ -3078,7 +3078,7 @@ static void checkpoint_iptables(struct ipt_table_desc* tables, int num_tables, i case ENOPROTOOPT: return; } - fail("iptable checkpoint %d: socket failed", family); + failmsg("iptable checkpoint: socket(SOCK_STREAM, IPPROTO_TCP) failed", "family=%d", family); } for (int i = 0; i < num_tables; i++) { struct ipt_table_desc* table = &tables[i]; @@ -3092,25 +3092,26 @@ static void checkpoint_iptables(struct ipt_table_desc* tables, int num_tables, i case ENOPROTOOPT: continue; } - fail("iptable checkpoint %s/%d: getsockopt(IPT_SO_GET_INFO)", table->name, family); + failmsg("iptable checkpoint: getsockopt(IPT_SO_GET_INFO) failed", + "table=%s, family=%d", table->name, family); } debug("iptable checkpoint %s/%d: checkpoint entries=%d hooks=%x size=%d\n", table->name, family, table->info.num_entries, table->info.valid_hooks, table->info.size); if (table->info.size > sizeof(table->replace.entrytable)) - fail("iptable checkpoint %s/%d: table size is too large: %u", - table->name, family, table->info.size); + failmsg("iptable checkpoint: table size is too large", "table=%s, family=%d, size=%u", + table->name, family, table->info.size); if (table->info.num_entries > XT_MAX_ENTRIES) - fail("iptable checkpoint %s/%d: too many counters: %u", - table->name, family, table->info.num_entries); + failmsg("iptable checkpoint: too many counters", "table=%s, family=%d, counters=%d", + table->name, family, table->info.num_entries); struct ipt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size; if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen)) - fail("iptable checkpoint %s/%d: getsockopt(IPT_SO_GET_ENTRIES)", - table->name, family); + failmsg("iptable checkpoint: getsockopt(IPT_SO_GET_ENTRIES) failed", + "table=%s, family=%d", table->name, family); table->replace.valid_hooks = table->info.valid_hooks; table->replace.num_entries = table->info.num_entries; table->replace.size = table->info.size; @@ -3130,7 +3131,7 @@ static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int fa case ENOPROTOOPT: return; } - fail("iptable %d: socket failed", family); + failmsg("iptable: socket(SOCK_STREAM, IPPROTO_TCP) failed", "family=%d", family); } for (int i = 0; i < num_tables; i++) { struct ipt_table_desc* table = &tables[i]; @@ -3141,7 +3142,8 @@ static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int fa strcpy(info.name, table->name); socklen_t optlen = sizeof(info); if (getsockopt(fd, level, IPT_SO_GET_INFO, &info, &optlen)) - fail("iptable %s/%d: getsockopt(IPT_SO_GET_INFO)", table->name, family); + failmsg("iptable: getsockopt(IPT_SO_GET_INFO) failed", + "table=%s, family=%d", table->name, family); if (memcmp(&table->info, &info, sizeof(table->info)) == 0) { struct ipt_get_entries entries; memset(&entries, 0, sizeof(entries)); @@ -3149,7 +3151,8 @@ static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int fa entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size; if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen)) - fail("iptable %s/%d: getsockopt(IPT_SO_GET_ENTRIES)", table->name, family); + failmsg("iptable: getsockopt(IPT_SO_GET_ENTRIES) failed", + "table=%s, family=%d", table->name, family); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; } @@ -3159,7 +3162,8 @@ static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int fa table->replace.counters = counters; optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size; if (setsockopt(fd, level, IPT_SO_SET_REPLACE, &table->replace, optlen)) - fail("iptable %s/%d: setsockopt(IPT_SO_SET_REPLACE)", table->name, family); + failmsg("iptable: setsockopt(IPT_SO_SET_REPLACE) failed", + "table=%s, family=%d", table->name, family); } close(fd); } @@ -3173,7 +3177,7 @@ static void checkpoint_arptables(void) case ENOPROTOOPT: return; } - fail("arptable checkpoint: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)"); + fail("arptable checkpoint: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) failed"); } for (unsigned i = 0; i < sizeof(arpt_tables) / sizeof(arpt_tables[0]); i++) { struct arpt_table_desc* table = &arpt_tables[i]; @@ -3187,23 +3191,23 @@ static void checkpoint_arptables(void) case ENOPROTOOPT: continue; } - fail("arptable checkpoint %s: getsockopt(ARPT_SO_GET_INFO)", table->name); + failmsg("arptable checkpoint: getsockopt(ARPT_SO_GET_INFO) failed", "table=%s", table->name); } debug("arptable checkpoint %s: entries=%d hooks=%x size=%d\n", table->name, table->info.num_entries, table->info.valid_hooks, table->info.size); if (table->info.size > sizeof(table->replace.entrytable)) - fail("arptable checkpoint %s: table size is too large: %u", - table->name, table->info.size); + failmsg("arptable checkpoint: table size is too large", + "table=%s, size=%u", table->name, table->info.size); if (table->info.num_entries > XT_MAX_ENTRIES) - fail("arptable checkpoint %s: too many counters: %u", - table->name, table->info.num_entries); + failmsg("arptable checkpoint: too many counters", + "table=%s, counters=%u", table->name, table->info.num_entries); struct arpt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size; if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen)) - fail("arptable checkpoint %s: getsockopt(ARPT_SO_GET_ENTRIES)", table->name); + failmsg("arptable checkpoint: getsockopt(ARPT_SO_GET_ENTRIES) failed", "table=%s", table->name); table->replace.valid_hooks = table->info.valid_hooks; table->replace.num_entries = table->info.num_entries; table->replace.size = table->info.size; @@ -3234,7 +3238,7 @@ static void reset_arptables() strcpy(info.name, table->name); socklen_t optlen = sizeof(info); if (getsockopt(fd, SOL_IP, ARPT_SO_GET_INFO, &info, &optlen)) - fail("arptable %s:getsockopt(ARPT_SO_GET_INFO)", table->name); + failmsg("arptable: getsockopt(ARPT_SO_GET_INFO) failed", "table=%s", table->name); if (memcmp(&table->info, &info, sizeof(table->info)) == 0) { struct arpt_get_entries entries; memset(&entries, 0, sizeof(entries)); @@ -3242,7 +3246,7 @@ static void reset_arptables() entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size; if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen)) - fail("arptable %s: getsockopt(ARPT_SO_GET_ENTRIES)", table->name); + failmsg("arptable: getsockopt(ARPT_SO_GET_ENTRIES) failed", "table=%s", table->name); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; debug("arptable %s: data changed\n", table->name); @@ -3255,7 +3259,8 @@ static void reset_arptables() table->replace.counters = counters; optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size; if (setsockopt(fd, SOL_IP, ARPT_SO_SET_REPLACE, &table->replace, optlen)) - fail("arptable %s: setsockopt(ARPT_SO_SET_REPLACE)", table->name); + failmsg("arptable: setsockopt(ARPT_SO_SET_REPLACE) failed", + "table=%s", table->name); } close(fd); } @@ -3328,19 +3333,21 @@ static void checkpoint_ebtables(void) case ENOPROTOOPT: continue; } - fail("ebtable checkpoint %s: getsockopt(EBT_SO_GET_INIT_INFO)", table->name); + failmsg("ebtable checkpoint: getsockopt(EBT_SO_GET_INIT_INFO) failed", + "table=%s", table->name); } debug("ebtable checkpoint %s: entries=%d hooks=%x size=%d\n", table->name, table->replace.nentries, table->replace.valid_hooks, table->replace.entries_size); if (table->replace.entries_size > sizeof(table->entrytable)) - fail("ebtable checkpoint %s: table size is too large: %u", - table->name, table->replace.entries_size); + failmsg("ebtable checkpoint: table size is too large", "table=%s, size=%u", + table->name, table->replace.entries_size); table->replace.num_counters = 0; table->replace.entries = table->entrytable; optlen = sizeof(table->replace) + table->replace.entries_size; if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_ENTRIES, &table->replace, &optlen)) - fail("ebtable checkpoint %s: getsockopt(EBT_SO_GET_INIT_ENTRIES)", table->name); + failmsg("ebtable checkpoint: getsockopt(EBT_SO_GET_INIT_ENTRIES) failed", + "table=%s", table->name); } close(fd); } @@ -3365,7 +3372,7 @@ static void reset_ebtables() strcpy(replace.name, table->name); socklen_t optlen = sizeof(replace); if (getsockopt(fd, SOL_IP, EBT_SO_GET_INFO, &replace, &optlen)) - fail("ebtable %s: getsockopt(EBT_SO_GET_INFO)", table->name); + failmsg("ebtable: getsockopt(EBT_SO_GET_INFO)", "table=%s", table->name); replace.num_counters = 0; table->replace.entries = 0; for (unsigned h = 0; h < NF_BR_NUMHOOKS; h++) @@ -3376,7 +3383,7 @@ static void reset_ebtables() replace.entries = entrytable; optlen = sizeof(replace) + replace.entries_size; if (getsockopt(fd, SOL_IP, EBT_SO_GET_ENTRIES, &replace, &optlen)) - fail("ebtable %s: getsockopt(EBT_SO_GET_ENTRIES)", table->name); + failmsg("ebtable: getsockopt(EBT_SO_GET_ENTRIES) failed", "table=%s", table->name); if (memcmp(table->entrytable, entrytable, replace.entries_size) == 0) continue; } @@ -3391,7 +3398,7 @@ static void reset_ebtables() table->replace.entries = table->entrytable; optlen = sizeof(table->replace) + table->replace.entries_size; if (setsockopt(fd, SOL_IP, EBT_SO_SET_ENTRIES, &table->replace, optlen)) - fail("ebtable %s: setsockopt(EBT_SO_SET_ENTRIES)", table->name); + failmsg("ebtable: setsockopt(EBT_SO_SET_ENTRIES) failed", "table=%s", table->name); } close(fd); } @@ -3978,19 +3985,18 @@ const size_t UNTRUSTED_APP_NUM_GROUPS = sizeof(UNTRUSTED_APP_GROUPS) / sizeof(UN // - No library dependency // - No dynamic memory allocation // - Uses fail() instead of returning an error code -static void syz_getcon(char* context, size_t context_size) +static void getcon(char* context, size_t context_size) { int fd = open(SELINUX_CONTEXT_FILE, O_RDONLY); - if (fd < 0) - fail("getcon: Couldn't open %s", SELINUX_CONTEXT_FILE); + fail("getcon: couldn't open context file"); ssize_t nread = read(fd, context, context_size); close(fd); if (nread <= 0) - fail("getcon: Failed to read from %s", SELINUX_CONTEXT_FILE); + fail("getcon: failed to read context file"); // The contents of the context file MAY end with a newline // and MAY not have a null terminator. Handle this here. @@ -4002,7 +4008,7 @@ static void syz_getcon(char* context, size_t context_size) // - No library dependency // - No dynamic memory allocation // - Uses fail() instead of returning an error code -static void syz_setcon(const char* context) +static void setcon(const char* context) { char new_context[512]; @@ -4010,7 +4016,7 @@ static void syz_setcon(const char* context) int fd = open(SELINUX_CONTEXT_FILE, O_WRONLY); if (fd < 0) - fail("setcon: Could not open %s", SELINUX_CONTEXT_FILE); + fail("setcon: could not open context file"); ssize_t bytes_written = write(fd, context, strlen(context)); @@ -4019,45 +4025,29 @@ static void syz_setcon(const char* context) close(fd); if (bytes_written != (ssize_t)strlen(context)) - fail("setcon: Could not write entire context. Wrote %zi, expected %zu", bytes_written, strlen(context)); + failmsg("setcon: could not write entire context", "wrote=%zi, expected=%zu", bytes_written, strlen(context)); // Validate the transition by checking the context - syz_getcon(new_context, sizeof(new_context)); + getcon(new_context, sizeof(new_context)); if (strcmp(context, new_context) != 0) - fail("setcon: Failed to change to %s, context is %s", context, new_context); -} - -// Similar to libselinux getfilecon(3), but: -// - No library dependency -// - No dynamic memory allocation -// - Uses fail() instead of returning an error code -static int syz_getfilecon(const char* path, char* context, size_t context_size) -{ - int length = getxattr(path, SELINUX_XATTR_NAME, context, context_size); - - if (length == -1) - fail("getfilecon: getxattr failed"); - - return length; + failmsg("setcon: failed to change", "want=%s, context=%s", context, new_context); } // Similar to libselinux setfilecon(3), but: // - No library dependency // - No dynamic memory allocation // - Uses fail() instead of returning an error code -static void syz_setfilecon(const char* path, const char* context) +static void setfilecon(const char* path, const char* context) { char new_context[512]; if (setxattr(path, SELINUX_XATTR_NAME, context, strlen(context) + 1, 0) != 0) fail("setfilecon: setxattr failed"); - - if (syz_getfilecon(path, new_context, sizeof(new_context)) <= 0) - fail("setfilecon: getfilecon failed"); - + if (getxattr(path, SELINUX_XATTR_NAME, new_context, sizeof(new_context)) < 0) + fail("setfilecon: getxattr failed"); if (strcmp(context, new_context) != 0) - fail("setfilecon: could not set context to %s, currently %s", context, new_context); + failmsg("setfilecon: could not set context", "want=%s, got=%s", context, new_context); } #define SYZ_HAVE_SANDBOX_ANDROID 1 @@ -4088,13 +4078,13 @@ static int do_sandbox_android(void) #endif if (chown(".", UNTRUSTED_APP_UID, UNTRUSTED_APP_UID) != 0) - fail("chmod failed"); + fail("do_sandbox_android: chmod failed"); if (setgroups(UNTRUSTED_APP_NUM_GROUPS, UNTRUSTED_APP_GROUPS) != 0) - fail("setgroups failed"); + fail("do_sandbox_android: setgroups failed"); if (setresgid(UNTRUSTED_APP_GID, UNTRUSTED_APP_GID, UNTRUSTED_APP_GID) != 0) - fail("setresgid failed"); + fail("do_sandbox_android: setresgid failed"); #if GOARCH_arm || GOARCH_arm64 || GOARCH_386 || GOARCH_amd64 // Will fail() if anything fails. @@ -4104,13 +4094,13 @@ static int do_sandbox_android(void) #endif if (setresuid(UNTRUSTED_APP_UID, UNTRUSTED_APP_UID, UNTRUSTED_APP_UID) != 0) - fail("setresuid failed"); + fail("do_sandbox_android: setresuid failed"); // setresuid and setresgid clear the parent-death signal. prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); - syz_setfilecon(".", SELINUX_LABEL_APP_DATA_FILE); - syz_setcon(SELINUX_CONTEXT_UNTRUSTED_APP); + setfilecon(".", SELINUX_LABEL_APP_DATA_FILE); + setcon(SELINUX_CONTEXT_UNTRUSTED_APP); loop(); doexit(1); @@ -4454,7 +4444,7 @@ static void setup_fault() if (!write_file(files[i].file, files[i].val)) { debug("failed to write %s: %d\n", files[i].file, errno); if (files[i].fatal) - fail("failed to write %s", files[i].file); + failmsg("failed to write fault injection file", "file=%s", files[i].file); } } } @@ -4473,12 +4463,12 @@ static void setup_leak() { // Flush boot leaks. if (!write_file(KMEMLEAK_FILE, "scan")) - fail("failed to write %s", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"scan\")"); sleep(5); // account for MSECS_MIN_AGE if (!write_file(KMEMLEAK_FILE, "scan")) - fail("failed to write %s", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"scan\")"); if (!write_file(KMEMLEAK_FILE, "clear")) - fail("failed to write %s", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"clear\")"); } #define SYZ_HAVE_LEAK_CHECK 1 @@ -4490,7 +4480,7 @@ static void check_leaks(void) { int fd = open(KMEMLEAK_FILE, O_RDWR); if (fd == -1) - fail("failed to open(\"%s\")", KMEMLEAK_FILE); + fail("failed to open(kmemleak)"); // KMEMLEAK has false positives. To mitigate most of them, it checksums // potentially leaked objects, and reports them only on the next scan // iff the checksum does not change. Because of that we do the following @@ -4501,28 +4491,28 @@ static void check_leaks(void) // hopefully these are true positives during the previous testing cycle. uint64 start = current_time_ms(); if (write(fd, "scan", 4) != 4) - fail("failed to write(%s, \"scan\")", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"scan\")"); sleep(1); // Account for MSECS_MIN_AGE // (1 second less because scanning will take at least a second). while (current_time_ms() - start < 4 * 1000) sleep(1); if (write(fd, "scan", 4) != 4) - fail("failed to write(%s, \"scan\")", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"scan\")"); static char buf[128 << 10]; ssize_t n = read(fd, buf, sizeof(buf) - 1); if (n < 0) - fail("failed to read(%s)", KMEMLEAK_FILE); + fail("failed to read(kmemleak)"); int nleaks = 0; if (n != 0) { sleep(1); if (write(fd, "scan", 4) != 4) - fail("failed to write(%s, \"scan\")", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"scan\")"); if (lseek(fd, 0, SEEK_SET) < 0) - fail("failed to lseek(%s)", KMEMLEAK_FILE); + fail("failed to lseek(kmemleak)"); n = read(fd, buf, sizeof(buf) - 1); if (n < 0) - fail("failed to read(%s)", KMEMLEAK_FILE); + fail("failed to read(kmemleak)"); buf[n] = 0; char* pos = buf; char* end = buf + n; @@ -4552,7 +4542,7 @@ static void check_leaks(void) } } if (write(fd, "clear", 5) != 5) - fail("failed to write(%s, \"clear\")", KMEMLEAK_FILE); + fail("failed to write(kmemleak, \"clear\")"); close(fd); if (nleaks) doexit(1); @@ -4589,7 +4579,7 @@ static void setup_kcsan_filterlist(char** frames, int nframes, bool suppress) { int fd = open(KCSAN_DEBUGFS_FILE, O_WRONLY); if (fd == -1) - fail("failed to open(\"%s\")", KCSAN_DEBUGFS_FILE); + fail("failed to open kcsan debugfs file"); printf("%s KCSAN reports in functions: ", suppress ? "suppressing" : "only showing"); diff --git a/executor/common_usb_netbsd.h b/executor/common_usb_netbsd.h index 56c9718be..138b50557 100644 --- a/executor/common_usb_netbsd.h +++ b/executor/common_usb_netbsd.h @@ -218,14 +218,11 @@ static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, analyze_usb_device(index); #endif - int rv = vhci_setport(fd, 1); - if (rv != 0) { - fail("syz_usb_connect: vhci_setport failed with %d", errno); - } + if (vhci_setport(fd, 1)) + fail("syz_usb_connect: vhci_setport failed with"); - rv = vhci_usb_attach(fd); - if (rv != 0) { - debug("syz_usb_connect: vhci_usb_attach failed with %d\n", rv); + if (vhci_usb_attach(fd)) { + debug("syz_usb_connect: vhci_usb_attach failed with %d\n", errno); return -1; } debug("syz_usb_connect: vhci_usb_attach success\n"); @@ -234,8 +231,7 @@ static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, while (!done) { vhci_request_t req; - rv = vhci_usb_recv(fd, &req, sizeof(req)); - if (rv != 0) { + if (vhci_usb_recv(fd, &req, sizeof(req))) { debug("syz_usb_connect: vhci_usb_recv failed with %d\n", errno); return -1; } @@ -285,6 +281,7 @@ static volatile long syz_usb_connect_impl(int fd, uint64 speed, uint64 dev_len, else memset(data, 0, response_length); + int rv = 0; if (req.u.ctrl.bmRequestType & UE_DIR_IN) { debug("syz_usb_connect: writing %d bytes\n", response_length); if (response_length > 0) { @@ -329,9 +326,8 @@ static volatile long syz_usb_connect(volatile long a0, volatile long a1, debug_dump_data(dev, dev_len); int fd = vhci_open(); - if (fd < 0) { - fail("syz_usb_connect: vhci_open failed with %d", errno); - } + if (fd < 0) + fail("syz_usb_connect: vhci_open failed"); long res = syz_usb_connect_impl(fd, speed, dev_len, dev, descs, &lookup_connect_response_out_generic); close(fd); return res; diff --git a/executor/cov_filter.h b/executor/cov_filter.h index 26eb67ec8..a8b6624fe 100644 --- a/executor/cov_filter.h +++ b/executor/cov_filter.h @@ -30,7 +30,7 @@ static void init_coverage_filter() void* preferred = (void*)0x110f230000ull; cov_filter = (cov_filter_t*)mmap(preferred, st.st_size, PROT_READ, MAP_PRIVATE, f, 0); if (cov_filter != preferred) - fail("failed to initialize coverage filter bitmap at %p", preferred); + failmsg("failed to mmap coverage filter bitmap", "want=%p, got=%p", preferred, cov_filter); if ((uint32)st.st_size != sizeof(uint32) * 2 + ((cov_filter->pcsize >> 4) + 7) / 8) fail("bad coverage filter bitmap size"); close(f); diff --git a/executor/executor.cc b/executor/executor.cc index 5bb2d7226..80fdc49cc 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -75,7 +75,12 @@ const int kCoverSize = 256 << 10; const int kFailStatus = 67; // Logical error (e.g. invalid input program), use as an assert() alternative. -static NORETURN PRINTF(1, 2) void fail(const char* msg, ...); +// If such error happens 10+ times in a row, it will be detected as a bug by syz-fuzzer. +// syz-fuzzer will fail and syz-manager will create a bug for this. +// Note: err is used for bug deduplication, thus distinction between err (constant message) +// and msg (varying part). +static NORETURN void fail(const char* err); +static NORETURN PRINTF(2, 3) void failmsg(const char* err, const char* msg, ...); // Just exit (e.g. due to temporal ENOMEM error). static NORETURN PRINTF(1, 2) void exitf(const char* msg, ...); static NORETURN void doexit(int status); @@ -524,9 +529,9 @@ void receive_handshake() handshake_req req = {}; int n = read(kInPipeFd, &req, sizeof(req)); if (n != sizeof(req)) - fail("handshake read failed: %d", n); + failmsg("handshake read failed", "read=%d", n); if (req.magic != kInMagic) - fail("bad handshake magic 0x%llx", req.magic); + failmsg("bad handshake magic", "magic=0x%llx", req.magic); parse_env_flags(req.flags); procid = req.pid; } @@ -548,9 +553,9 @@ void receive_execute() if (read(kInPipeFd, &req, sizeof(req)) != (ssize_t)sizeof(req)) fail("control pipe read failed"); if (req.magic != kInMagic) - fail("bad execute request magic 0x%llx", req.magic); + failmsg("bad execute request magic", "magic=0x%llx", req.magic); if (req.prog_size > kMaxInput) - fail("bad execute prog size 0x%llx", req.prog_size); + failmsg("bad execute prog size", "size=0x%llx", req.prog_size); parse_env_flags(req.env_flags); procid = req.pid; syscall_timeout_ms = req.syscall_timeout_ms; @@ -574,7 +579,8 @@ void receive_execute() flag_fault_call, flag_fault_nth, syscall_timeout_ms, program_timeout_ms, slowdown_scale, req.prog_size, flag_coverage_filter); if (syscall_timeout_ms == 0 || program_timeout_ms <= syscall_timeout_ms || slowdown_scale == 0) - fail("bad timeouts: %llu/%llu/%llu", syscall_timeout_ms, program_timeout_ms, slowdown_scale); + failmsg("bad timeouts", "syscall=%llu, program=%llu, scale=%llu", + syscall_timeout_ms, program_timeout_ms, slowdown_scale); if (SYZ_EXECUTOR_USES_SHMEM) { if (req.prog_size) fail("need_prog: no program"); @@ -592,7 +598,7 @@ void receive_execute() break; } if (pos != req.prog_size) - fail("bad input size %lld, want %lld", pos, req.prog_size); + failmsg("bad input size", "size=%lld, want=%lld", pos, req.prog_size); } #if GOOS_akaros @@ -681,7 +687,7 @@ retry: switch (csum_kind) { case arg_csum_inet: { if (size != 2) - fail("inet checksum must be 2 bytes, not %llu", size); + failmsg("bag inet checksum size", "size=%llu", size); debug_verbose("calculating checksum for %p\n", csum_addr); struct csum_inet csum; csum_inet_init(&csum); @@ -698,16 +704,15 @@ retry: NONFAILING(csum_inet_update(&csum, (const uint8*)chunk_value, chunk_size)); break; case arg_csum_chunk_const: - if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) { - fail("bad checksum const chunk size %lld", chunk_size); - } + if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) + failmsg("bad checksum const chunk size", "size=%lld", chunk_size); // Here we assume that const values come to us big endian. debug_verbose("#%lld: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size); csum_inet_update(&csum, (const uint8*)&chunk_value, chunk_size); break; default: - fail("bad checksum chunk kind %llu", chunk_kind); + failmsg("bad checksum chunk kind", "kind=%llu", chunk_kind); } } uint16 csum_value = csum_inet_digest(&csum); @@ -716,12 +721,12 @@ retry: break; } default: - fail("bad checksum kind %llu", csum_kind); + failmsg("bad checksum kind", "kind=%llu", csum_kind); } break; } default: - fail("bad argument type %llu", typ); + failmsg("bad argument type", "type=%llu", typ); } continue; } @@ -735,10 +740,10 @@ retry: // Normal syscall. if (call_num >= ARRAY_SIZE(syscalls)) - fail("invalid command number %llu", call_num); + failmsg("invalid syscall number", "call_num=%llu", call_num); const call_t* call = &syscalls[call_num]; if (call->attrs.disabled) - fail("executing disabled syscall %s", call->name); + failmsg("executing disabled syscall", "syscall=%s", call->name); if (prog_extra_timeout < call->attrs.prog_timeout) prog_extra_timeout = call->attrs.prog_timeout * slowdown_scale; if (strncmp(syscalls[call_num].name, "syz_usb", strlen("syz_usb")) == 0) @@ -748,7 +753,7 @@ retry: uint64 copyout_index = read_input(&input_pos); uint64 num_args = read_input(&input_pos); if (num_args > kMaxArgs) - fail("command has bad number of arguments %llu", num_args); + failmsg("command has bad number of arguments", "args=%llu", num_args); uint64 args[kMaxArgs] = {}; for (uint64 i = 0; i < num_args; i++) args[i] = read_arg(&input_pos); @@ -856,8 +861,8 @@ thread_t* schedule_call(int call_index, int call_num, bool colliding, uint64 cop exitf("out of threads"); thread_t* th = &threads[i]; if (event_isset(&th->ready) || !event_isset(&th->done) || th->executing) - fail("bad thread state in schedule: ready=%d done=%d executing=%d", - event_isset(&th->ready), event_isset(&th->done), th->executing); + failmsg("bad thread state in schedule", "ready=%d done=%d executing=%d", + event_isset(&th->ready), event_isset(&th->done), th->executing); last_scheduled = th; th->colliding = colliding; th->copyout_pos = pos; @@ -925,8 +930,8 @@ void write_coverage_signal(cover_t* cov, uint32* signal_count_pos, uint32* cover void handle_completion(thread_t* th) { if (event_isset(&th->ready) || !event_isset(&th->done) || !th->executing) - fail("bad thread state in completion: ready=%d done=%d executing=%d", - event_isset(&th->ready), event_isset(&th->done), th->executing); + failmsg("bad thread state in completion", "ready=%d done=%d executing=%d", + event_isset(&th->ready), event_isset(&th->done), th->executing); if (th->res != (intptr_t)-1) copyout_call_results(th); if (!collide && !th->colliding) { @@ -947,7 +952,7 @@ void handle_completion(thread_t* th) event_isset(&th1->ready), event_isset(&th1->done), th1->call_index, (uint64)th1->res, th1->reserrno); } - fail("running = %d", running); + fail("negative running"); } } @@ -955,7 +960,7 @@ void copyout_call_results(thread_t* th) { if (th->copyout_index != no_copyout) { if (th->copyout_index >= kMaxCommands) - fail("result idx %lld overflows kMaxCommands", th->copyout_index); + failmsg("result overflows kMaxCommands", "index=%lld", th->copyout_index); results[th->copyout_index].executed = true; results[th->copyout_index].val = th->res; } @@ -965,7 +970,7 @@ void copyout_call_results(thread_t* th) case instr_copyout: { uint64 index = read_input(&th->copyout_pos); if (index >= kMaxCommands) - fail("result idx %lld overflows kMaxCommands", index); + failmsg("result overflows kMaxCommands", "index=%lld", index); char* addr = (char*)read_input(&th->copyout_pos); uint64 size = read_input(&th->copyout_pos); uint64 val = 0; @@ -1008,7 +1013,7 @@ void write_call_output(thread_t* th, bool finished) kcov_comparison_t* start = (kcov_comparison_t*)(th->cov.data + sizeof(uint64)); kcov_comparison_t* end = start + ncomps; if ((char*)end > th->cov.data_end) - fail("too many comparisons %u", ncomps); + failmsg("too many comparisons", "ncomps=%u", ncomps); cover_unprotect(&th->cov); std::sort(start, end); ncomps = std::unique(start, end) - start; @@ -1143,7 +1148,7 @@ void execute_call(thread_t* th) if (flag_coverage) { cover_collect(&th->cov); if (th->cov.size >= kCoverSize) - fail("#%d: too much cover %u", th->id, th->cov.size); + failmsg("too much cover", "thr=%d, cov=%u", th->id, th->cov.size); } th->fault_injected = false; @@ -1217,7 +1222,7 @@ void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint6 debug_verbose("copyin: addr=%p val=0x%llx size=%llu bf=%llu bf_off=%llu bf_len=%llu\n", addr, val, size, bf, bf_off, bf_len); if (bf != binary_format_native && bf != binary_format_bigendian && (bf_off != 0 || bf_len != 0)) - fail("bitmask for string format %llu/%llu", bf_off, bf_len); + failmsg("bitmask for string format", "off=%llu, len=%llu", bf_off, bf_len); switch (bf) { case binary_format_native: case binary_format_bigendian: @@ -1235,26 +1240,26 @@ void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint6 copyin_int<uint64>(addr, val, bf, bf_off, bf_len); break; default: - fail("copyin: bad argument size %llu", size); + failmsg("copyin: bad argument size", "size=%llu", size); }); break; case binary_format_strdec: if (size != 20) - fail("bad strdec size %llu", size); + failmsg("bad strdec size", "size=%llu", size); NONFAILING(sprintf((char*)addr, "%020llu", val)); break; case binary_format_strhex: if (size != 18) - fail("bad strhex size %llu", size); + failmsg("bad strhex size", "size=%llu", size); NONFAILING(sprintf((char*)addr, "0x%016llx", val)); break; case binary_format_stroct: if (size != 23) - fail("bad stroct size %llu", size); + failmsg("bad stroct size", "size=%llu", size); NONFAILING(sprintf((char*)addr, "%023llo", val)); break; default: - fail("unknown binary format %llu", bf); + failmsg("unknown binary format", "format=%llu", bf); } } @@ -1275,7 +1280,7 @@ bool copyout(char* addr, uint64 size, uint64* res) *res = *(uint64*)addr; break; default: - fail("copyout: bad argument size %llu", size); + failmsg("copyout: bad argument size", "size=%llu", size); }); } @@ -1287,20 +1292,20 @@ uint64 read_arg(uint64** input_posp) uint64 size, bf, bf_off, bf_len; uint64 val = read_const_arg(input_posp, &size, &bf, &bf_off, &bf_len); if (bf != binary_format_native && bf != binary_format_bigendian) - fail("bad argument binary format %llu", bf); + failmsg("bad argument binary format", "format=%llu", bf); if (bf_off != 0 || bf_len != 0) - fail("bad argument bitfield %llu/%llu", bf_off, bf_len); + failmsg("bad argument bitfield", "off=%llu, len=%llu", bf_off, bf_len); return swap(val, size, bf); } case arg_result: { uint64 meta = read_input(input_posp); uint64 bf = meta >> 8; if (bf != binary_format_native) - fail("bad result argument format %llu", bf); + failmsg("bad result argument format", "format=%llu", bf); return read_result(input_posp); } default: - fail("bad argument type %llu", typ); + failmsg("bad argument type", "type=%llu", typ); } } @@ -1309,7 +1314,7 @@ uint64 swap(uint64 v, uint64 size, uint64 bf) if (bf == binary_format_native) return v; if (bf != binary_format_bigendian) - fail("bad binary format in swap: %llu", bf); + failmsg("bad binary format in swap", "format=%llu", bf); switch (size) { case 2: return htobe16(v); @@ -1318,7 +1323,7 @@ uint64 swap(uint64 v, uint64 size, uint64 bf) case 8: return htobe64(v); default: - fail("bad big-endian int size %llu", size); + failmsg("bad big-endian int size", "size=%llu", size); } } @@ -1343,7 +1348,7 @@ uint64 read_result(uint64** input_posp) uint64 op_add = read_input(input_posp); uint64 arg = read_input(input_posp); if (idx >= kMaxCommands) - fail("command refers to bad result %lld", idx); + failmsg("command refers to bad result", "result=%lld", idx); if (results[idx].executed) { arg = results[idx].val; if (op_div != 0) @@ -1357,7 +1362,7 @@ uint64 read_input(uint64** input_posp, bool peek) { uint64* input_pos = *input_posp; if ((char*)input_pos >= input_data + kMaxInput) - fail("input command overflows input %p: [%p:%p)", input_pos, input_data, input_data + kMaxInput); + failmsg("input command overflows input", "pos=%p: [%p:%p)", input_pos, input_data, input_data + kMaxInput); if (!peek) *input_posp = input_pos + 1; return *input_pos; @@ -1367,8 +1372,8 @@ uint64 read_input(uint64** input_posp, bool peek) uint32* write_output(uint32 v) { if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput) - fail("output overflow: pos=%p region=[%p:%p]", - output_pos, output_data, (char*)output_data + kMaxOutput); + failmsg("output overflow", "pos=%p region=[%p:%p]", + output_pos, output_data, (char*)output_data + kMaxOutput); *output_pos = v; return output_pos++; } @@ -1376,8 +1381,8 @@ uint32* write_output(uint32 v) uint32* write_output_64(uint64 v) { if (output_pos < output_data || (char*)(output_pos + 1) >= (char*)output_data + kMaxOutput) - fail("output overflow: pos=%p region=[%p:%p]", - output_pos, output_data, (char*)output_data + kMaxOutput); + failmsg("output overflow", "pos=%p region=[%p:%p]", + output_pos, output_data, (char*)output_data + kMaxOutput); *(uint64*)output_pos = v; output_pos += 2; return output_pos; @@ -1393,7 +1398,7 @@ void write_completed(uint32 completed) void kcov_comparison_t::write() { if (type > (KCOV_CMP_CONST | KCOV_CMP_SIZE_MASK)) - fail("invalid kcov comp type %llx", type); + failmsg("invalid kcov comp type", "type=%llx", type); // Write order: type arg1 arg2 pc. write_output((uint32)type); @@ -1499,18 +1504,21 @@ void setup_features(char** enable, int n) } #endif if (!found) - fail("unknown feature %s", enable[i]); + failmsg("setup features: unknown feature", "feature=%s", enable[i]); } } -void fail(const char* msg, ...) +void failmsg(const char* err, 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); + if (msg) { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + } + fprintf(stderr, " (errno %d: %s)\n", e, strerror(e)); + fprintf(stderr, "SYZFAIL: %s\n", err); // fail()'s are often used during the validation of kernel reactions to queries // that were issued by pseudo syscalls implementations. As fault injection may @@ -1528,6 +1536,11 @@ void fail(const char* msg, ...) doexit(kFailStatus); } +void fail(const char* err) +{ + failmsg(err, 0); +} + void exitf(const char* msg, ...) { int e = errno; diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h index fa31099fe..8ef8186f8 100644 --- a/executor/executor_bsd.h +++ b/executor/executor_bsd.h @@ -61,7 +61,7 @@ static void cover_open(cover_t* cov, bool extra) if (fd == -1) fail("open of /dev/kcov failed"); if (dup2(fd, cov->fd) < 0) - fail("failed to dup2(%d, %d) cover fd", fd, cov->fd); + failmsg("failed to dup cover fd", "from=%d, to=%d", fd, cov->fd); close(fd); #if GOOS_freebsd diff --git a/executor/executor_fuchsia.h b/executor/executor_fuchsia.h index 88a1ccff5..646711079 100644 --- a/executor/executor_fuchsia.h +++ b/executor/executor_fuchsia.h @@ -15,7 +15,7 @@ static void os_init(int argc, char** argv, void* data, size_t data_size) { zx_status_t status = syz_mmap((size_t)data, data_size); if (status != ZX_OK) - fail("mmap of data segment failed: %s (%d)", zx_status_get_string(status), status); + failmsg("mmap of data segment failed", "status=%s (%d)", zx_status_get_string(status), status); } static intptr_t execute_syscall(const call_t* c, intptr_t a[kMaxArgs]) diff --git a/executor/executor_linux.h b/executor/executor_linux.h index 57c2638ea..3a0620fcd 100644 --- a/executor/executor_linux.h +++ b/executor/executor_linux.h @@ -79,7 +79,7 @@ static void cover_open(cover_t* cov, bool extra) if (fd == -1) fail("open of /sys/kernel/debug/kcov failed"); if (dup2(fd, cov->fd) < 0) - fail("filed to dup2(%d, %d) cover fd", fd, cov->fd); + failmsg("filed to dup cover fd", "from=%d, to=%d", fd, cov->fd); close(fd); const int kcov_init_trace = is_kernel_64_bit ? KCOV_INIT_TRACE64 : KCOV_INIT_TRACE32; const int cover_size = extra ? kExtraCoverSize : kCoverSize; diff --git a/executor/style_test.go b/executor/style_test.go index 3b0ee8ce7..9c83f2536 100644 --- a/executor/style_test.go +++ b/executor/style_test.go @@ -111,12 +111,20 @@ if (foo) }, }, { - pattern: `\s*(fail|exitf)\(".*\\n`, + pattern: `(fail|exitf)\(".*\\n`, message: "Don't use \\n in fail/exitf messages", tests: []string{ `fail("some message with new line\n");`, }, }, + { + pattern: `fail(msg)?\("[^"]*%`, + message: "DON'T", + tests: []string{ + `fail("format %s string")`, + `failmsg("format %s string", "format")`, + }, + }, } for _, check := range checks { re := regexp.MustCompile(check.pattern) |
