aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2020-04-01 19:37:07 +0200
committerAndrey Konovalov <andreyknvl@gmail.com>2020-04-03 12:42:06 +0200
commit09ff5abc02a0e38bb275a91380fc03d6cd0d47a5 (patch)
treea39602cd91fbad39b6e10a8455b58d7f59831965
parentca1beb07f02e67ba2faa81a5b56b061111f818f3 (diff)
csource, executor: add usb emulation feature
The feature gets enabled when /dev/raw-gadget is present and accessible. With this feature enabled, executor will do chmod 0666 /dev/raw-gadget on startup, which makes it possible to do USB fuzzing in setuid and namespace sandboxes. There should be no backwards compatibility issues with syz reproducers that don't explicitly enable this feature, as they currently only work in none sandbox.
-rw-r--r--executor/common.h3
-rw-r--r--executor/common_linux.h8
-rw-r--r--executor/executor_linux.h1
-rw-r--r--pkg/csource/common.go1
-rw-r--r--pkg/csource/generated.go11
-rw-r--r--pkg/csource/options.go6
-rw-r--r--pkg/csource/options_test.go9
-rw-r--r--pkg/host/features.go5
-rw-r--r--pkg/host/features_linux.go3
-rw-r--r--pkg/host/syscalls_linux.go4
-rw-r--r--pkg/repro/repro.go8
-rw-r--r--tools/syz-prog2c/prog2c.go1
12 files changed, 57 insertions, 3 deletions
diff --git a/executor/common.h b/executor/common.h
index 8591110be..04e51cd2a 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -708,6 +708,9 @@ int main(void)
#if SYZ_KCSAN
setup_kcsan();
#endif
+#if SYZ_USB
+ setup_usb();
+#endif
#if SYZ_HANDLE_SEGV
install_segv_handler();
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 30b6309c9..772d98c03 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -3514,3 +3514,11 @@ static void setup_kcsan_filterlist(char** frames, int nframes, bool blacklist)
#define SYZ_HAVE_KCSAN 1
#endif
#endif
+
+#if SYZ_EXECUTOR || SYZ_USB
+static void setup_usb()
+{
+ if (chmod("/dev/raw-gadget", 0666))
+ fail("failed to chmod /dev/raw-gadget");
+}
+#endif
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index d4220c23f..33f4e377a 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -224,6 +224,7 @@ static feature_t features[] = {
{"fault", setup_fault},
{"binfmt_misc", setup_binfmt_misc},
{"kcsan", setup_kcsan},
+ {"usb", setup_usb},
};
static void setup_machine()
diff --git a/pkg/csource/common.go b/pkg/csource/common.go
index 542cf36bb..96d719b67 100644
--- a/pkg/csource/common.go
+++ b/pkg/csource/common.go
@@ -112,6 +112,7 @@ func commonDefines(p *prog.Prog, opts Options) map[string]bool {
"SYZ_CLOSE_FDS": opts.CloseFDs,
"SYZ_KCSAN": opts.KCSAN,
"SYZ_DEVLINK_PCI": opts.DevlinkPCI,
+ "SYZ_USB": opts.USB,
"SYZ_USE_TMP_DIR": opts.UseTmpDir,
"SYZ_HANDLE_SEGV": opts.HandleSegv,
"SYZ_REPRO": opts.Repro,
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 3bf6c0aa8..98619862b 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -7066,6 +7066,14 @@ static void setup_kcsan_filterlist(char** frames, int nframes, bool blacklist)
#endif
#endif
+#if SYZ_EXECUTOR || SYZ_USB
+static void setup_usb()
+{
+ if (chmod("/dev/raw-gadget", 0666))
+ fail("failed to chmod /dev/raw-gadget");
+}
+#endif
+
#elif GOOS_test
#include <stdlib.h>
@@ -7549,6 +7557,9 @@ int main(void)
#if SYZ_KCSAN
setup_kcsan();
#endif
+#if SYZ_USB
+ setup_usb();
+#endif
#if SYZ_HANDLE_SEGV
install_segv_handler();
diff --git a/pkg/csource/options.go b/pkg/csource/options.go
index 27529f429..01389240c 100644
--- a/pkg/csource/options.go
+++ b/pkg/csource/options.go
@@ -39,6 +39,7 @@ type Options struct {
CloseFDs bool `json:"close_fds"`
KCSAN bool `json:"kcsan,omitempty"`
DevlinkPCI bool `json:"devlinkpci,omitempty"`
+ USB bool `json:"usb,omitempty"`
UseTmpDir bool `json:"tmpdir,omitempty"`
HandleSegv bool `json:"segv,omitempty"`
@@ -131,6 +132,9 @@ func (opts Options) checkLinuxOnly(OS string) error {
if opts.DevlinkPCI {
return fmt.Errorf("option DevlinkPCI is not supported on %v", OS)
}
+ if opts.USB {
+ return fmt.Errorf("option USB is not supported on %v", OS)
+ }
if opts.Sandbox == sandboxNamespace ||
(opts.Sandbox == sandboxSetuid && !(OS == openbsd || OS == freebsd || OS == netbsd)) ||
opts.Sandbox == sandboxAndroid {
@@ -171,6 +175,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options {
opts.BinfmtMisc = false
opts.CloseFDs = false
opts.DevlinkPCI = false
+ opts.USB = false
}
if cfg.Sandbox == "" || cfg.Sandbox == "setuid" {
opts.NetReset = false
@@ -250,6 +255,7 @@ func defaultFeatures(value bool) Features {
"binfmt_misc": {"setup binfmt_misc for testing", value},
"close_fds": {"close fds after each program", value},
"devlink_pci": {"setup devlink PCI device", value},
+ "usb": {"setup and use /dev/raw-gadget for USB emulation", value},
}
}
diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go
index b15783359..d4e1832e7 100644
--- a/pkg/csource/options_test.go
+++ b/pkg/csource/options_test.go
@@ -220,6 +220,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": true,
"close_fds": true,
"devlink_pci": true,
+ "usb": true,
}},
{"none", "none", false, map[string]bool{
"tun": false,
@@ -229,6 +230,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": false,
"close_fds": false,
"devlink_pci": false,
+ "usb": false,
}},
{"all", "none", true, map[string]bool{
"tun": true,
@@ -238,6 +240,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": true,
"close_fds": true,
"devlink_pci": true,
+ "usb": true,
}},
{"", "none", true, map[string]bool{
"tun": false,
@@ -247,6 +250,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": false,
"close_fds": false,
"devlink_pci": false,
+ "usb": false,
}},
{"none", "all", true, map[string]bool{
"tun": false,
@@ -256,6 +260,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": false,
"close_fds": false,
"devlink_pci": false,
+ "usb": false,
}},
{"none", "", true, map[string]bool{
"tun": true,
@@ -265,6 +270,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": true,
"close_fds": true,
"devlink_pci": true,
+ "usb": true,
}},
{"tun,net_dev", "none", true, map[string]bool{
"tun": true,
@@ -274,6 +280,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": false,
"close_fds": false,
"devlink_pci": false,
+ "usb": false,
}},
{"none", "cgroups,net_dev", true, map[string]bool{
"tun": true,
@@ -283,6 +290,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": true,
"close_fds": true,
"devlink_pci": true,
+ "usb": true,
}},
{"close_fds", "none", true, map[string]bool{
"tun": false,
@@ -292,6 +300,7 @@ func TestParseFeaturesFlags(t *testing.T) {
"binfmt_misc": false,
"close_fds": true,
"devlink_pci": false,
+ "usb": false,
}},
}
for i, test := range tests {
diff --git a/pkg/host/features.go b/pkg/host/features.go
index 3bc0127b6..707757755 100644
--- a/pkg/host/features.go
+++ b/pkg/host/features.go
@@ -25,6 +25,7 @@ const (
FeatureNetDevices
FeatureKCSAN
FeatureDevlinkPCI
+ FeatureUSBEmulation
numFeatures
)
@@ -62,6 +63,7 @@ func Check(target *prog.Target) (*Features, error) {
FeatureNetDevices: {Name: "net device setup", Reason: unsupported},
FeatureKCSAN: {Name: "concurrency sanitizer", Reason: unsupported},
FeatureDevlinkPCI: {Name: "devlink PCI setup", Reason: unsupported},
+ FeatureUSBEmulation: {Name: "USB emulation", Reason: unsupported},
}
if targets.Get(target.OS, target.Arch).HostFuzzer {
return res, nil
@@ -99,6 +101,9 @@ func Setup(target *prog.Target, features *Features, featureFlags csource.Feature
if features[FeatureKCSAN].Enabled {
args = append(args, "kcsan")
}
+ if features[FeatureUSBEmulation].Enabled {
+ args = append(args, "usb")
+ }
_, err := osutil.RunCmd(time.Minute, "", executor, args...)
return err
}
diff --git a/pkg/host/features_linux.go b/pkg/host/features_linux.go
index 7b4b7b243..8c6f63004 100644
--- a/pkg/host/features_linux.go
+++ b/pkg/host/features_linux.go
@@ -27,6 +27,7 @@ func init() {
checkFeature[FeatureNetDevices] = unconditionallyEnabled
checkFeature[FeatureKCSAN] = checkKCSAN
checkFeature[FeatureDevlinkPCI] = checkDevlinkPCI
+ checkFeature[FeatureUSBEmulation] = checkUSBEmulation
}
func checkCoverage() string {
@@ -183,7 +184,7 @@ func checkNetInjection() string {
return ""
}
-func checkUSBInjection() string {
+func checkUSBEmulation() string {
if err := osutil.IsAccessible("/dev/raw-gadget"); err != nil {
return err.Error()
}
diff --git a/pkg/host/syscalls_linux.go b/pkg/host/syscalls_linux.go
index 693ec3f3e..dd89733c0 100644
--- a/pkg/host/syscalls_linux.go
+++ b/pkg/host/syscalls_linux.go
@@ -177,7 +177,7 @@ func isSupportedSyzkall(sandbox string, c *prog.Syscall) (bool, string) {
if !strings.Contains(fname, "#") {
panic(fmt.Sprintf("%v does not contain # in the file name (should be openat)", c.Name))
}
- if checkUSBInjection() == "" {
+ if checkUSBEmulation() == "" {
// These entries might not be available at boot time,
// but will be created by connected USB devices.
USBDevicePrefixes := []string{
@@ -215,7 +215,7 @@ func isSupportedSyzkall(sandbox string, c *prog.Syscall) (bool, string) {
return reason == "", reason
case "syz_usb_connect", "syz_usb_connect_ath9k", "syz_usb_disconnect",
"syz_usb_control_io", "syz_usb_ep_write", "syz_usb_ep_read":
- reason := checkUSBInjection()
+ reason := checkUSBEmulation()
return reason == "", reason
case "syz_kvm_setup_cpu":
switch c.Name {
diff --git a/pkg/repro/repro.go b/pkg/repro/repro.go
index 6de117df6..9c05f34ba 100644
--- a/pkg/repro/repro.go
+++ b/pkg/repro/repro.go
@@ -844,6 +844,7 @@ var cSimplifies = append(progSimplifies, []Simplify{
opts.BinfmtMisc = false
opts.CloseFDs = false
opts.DevlinkPCI = false
+ opts.USB = false
return true
},
func(opts *csource.Options) bool {
@@ -898,6 +899,13 @@ var cSimplifies = append(progSimplifies, []Simplify{
return true
},
func(opts *csource.Options) bool {
+ if !opts.USB {
+ return false
+ }
+ opts.USB = false
+ return true
+ },
+ func(opts *csource.Options) bool {
if !opts.UseTmpDir || opts.Sandbox == "namespace" || opts.Cgroups {
return false
}
diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go
index 92c94da34..5d161929e 100644
--- a/tools/syz-prog2c/prog2c.go
+++ b/tools/syz-prog2c/prog2c.go
@@ -89,6 +89,7 @@ func main() {
CloseFDs: features["close_fds"].Enabled,
KCSAN: features["kcsan"].Enabled,
DevlinkPCI: features["devlink_pci"].Enabled,
+ USB: features["usb"].Enabled,
UseTmpDir: *flagUseTmpDir,
HandleSegv: *flagHandleSegv,
Repro: false,