From d40d75d2d787b9d4f949422b88de18ede4ee20b6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Oct 2019 10:16:19 +0200 Subject: executor: move fixed pci devlink handle into network namespace In case there is a fixed pci devlink handle "pci/pci/0000:00:10.0" on the system (initial network namespace), it is moved to a working network namespace. Signed-off-by: Jiri Pirko --- executor/common_linux.h | 106 +++++++++++++++++++++++++- executor/executor.cc | 2 + pkg/csource/common.go | 1 + pkg/csource/generated.go | 107 +++++++++++++++++++++++++-- pkg/csource/options.go | 12 +++ pkg/csource/options_test.go | 18 ++--- pkg/host/host.go | 2 + pkg/host/host_linux.go | 8 ++ pkg/ipc/ipc.go | 1 + pkg/runtest/run.go | 3 + sys/linux/socket_netlink_generic_devlink.txt | 1 + syz-fuzzer/fuzzer.go | 3 + tools/syz-execprog/execprog.go | 3 + tools/syz-prog2c/prog2c.go | 1 + tools/syz-reprolist/reprolist.go | 4 + tools/syz-stress/stress.go | 3 + 16 files changed, 257 insertions(+), 18 deletions(-) diff --git a/executor/common_linux.h b/executor/common_linux.h index 1c0f51b5e..0b7e15a63 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -106,7 +106,7 @@ static bool write_file(const char* file, const char* what, ...) } #endif -#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE +#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE || SYZ_ENABLE_DEVLINK_PCI #include #include #include @@ -165,7 +165,7 @@ static void netlink_done(void) } #endif -static int netlink_send(int sock) +static int netlink_send_ext(int sock, uint16 reply_type, int* reply_len) { if (nlmsg.pos > nlmsg.buf + sizeof(nlmsg.buf) || nlmsg.nesting) fail("nlmsg overflow/bad nesting"); @@ -178,6 +178,12 @@ static int netlink_send(int sock) if (n != hdr->nlmsg_len) fail("short netlink write: %d/%d", n, hdr->nlmsg_len); n = recv(sock, nlmsg.buf, sizeof(nlmsg.buf), 0); + if (n < sizeof(struct nlmsghdr)) + fail("short netlink read: %d", n); + if (reply_len && hdr->nlmsg_type == reply_type) { + *reply_len = n; + return 0; + } if (n < sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr)) fail("short netlink read: %d", n); if (hdr->nlmsg_type != NLMSG_ERROR) @@ -185,6 +191,11 @@ static int netlink_send(int sock) return -((struct nlmsgerr*)(hdr + 1))->error; } +static int netlink_send(int sock) +{ + return netlink_send_ext(sock, 0, NULL); +} + #if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV static void netlink_add_device_impl(const char* type, const char* name) { @@ -238,6 +249,7 @@ static void netlink_add_hsr(int sock, const char* name, const char* slave1, cons } #endif +#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE static void netlink_device_change(int sock, const char* name, bool up, const char* master, const void* mac, int macsize) { @@ -289,6 +301,7 @@ static void netlink_add_addr6(int sock, const char* dev, const char* addr) debug("netlink: add addr %s dev %s: %s\n", addr, dev, strerror(err)); (void)err; } +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE static void netlink_add_neigh(int sock, const char* name, @@ -422,6 +435,83 @@ static void initialize_tun(void) } #endif +#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_ENABLE_DEVLINK_PCI +const int kInitNetNsFd = 239; // see kMaxFd +#endif + +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + +#include + +#define DEVLINK_FAMILY_NAME "devlink" + +#define DEVLINK_CMD_RELOAD 37 +#define DEVLINK_ATTR_BUS_NAME 1 +#define DEVLINK_ATTR_DEV_NAME 2 +#define DEVLINK_ATTR_NETNS_FD 137 + +static void netlink_devlink_netns_move(const char* bus_name, const char* dev_name, int netns_fd) +{ + struct genlmsghdr genlhdr; + struct nlattr* attr; + int sock, err, n; + uint16 id = 0; + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + if (sock == -1) + fail("socket(AF_NETLINK) failed\n"); + memset(&genlhdr, 0, sizeof(genlhdr)); + genlhdr.cmd = CTRL_CMD_GETFAMILY; + netlink_init(GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr)); + netlink_attr(CTRL_ATTR_FAMILY_NAME, DEVLINK_FAMILY_NAME, strlen(DEVLINK_FAMILY_NAME) + 1); + err = netlink_send_ext(sock, GENL_ID_CTRL, &n); + if (err) { + debug("netlink: failed to get devlink family id: %s\n", strerror(err)); + goto error; + } + attr = (struct nlattr*)(nlmsg.buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr))); + for (; (char*)attr < nlmsg.buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { + if (attr->nla_type == CTRL_ATTR_FAMILY_ID) { + id = *(uint16*)(attr + 1); + break; + } + } + if (!id) { + debug("netlink: failed to parse message for devlink family id\n"); + goto error; + } + recv(sock, nlmsg.buf, sizeof(nlmsg.buf), 0); /* recv ack */ + memset(&genlhdr, 0, sizeof(genlhdr)); + genlhdr.cmd = DEVLINK_CMD_RELOAD; + netlink_init(id, 0, &genlhdr, sizeof(genlhdr)); + netlink_attr(DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1); + netlink_attr(DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1); + netlink_attr(DEVLINK_ATTR_NETNS_FD, &netns_fd, sizeof(netns_fd)); + netlink_send(sock); +error: + close(sock); +} + +static void initialize_devlink_pci(void) +{ +#if SYZ_EXECUTOR + if (!flag_enable_devlink_pci) + return; +#endif + int netns = open("/proc/self/ns/net", O_RDONLY); + if (netns == -1) + fail("open(/proc/self/ns/net) failed"); + int ret = setns(kInitNetNsFd, 0); + if (ret == -1) + fail("set_ns(init_netns_fd) failed"); + netlink_devlink_netns_move("pci", "0000:00:10.0", netns); + ret = setns(netns, 0); + if (ret == -1) + fail("set_ns(this_netns_fd) failed"); + close(netns); +} +#endif + #if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV #include #include @@ -909,7 +999,6 @@ static long syz_open_pts(volatile long a0, volatile long a1) #include #include -const int kInitNetNsFd = 239; // see kMaxFd // syz_init_net_socket opens a socket in init net namespace. // Used for families that can only be created in init net namespace. static long syz_init_net_socket(volatile long domain, volatile long type, volatile long proto) @@ -1911,7 +2000,7 @@ static void sandbox_common() setpgrp(); setsid(); -#if SYZ_EXECUTOR || __NR_syz_init_net_socket +#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_ENABLE_DEVLINK_PCI int netns = open("/proc/self/ns/net", O_RDONLY); if (netns == -1) fail("open(/proc/self/ns/net) failed"); @@ -2049,6 +2138,9 @@ static int do_sandbox_none(void) if (unshare(CLONE_NEWNET)) { debug("unshare(CLONE_NEWNET): %d\n", errno); } +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE initialize_tun(); #endif @@ -2083,6 +2175,9 @@ static int do_sandbox_setuid(void) if (unshare(CLONE_NEWNET)) { debug("unshare(CLONE_NEWNET): %d\n", errno); } +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE initialize_tun(); #endif @@ -2135,6 +2230,9 @@ static int namespace_sandbox_proc(void* arg) // because we want the tun device in the test namespace. if (unshare(CLONE_NEWNET)) fail("unshare(CLONE_NEWNET)"); +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE // We setup tun here as it needs to be in the test net namespace, // which in turn needs to be in the test user namespace. diff --git a/executor/executor.cc b/executor/executor.cc index 30d497ea9..2016a8bf5 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -118,6 +118,7 @@ static bool flag_enable_net_dev; static bool flag_enable_net_reset; static bool flag_enable_cgroups; static bool flag_enable_close_fds; +static bool flag_enable_devlink_pci; static bool flag_collect_cover; static bool flag_dedup_cover; @@ -481,6 +482,7 @@ void parse_env_flags(uint64 flags) flag_enable_net_reset = flags & (1 << 8); flag_enable_cgroups = flags & (1 << 9); flag_enable_close_fds = flags & (1 << 10); + flag_enable_devlink_pci = flags & (1 << 11); } #if SYZ_EXECUTOR_USES_FORK_SERVER diff --git a/pkg/csource/common.go b/pkg/csource/common.go index e537ed724..67d31ad81 100644 --- a/pkg/csource/common.go +++ b/pkg/csource/common.go @@ -95,6 +95,7 @@ func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) { "SYZ_ENABLE_BINFMT_MISC": opts.EnableBinfmtMisc, "SYZ_ENABLE_CLOSE_FDS": opts.EnableCloseFds, "SYZ_ENABLE_KCSAN": opts.EnableKCSAN, + "SYZ_ENABLE_DEVLINK_PCI": opts.EnableDevlinkPCI, "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 bcfc0a01f..2266f86d6 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -1130,7 +1130,7 @@ static bool write_file(const char* file, const char* what, ...) } #endif -#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE +#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE || SYZ_ENABLE_DEVLINK_PCI #include #include #include @@ -1189,7 +1189,7 @@ static void netlink_done(void) } #endif -static int netlink_send(int sock) +static int netlink_send_ext(int sock, uint16 reply_type, int* reply_len) { if (nlmsg.pos > nlmsg.buf + sizeof(nlmsg.buf) || nlmsg.nesting) fail("nlmsg overflow/bad nesting"); @@ -1202,6 +1202,12 @@ static int netlink_send(int sock) if (n != hdr->nlmsg_len) fail("short netlink write: %d/%d", n, hdr->nlmsg_len); n = recv(sock, nlmsg.buf, sizeof(nlmsg.buf), 0); + if (n < sizeof(struct nlmsghdr)) + fail("short netlink read: %d", n); + if (reply_len && hdr->nlmsg_type == reply_type) { + *reply_len = n; + return 0; + } if (n < sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr)) fail("short netlink read: %d", n); if (hdr->nlmsg_type != NLMSG_ERROR) @@ -1209,6 +1215,11 @@ static int netlink_send(int sock) return -((struct nlmsgerr*)(hdr + 1))->error; } +static int netlink_send(int sock) +{ + return netlink_send_ext(sock, 0, NULL); +} + #if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV static void netlink_add_device_impl(const char* type, const char* name) { @@ -1262,6 +1273,7 @@ static void netlink_add_hsr(int sock, const char* name, const char* slave1, cons } #endif +#if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV || SYZ_TUN_ENABLE static void netlink_device_change(int sock, const char* name, bool up, const char* master, const void* mac, int macsize) { @@ -1313,6 +1325,7 @@ static void netlink_add_addr6(int sock, const char* dev, const char* addr) debug("netlink: add addr %s dev %s: %s\n", addr, dev, strerror(err)); (void)err; } +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE static void netlink_add_neigh(int sock, const char* name, @@ -1432,6 +1445,83 @@ static void initialize_tun(void) } #endif +#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_ENABLE_DEVLINK_PCI +const int kInitNetNsFd = 239; +#endif + +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + +#include + +#define DEVLINK_FAMILY_NAME "devlink" + +#define DEVLINK_CMD_RELOAD 37 +#define DEVLINK_ATTR_BUS_NAME 1 +#define DEVLINK_ATTR_DEV_NAME 2 +#define DEVLINK_ATTR_NETNS_FD 137 + +static void netlink_devlink_netns_move(const char* bus_name, const char* dev_name, int netns_fd) +{ + struct genlmsghdr genlhdr; + struct nlattr* attr; + int sock, err, n; + uint16 id = 0; + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); + if (sock == -1) + fail("socket(AF_NETLINK) failed\n"); + memset(&genlhdr, 0, sizeof(genlhdr)); + genlhdr.cmd = CTRL_CMD_GETFAMILY; + netlink_init(GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr)); + netlink_attr(CTRL_ATTR_FAMILY_NAME, DEVLINK_FAMILY_NAME, strlen(DEVLINK_FAMILY_NAME) + 1); + err = netlink_send_ext(sock, GENL_ID_CTRL, &n); + if (err) { + debug("netlink: failed to get devlink family id: %s\n", strerror(err)); + goto error; + } + attr = (struct nlattr*)(nlmsg.buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr))); + for (; (char*)attr < nlmsg.buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { + if (attr->nla_type == CTRL_ATTR_FAMILY_ID) { + id = *(uint16*)(attr + 1); + break; + } + } + if (!id) { + debug("netlink: failed to parse message for devlink family id\n"); + goto error; + } + recv(sock, nlmsg.buf, sizeof(nlmsg.buf), 0); /* recv ack */ + memset(&genlhdr, 0, sizeof(genlhdr)); + genlhdr.cmd = DEVLINK_CMD_RELOAD; + netlink_init(id, 0, &genlhdr, sizeof(genlhdr)); + netlink_attr(DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1); + netlink_attr(DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1); + netlink_attr(DEVLINK_ATTR_NETNS_FD, &netns_fd, sizeof(netns_fd)); + netlink_send(sock); +error: + close(sock); +} + +static void initialize_devlink_pci(void) +{ +#if SYZ_EXECUTOR + if (!flag_enable_devlink_pci) + return; +#endif + int netns = open("/proc/self/ns/net", O_RDONLY); + if (netns == -1) + fail("open(/proc/self/ns/net) failed"); + int ret = setns(kInitNetNsFd, 0); + if (ret == -1) + fail("set_ns(init_netns_fd) failed"); + netlink_devlink_netns_move("pci", "0000:00:10.0", netns); + ret = setns(netns, 0); + if (ret == -1) + fail("set_ns(this_netns_fd) failed"); + close(netns); +} +#endif + #if SYZ_EXECUTOR || SYZ_ENABLE_NETDEV #include #include @@ -2671,8 +2761,6 @@ static long syz_open_pts(volatile long a0, volatile long a1) #include #include #include - -const int kInitNetNsFd = 239; static long syz_init_net_socket(volatile long domain, volatile long type, volatile long proto) { int netns = open("/proc/self/ns/net", O_RDONLY); @@ -4571,7 +4659,7 @@ static void sandbox_common() setpgrp(); setsid(); -#if SYZ_EXECUTOR || __NR_syz_init_net_socket +#if SYZ_EXECUTOR || __NR_syz_init_net_socket || SYZ_ENABLE_DEVLINK_PCI int netns = open("/proc/self/ns/net", O_RDONLY); if (netns == -1) fail("open(/proc/self/ns/net) failed"); @@ -4685,6 +4773,9 @@ static int do_sandbox_none(void) if (unshare(CLONE_NEWNET)) { debug("unshare(CLONE_NEWNET): %d\n", errno); } +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE initialize_tun(); #endif @@ -4719,6 +4810,9 @@ static int do_sandbox_setuid(void) if (unshare(CLONE_NEWNET)) { debug("unshare(CLONE_NEWNET): %d\n", errno); } +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE initialize_tun(); #endif @@ -4763,6 +4857,9 @@ static int namespace_sandbox_proc(void* arg) #endif if (unshare(CLONE_NEWNET)) fail("unshare(CLONE_NEWNET)"); +#if SYZ_EXECUTOR || SYZ_ENABLE_DEVLINK_PCI + initialize_devlink_pci(); +#endif #if SYZ_EXECUTOR || SYZ_TUN_ENABLE initialize_tun(); #endif diff --git a/pkg/csource/options.go b/pkg/csource/options.go index 7ad8c1d9c..a4cc45d45 100644 --- a/pkg/csource/options.go +++ b/pkg/csource/options.go @@ -38,6 +38,7 @@ type Options struct { EnableBinfmtMisc bool `json:"binfmt_misc,omitempty"` EnableCloseFds bool `json:"close_fds"` EnableKCSAN bool `json:"kcsan,omitempty"` + EnableDevlinkPCI bool `json:"devlinkpci,omitempty"` UseTmpDir bool `json:"tmpdir,omitempty"` HandleSegv bool `json:"segv,omitempty"` @@ -127,6 +128,9 @@ func (opts Options) checkLinuxOnly(OS string) error { if opts.EnableKCSAN { return fmt.Errorf("option EnableKCSAN is not supported on %v", OS) } + if opts.EnableDevlinkPCI { + return fmt.Errorf("option EnableDevlinkPCI is not supported on %v", OS) + } if opts.Sandbox == sandboxNamespace || (opts.Sandbox == sandboxSetuid && !(OS == openbsd || OS == freebsd || OS == netbsd)) || opts.Sandbox == sandboxAndroidUntrustedApp { @@ -154,6 +158,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options { EnableCgroups: true, EnableBinfmtMisc: true, EnableCloseFds: true, + EnableDevlinkPCI: true, UseTmpDir: true, HandleSegv: true, Repro: true, @@ -165,6 +170,12 @@ func DefaultOpts(cfg *mgrconfig.Config) Options { opts.EnableCgroups = false opts.EnableBinfmtMisc = false opts.EnableCloseFds = false + opts.EnableDevlinkPCI = false + } + if cfg.Sandbox == "" || cfg.Sandbox == "setuid" { + opts.EnableNetReset = false + } + if err := opts.Check(cfg.TargetOS); err != nil { } if cfg.Sandbox == "" || cfg.Sandbox == "setuid" { opts.EnableNetReset = false @@ -244,6 +255,7 @@ func defaultFeatures(value bool) Features { "cgroups": {"setup cgroups for testing", value}, "binfmt_misc": {"setup binfmt_misc for testing", value}, "close_fds": {"close fds after each program", value}, + "devlink_pci": {"setup devlink PCI device", value}, } } diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go index 13afa84d3..34c64f9e2 100644 --- a/pkg/csource/options_test.go +++ b/pkg/csource/options_test.go @@ -213,31 +213,31 @@ func TestParseFeaturesFlags(t *testing.T) { Features map[string]bool }{ {"none", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, "devlink_pci": true, }}, {"none", "none", false, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, "devlink_pci": false, }}, {"all", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, "devlink_pci": true, }}, {"", "none", true, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, "devlink_pci": false, }}, {"none", "all", true, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, "devlink_pci": false, }}, {"none", "", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, "devlink_pci": true, }}, {"tun,net_dev", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, + "tun": true, "net_dev": true, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, "devlink_pci": false, }}, {"none", "cgroups,net_dev", true, map[string]bool{ - "tun": true, "net_dev": false, "net_reset": true, "cgroups": false, "binfmt_misc": true, "close_fds": true, + "tun": true, "net_dev": false, "net_reset": true, "cgroups": false, "binfmt_misc": true, "close_fds": true, "devlink_pci": true, }}, {"close_fds", "none", true, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": true, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": true, "devlink_pci": false, }}, } for i, test := range tests { diff --git a/pkg/host/host.go b/pkg/host/host.go index dbd3b9ec3..f18233085 100644 --- a/pkg/host/host.go +++ b/pkg/host/host.go @@ -76,6 +76,7 @@ const ( FeatureNetworkInjection FeatureNetworkDevices FeatureKCSAN + FeatureDevlinkPCI numFeatures ) @@ -108,6 +109,7 @@ func Check(target *prog.Target) (*Features, error) { FeatureNetworkInjection: {Name: "net packet injection", Reason: unsupported}, FeatureNetworkDevices: {Name: "net device setup", Reason: unsupported}, FeatureKCSAN: {Name: "concurrency sanitizer", Reason: unsupported}, + FeatureDevlinkPCI: {Name: "devlink PCI setup", Reason: unsupported}, } switch target.OS { case "akaros", "fuchsia", "test": diff --git a/pkg/host/host_linux.go b/pkg/host/host_linux.go index a1d5ff1b3..c908ee411 100644 --- a/pkg/host/host_linux.go +++ b/pkg/host/host_linux.go @@ -396,6 +396,7 @@ func init() { checkFeature[FeatureNetworkInjection] = checkNetworkInjection checkFeature[FeatureNetworkDevices] = unconditionallyEnabled checkFeature[FeatureKCSAN] = checkKCSAN + checkFeature[FeatureDevlinkPCI] = checkDevlinkPCI } func checkCoverage() string { @@ -564,3 +565,10 @@ func checkKCSAN() string { } return "" } + +func checkDevlinkPCI() string { + if err := osutil.IsAccessible("/sys/bus/pci/devices/0000:00:10.0/"); err != nil { + return "PCI device 0000:00:10.0 is not available" + } + return "" +} diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index aea594fba..34b4ce2d0 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -37,6 +37,7 @@ const ( FlagEnableNetReset // reset network namespace between programs FlagEnableCgroups // setup cgroups for testing FlagEnableCloseFds // close fds after each program + FlagEnableDevlinkPCI // setup devlink PCI device // Executor does not know about these: FlagUseShmem // use shared memory instead of pipes for communication FlagUseForkServer // use extended protocol with handshake diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go index 0248b0b31..633e67455 100644 --- a/pkg/runtest/run.go +++ b/pkg/runtest/run.go @@ -381,6 +381,9 @@ func (ctx *Context) createSyzTest(p *prog.Prog, sandbox string, threaded, cov bo } cfg.Flags |= ipc.FlagEnableNetReset cfg.Flags |= ipc.FlagEnableCgroups + if ctx.Features[host.FeatureDevlinkPCI].Enabled { + cfg.Flags |= ipc.FlagEnableDevlinkPCI + } req := &RunRequest{ P: p, Cfg: cfg, diff --git a/sys/linux/socket_netlink_generic_devlink.txt b/sys/linux/socket_netlink_generic_devlink.txt index f090e4104..7a89fc648 100644 --- a/sys/linux/socket_netlink_generic_devlink.txt +++ b/sys/linux/socket_netlink_generic_devlink.txt @@ -25,6 +25,7 @@ devlink_handle_nsim { devlink_handle_pci { DEVLINK_ATTR_BUS_NAME nlattr[DEVLINK_ATTR_BUS_NAME, string["pci"]] +# 0000:00:10.0 is a fixed pci address what is moved from initial network namespace by initialize_devlink() DEVLINK_ATTR_DEV_NAME nlattr[DEVLINK_ATTR_DEV_NAME, string["0000:00:10.0"]] } [packed, align_4] diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index 41da54d1c..5cc7df893 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -214,6 +214,9 @@ func main() { config.Flags |= ipc.FlagEnableNetReset config.Flags |= ipc.FlagEnableCgroups config.Flags |= ipc.FlagEnableCloseFds + if r.CheckResult.Features[host.FeatureDevlinkPCI].Enabled { + config.Flags |= ipc.FlagEnableDevlinkPCI + } if *flagRunTest { runTest(target, manager, *flagName, config.Executor) diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go index 32ba987ae..909715b7c 100644 --- a/tools/syz-execprog/execprog.go +++ b/tools/syz-execprog/execprog.go @@ -326,5 +326,8 @@ func createConfig(target *prog.Target, if featuresFlags["close_fds"].Enabled { config.Flags |= ipc.FlagEnableCloseFds } + if featuresFlags["devlink_pci"].Enabled && features[host.FeatureDevlinkPCI].Enabled { + config.Flags |= ipc.FlagEnableDevlinkPCI + } return config, execOpts } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index de704b353..c1a3f50ef 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -88,6 +88,7 @@ func main() { EnableBinfmtMisc: features["binfmt_misc"].Enabled, EnableCloseFds: features["close_fds"].Enabled, EnableKCSAN: features["kcsan"].Enabled, + EnableDevlinkPCI: features["devlink_pci"].Enabled, UseTmpDir: *flagUseTmpDir, HandleSegv: *flagHandleSegv, Repro: false, diff --git a/tools/syz-reprolist/reprolist.go b/tools/syz-reprolist/reprolist.go index 85e328fac..5d082b37e 100644 --- a/tools/syz-reprolist/reprolist.go +++ b/tools/syz-reprolist/reprolist.go @@ -215,6 +215,10 @@ func createProg2CArgs(bug *dashapi.LoadBugResp, opts csource.Options, file strin if opts.EnableCloseFds && haveCloseFds { enable = append(enable, "close_fds") } + if opts.EnableDevlinkPCI { + enable = append(enable, "devlink_pci") + flags = append(flags, "-devlinkpci") + } if !haveEnableFlag { args = append(args, flags...) } else if len(enable) != 0 { diff --git a/tools/syz-stress/stress.go b/tools/syz-stress/stress.go index af78906ab..9323013c0 100644 --- a/tools/syz-stress/stress.go +++ b/tools/syz-stress/stress.go @@ -98,6 +98,9 @@ func main() { if featuresFlags["close_fds"].Enabled { config.Flags |= ipc.FlagEnableCloseFds } + if featuresFlags["devlink_pci"].Enabled && features[host.FeatureDevlinkPCI].Enabled { + config.Flags |= ipc.FlagEnableDevlinkPCI + } if err = host.Setup(target, features, featuresFlags, config.Executor); err != nil { log.Fatal(err) } -- cgit mrf-deployment