aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/common_bsd.h4
-rw-r--r--executor/executor.cc44
-rw-r--r--executor/executor_bsd.h4
-rw-r--r--executor/executor_linux.h52
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},
};