diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_bsd.h | 4 | ||||
| -rw-r--r-- | executor/executor.cc | 44 | ||||
| -rw-r--r-- | executor/executor_bsd.h | 4 | ||||
| -rw-r--r-- | executor/executor_linux.h | 52 |
4 files changed, 77 insertions, 27 deletions
diff --git a/executor/common_bsd.h b/executor/common_bsd.h index 4ed45d0bd..e0beac33f 100644 --- a/executor/common_bsd.h +++ b/executor/common_bsd.h @@ -24,6 +24,7 @@ static void setup_usb(void) if (dir == NULL) fail("failed to open /dev"); + bool have_vhci = false; struct dirent* ent = NULL; while ((ent = readdir(dir)) != NULL) { if (ent->d_type != DT_CHR) @@ -34,7 +35,10 @@ static void setup_usb(void) snprintf(path, sizeof(path), "/dev/%s", ent->d_name); if (chmod(path, 0666)) failmsg("failed to chmod vhci", "path=%s", path); + have_vhci = true; } + if (!have_vhci) + fail("don't have any /dev/vhci devices"); closedir(dir); } diff --git a/executor/executor.cc b/executor/executor.cc index 6ac777ad6..2e4e01da8 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -369,7 +369,7 @@ struct kcov_comparison_t { typedef char kcov_comparison_size[sizeof(kcov_comparison_t) == 4 * sizeof(uint64) ? 1 : -1]; struct feature_t { - const char* name; + rpc::Feature id; void (*setup)(); }; @@ -1658,33 +1658,41 @@ bool kcov_comparison_t::operator<(const struct kcov_comparison_t& other) const } #endif // if SYZ_EXECUTOR_USES_SHMEM +#if !SYZ_HAVE_FEATURES +static feature_t features[] = {}; +#endif + void setup_features(char** enable, int n) { // This does any one-time setup for the requested features on the machine. // Note: this can be called multiple times and must be idempotent. flag_debug = true; + if (n != 1) + fail("setup: more than one feature"); + char* endptr = nullptr; + auto feature = static_cast<rpc::Feature>(strtoull(enable[0], &endptr, 10)); + if (endptr == enable[0] || (feature > rpc::Feature::ANY) || + __builtin_popcountll(static_cast<uint64>(feature)) > 1) + failmsg("setup: failed to parse feature", "feature='%s'", enable[0]); + if (feature == rpc::Feature::NONE) { #if SYZ_HAVE_FEATURES - setup_sysctl(); - setup_cgroups(); + setup_sysctl(); + setup_cgroups(); #endif #if SYZ_HAVE_SETUP_EXT - // This can be defined in common_ext.h. - setup_ext(); + // This can be defined in common_ext.h. + setup_ext(); #endif - for (int i = 0; i < n; i++) { - bool found = false; -#if SYZ_HAVE_FEATURES - for (unsigned f = 0; f < sizeof(features) / sizeof(features[0]); f++) { - if (strcmp(enable[i], features[f].name) == 0) { - features[f].setup(); - found = true; - break; - } + return; + } + for (size_t i = 0; i < sizeof(features) / sizeof(features[0]); i++) { + if (features[i].id == feature) { + features[i].setup(); + return; } -#endif - if (!found) - failmsg("setup features: unknown feature", "feature=%s", enable[i]); } + // Note: pkg/host knows about this error message. + fail("feature setup is not needed"); } void failmsg(const char* err, const char* msg, ...) @@ -1728,7 +1736,7 @@ void exitf(const char* msg, ...) vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, " (errno %d)\n", e); - doexit(0); + doexit(1); } void debug(const char* msg, ...) diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h index d88922417..6c2174360 100644 --- a/executor/executor_bsd.h +++ b/executor/executor_bsd.h @@ -182,8 +182,8 @@ static bool use_cover_edges(uint64 pc) #if GOOS_netbsd #define SYZ_HAVE_FEATURES 1 static feature_t features[] = { - {"usb", setup_usb}, - {"fault", setup_fault}, + {rpc::Feature::USBEmulation, setup_usb}, + {rpc::Feature::Fault, setup_fault}, }; static void setup_sysctl(void) diff --git a/executor/executor_linux.h b/executor/executor_linux.h index 578c65673..b8c98d3f7 100644 --- a/executor/executor_linux.h +++ b/executor/executor_linux.h @@ -256,13 +256,51 @@ NORETURN void doexit_thread(int status) } } +static void setup_nicvf() +{ + // This feature has custom checking precedure rather than just rely on running + // a simple program with this feature enabled b/c find_vf_interface cannot be made + // failing. It searches for the nic in init namespace, but then the nic is moved + // to one of testing namespace, so if number of procs is more than the number of devices, + // then some of them won't fine a nic (the code is also racy, more than one proc + // can find the same device and then moving it will fail for all but one). + // So we have to make find_vf_interface non-failing in case of failures, + // which means we cannot use it for feature checking. + if (open("/sys/bus/pci/devices/0000:00:11.0/", O_RDONLY | O_NONBLOCK) == -1) + fail("PCI device 0000:00:11.0 is not available"); +} + +static void setup_devlink_pci() +{ + // See comment in setup_nicvf. + if (open("/sys/bus/pci/devices/0000:00:10.0/", O_RDONLY | O_NONBLOCK) == -1) + fail("PCI device 0000:00:10.0 is not available"); +} + +static void setup_delay_kcov() +{ + is_kernel_64_bit = detect_kernel_bitness(); + cover_t cov = {}; + cov.fd = kCoverFd; + cover_open(&cov, false); + cover_mmap(&cov); + cov.data = nullptr; + cover_mmap(&cov); + // If delayed kcov mmap is not supported by the kernel, + // accesses to the second mapping will crash. + const_cast<volatile char*>(cov.data)[0] = 1; +} + #define SYZ_HAVE_FEATURES 1 static feature_t features[] = { - {"leak", setup_leak}, - {"fault", setup_fault}, - {"binfmt_misc", setup_binfmt_misc}, - {"kcsan", setup_kcsan}, - {"usb", setup_usb}, - {"802154", setup_802154}, - {"swap", setup_swap}, + {rpc::Feature::DelayKcovMmap, setup_delay_kcov}, + {rpc::Feature::Fault, setup_fault}, + {rpc::Feature::Leak, setup_leak}, + {rpc::Feature::KCSAN, setup_kcsan}, + {rpc::Feature::USBEmulation, setup_usb}, + {rpc::Feature::LRWPANEmulation, setup_802154}, + {rpc::Feature::BinFmtMisc, setup_binfmt_misc}, + {rpc::Feature::Swap, setup_swap}, + {rpc::Feature::NicVF, setup_nicvf}, + {rpc::Feature::DevlinkPCI, setup_devlink_pci}, }; |
