mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 03:19:51 +00:00
all: integrate with mac80211_hwsim
Two virtual wireless devices are instantiated during network devices initialization. A new flag (-wifi) is added that controls whether these virtual wifi devices are instantiated and configured during proc initialization. Also, two new pseudo syscalls are added: 1. syz_80211_inject_frame(mac_addr, packet, packet_len) -- injects an arbitrary packet into the wireless stack. It is injected as if it originated from the device identitied by mac_addr. 2. syz_80211_join_ibss(interface_name, ssid, ssid_len, mode) -- puts a specific network interface into IBSS state and joins an IBSS network. Arguments of syz_80211_join_ibss: 1) interface_name -- null-terminated string that identifies a wireless interface 2) ssid, ssid_len -- SSID of an IBSS network to join to 3) mode -- mode of syz_80211_join_ibss operation (see below) Modes of operation: JOIN_IBSS_NO_SCAN (0x0) -- channel scan is not performed and syz_80211_join_ibss waits until the interface reaches IF_OPER_UP. JOIN_IBSS_BG_SCAN (0x1) -- channel scan is performed (takes ~ 9 seconds), syz_80211_join_ibss does not await IF_OPER_UP. JOIN_IBSS_BG_NO_SCAN (0x2) -- channel scan is not performed, syz_80211_join_ibss does not await IF_OPER_UP. Local testing ensured that these syscalls are indeed able to set up an operating network and inject packets into mac80211.
This commit is contained in:
parent
1125444eb8
commit
9133037195
@ -107,7 +107,8 @@ static bool write_file(const char* file, const char* what, ...)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || __NR_syz_genetlink_get_family_id
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || \
|
||||||
|
__NR_syz_genetlink_get_family_id || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -201,7 +202,8 @@ static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
|
|||||||
return ((struct nlmsgerr*)(hdr + 1))->error;
|
return ((struct nlmsgerr*)(hdr + 1))->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || \
|
||||||
|
__NR_syz_80211_join_ibss || __NR_syz_80211_inject_frame
|
||||||
static int netlink_send(struct nlmsg* nlmsg, int sock)
|
static int netlink_send(struct nlmsg* nlmsg, int sock)
|
||||||
{
|
{
|
||||||
return netlink_send_ext(nlmsg, sock, 0, NULL);
|
return netlink_send_ext(nlmsg, sock, 0, NULL);
|
||||||
@ -471,7 +473,7 @@ static void netlink_add_neigh(struct nlmsg* nlmsg, int sock, const char* name,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI
|
||||||
static struct nlmsg nlmsg;
|
static struct nlmsg nlmsg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -728,6 +730,278 @@ static void initialize_devlink_pci(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss
|
||||||
|
|
||||||
|
#define WIFI_INITIAL_DEVICE_COUNT 2
|
||||||
|
#define WIFI_MAC_BASE \
|
||||||
|
{ \
|
||||||
|
0x08, 0x02, 0x11, 0x00, 0x00, 0x00 \
|
||||||
|
}
|
||||||
|
#define WIFI_IBSS_BSSID \
|
||||||
|
{ \
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50 \
|
||||||
|
}
|
||||||
|
#define WIFI_IBSS_SSID \
|
||||||
|
{ \
|
||||||
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 \
|
||||||
|
}
|
||||||
|
#define WIFI_DEFAULT_FREQUENCY 2412
|
||||||
|
#define WIFI_DEFAULT_SIGNAL 0
|
||||||
|
#define WIFI_DEFAULT_RX_RATE 1
|
||||||
|
|
||||||
|
// consts from drivers/net/wireless/mac80211_hwsim.h
|
||||||
|
#define HWSIM_CMD_REGISTER 1
|
||||||
|
#define HWSIM_CMD_FRAME 2
|
||||||
|
#define HWSIM_CMD_NEW_RADIO 4
|
||||||
|
#define HWSIM_ATTR_SUPPORT_P2P_DEVICE 14
|
||||||
|
#define HWSIM_ATTR_PERM_ADDR 22
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_join_ibss
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
// From linux/if.h, but we cannot include the file as it conflicts with net/if.h
|
||||||
|
#define IF_OPER_UP 6
|
||||||
|
|
||||||
|
// IBSS parameters for nl80211_join_ibss
|
||||||
|
struct join_ibss_props {
|
||||||
|
int wiphy_freq;
|
||||||
|
bool wiphy_freq_fixed;
|
||||||
|
uint8* mac;
|
||||||
|
uint8* ssid;
|
||||||
|
int ssid_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int set_interface_state(const char* interface_name, int on)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("set_interface_state: failed to open socket, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strcpy(ifr.ifr_name, interface_name);
|
||||||
|
int ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("set_interface_state: failed to execute SIOCGIFFLAGS, ret %d\n", ret);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on)
|
||||||
|
ifr.ifr_flags |= IFF_UP;
|
||||||
|
else
|
||||||
|
ifr.ifr_flags &= ~IFF_UP;
|
||||||
|
|
||||||
|
ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("set_interface_state: failed to execute SIOCSIFFLAGS, ret %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_set_interface(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex, uint32 iftype)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = NL80211_CMD_SET_INTERFACE;
|
||||||
|
netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFTYPE, &iftype, sizeof(iftype));
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("nl80211_set_interface failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_join_ibss(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex, struct join_ibss_props* props)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = NL80211_CMD_JOIN_IBSS;
|
||||||
|
netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_SSID, props->ssid, props->ssid_len);
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_WIPHY_FREQ, &(props->wiphy_freq), sizeof(props->wiphy_freq));
|
||||||
|
if (props->mac)
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_MAC, props->mac, ETH_ALEN);
|
||||||
|
if (props->wiphy_freq_fixed)
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_FREQ_FIXED, NULL, 0);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("nl80211_join_ibss failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_ifla_operstate(struct nlmsg* nlmsg, int ifindex)
|
||||||
|
{
|
||||||
|
struct ifinfomsg info;
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.ifi_family = AF_UNSPEC;
|
||||||
|
info.ifi_index = ifindex;
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if (sock == -1) {
|
||||||
|
debug("get_ifla_operstate: socket failed: %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
netlink_init(nlmsg, RTM_GETLINK, 0, &info, sizeof(info));
|
||||||
|
int n;
|
||||||
|
int err = netlink_send_ext(nlmsg, sock, RTM_NEWLINK, &n);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
debug("get_ifla_operstate: failed to query: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rtattr* attr = IFLA_RTA(NLMSG_DATA(nlmsg->buf));
|
||||||
|
for (; RTA_OK(attr, n); attr = RTA_NEXT(attr, n)) {
|
||||||
|
if (attr->rta_type == IFLA_OPERSTATE)
|
||||||
|
return *((int32_t*)RTA_DATA(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int await_ifla_operstate(struct nlmsg* nlmsg, char* interface, int operstate)
|
||||||
|
{
|
||||||
|
int ifindex = if_nametoindex(interface);
|
||||||
|
while (true) {
|
||||||
|
usleep(1000); // 1 ms
|
||||||
|
int ret = get_ifla_operstate(nlmsg, ifindex);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret == operstate)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_setup_ibss_interface(struct nlmsg* nlmsg, int sock, int nl80211_family_id, char* interface, struct join_ibss_props* ibss_props)
|
||||||
|
{
|
||||||
|
int ifindex = if_nametoindex(interface);
|
||||||
|
if (ifindex == 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: if_nametoindex failed for %.32s, ret 0\n", interface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = nl80211_set_interface(nlmsg, sock, nl80211_family_id, ifindex, NL80211_IFTYPE_ADHOC);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: nl80211_set_interface failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_interface_state(interface, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: set_interface_state failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nl80211_join_ibss(nlmsg, sock, nl80211_family_id, ifindex, ibss_props);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: nl80211_join_ibss failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
static int hwsim80211_create_device(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8 mac_addr[ETH_ALEN])
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_NEW_RADIO;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_SUPPORT_P2P_DEVICE, NULL, 0);
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_PERM_ADDR, mac_addr, ETH_ALEN);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim80211_create_device failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initialize_wifi_devices(void)
|
||||||
|
{
|
||||||
|
// Set up virtual wifi devices and join them into an IBSS network.
|
||||||
|
// An IBSS network is created here in order to put these devices in an operable state right from
|
||||||
|
// the beginning. It has the following positive effects.
|
||||||
|
// 1. Frame injection becomes possible from the very start.
|
||||||
|
// 2. A number of nl80211 commands expect their target wireless interface to be in an operable state.
|
||||||
|
// 3. Simplification of reproducer generation - in many cases the reproducer will not have to spend time
|
||||||
|
// selecting system calls that set up the environment.
|
||||||
|
//
|
||||||
|
// IBSS network was chosen as the simplest network type to begin with.
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR
|
||||||
|
if (!flag_wifi)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
uint8 mac_addr[6] = WIFI_MAC_BASE;
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("initialize_wifi_devices: failed to create socket (%d)\n", errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwsim_family_id = netlink_query_family_id(&nlmsg, sock, "MAC80211_HWSIM");
|
||||||
|
int nl80211_family_id = netlink_query_family_id(&nlmsg, sock, "nl80211");
|
||||||
|
uint8 ssid[] = WIFI_IBSS_SSID;
|
||||||
|
uint8 bssid[] = WIFI_IBSS_BSSID;
|
||||||
|
struct join_ibss_props ibss_props = {
|
||||||
|
.wiphy_freq = WIFI_DEFAULT_FREQUENCY, .wiphy_freq_fixed = true, .mac = bssid, .ssid = ssid, .ssid_len = sizeof(ssid)};
|
||||||
|
|
||||||
|
for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
|
||||||
|
// Virtual wifi devices will have consequtive mac addresses
|
||||||
|
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\n", 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.
|
||||||
|
char interface[6] = "wlan0";
|
||||||
|
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\n", device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all devices to join the IBSS network
|
||||||
|
for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
|
||||||
|
char interface[6] = "wlan0";
|
||||||
|
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\n", device_id, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -3385,6 +3659,9 @@ static int do_sandbox_none(void)
|
|||||||
#endif
|
#endif
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
#endif
|
#endif
|
||||||
loop();
|
loop();
|
||||||
doexit(1);
|
doexit(1);
|
||||||
@ -3426,6 +3703,9 @@ static int do_sandbox_setuid(void)
|
|||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
#endif
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
|
#endif
|
||||||
|
|
||||||
const int nobody = 65534;
|
const int nobody = 65534;
|
||||||
if (setgroups(0, NULL))
|
if (setgroups(0, NULL))
|
||||||
@ -3486,6 +3766,9 @@ static int namespace_sandbox_proc(void* arg)
|
|||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
#endif
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mkdir("./syz-tmp", 0777))
|
if (mkdir("./syz-tmp", 0777))
|
||||||
fail("mkdir(syz-tmp) failed");
|
fail("mkdir(syz-tmp) failed");
|
||||||
@ -4507,3 +4790,169 @@ static volatile long syz_fuse_handle_req(volatile long a0, // /dev/fuse fd.
|
|||||||
return fuse_send_response(fd, in_hdr, out_hdr);
|
return fuse_send_response(fd, in_hdr, out_hdr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || __NR_syz_80211_inject_frame
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
// This pseudo syscall performs 802.11 frame injection.
|
||||||
|
//
|
||||||
|
// Its current implementation performs the injection by means of mac80211_hwsim.
|
||||||
|
// The procedure consists of the following steps:
|
||||||
|
// 1. Open a netlink socket
|
||||||
|
// 2. Register as an application responsible for wireless medium simulation by executing
|
||||||
|
// HWSIM_CMD_REGISTER. This is a preq-requisite for the following step. After HWSIM_CMD_REGISTER
|
||||||
|
// is executed, mac80211_hwsim stops simulating a perfect medium.
|
||||||
|
// It is also important to note that this command registers a specific socket, not a netlink port.
|
||||||
|
// 3. Inject a frame to the required interface by executing HWSIM_CMD_FRAME.
|
||||||
|
// 4. Close the socket. mac80211_hwsim will detect this and return to perfect medium simulation.
|
||||||
|
//
|
||||||
|
// Note that we cannot (should not) open a socket, register it once and then use it for frame injection
|
||||||
|
// throughout the lifetime of a proc. When some socket is registered, mac80211_hwsim does not broadcast
|
||||||
|
// frames to all interfaces itself. As we do not perform this activity either, a permanently registered
|
||||||
|
// socket will disrupt normal network operation.
|
||||||
|
|
||||||
|
#define HWSIM_ATTR_RX_RATE 5
|
||||||
|
#define HWSIM_ATTR_SIGNAL 6
|
||||||
|
#define HWSIM_ATTR_ADDR_RECEIVER 1
|
||||||
|
#define HWSIM_ATTR_FRAME 3
|
||||||
|
|
||||||
|
#define WIFI_MAX_INJECT_LEN 2048
|
||||||
|
|
||||||
|
static int hwsim_register_socket(struct nlmsg* nlmsg, int sock, int hwsim_family)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_REGISTER;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim_register_device failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hwsim_inject_frame(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8* mac_addr, uint8* data, int len)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
uint32 rx_rate = WIFI_DEFAULT_RX_RATE;
|
||||||
|
uint32 signal = WIFI_DEFAULT_SIGNAL;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_FRAME;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_RX_RATE, &rx_rate, sizeof(rx_rate));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_SIGNAL, &signal, sizeof(signal));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_ADDR_RECEIVER, mac_addr, ETH_ALEN);
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_FRAME, data, len);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim_inject_frame failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long syz_80211_inject_frame(volatile long a0, volatile long a1, volatile long a2)
|
||||||
|
{
|
||||||
|
uint8* mac_addr = (uint8*)a0;
|
||||||
|
uint8* buf = (uint8*)a1;
|
||||||
|
int buf_len = (int)a2;
|
||||||
|
struct nlmsg tmp_msg;
|
||||||
|
|
||||||
|
if (buf_len < 0 || buf_len > WIFI_MAX_INJECT_LEN) {
|
||||||
|
debug("syz_80211_inject_frame: wrong buffer size %d\n", buf_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("syz_80211_inject_frame: socket creation failed, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwsim_family_id = netlink_query_family_id(&tmp_msg, sock, "MAC80211_HWSIM");
|
||||||
|
int ret = hwsim_register_socket(&tmp_msg, sock, hwsim_family_id);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_inject_frame: failed to register socket, ret %d\n", ret);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hwsim_inject_frame(&tmp_msg, sock, hwsim_family_id, mac_addr, buf, buf_len);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_inject_frame: failed to inject message, ret %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || __NR_syz_80211_join_ibss
|
||||||
|
|
||||||
|
#define WIFI_MAX_SSID_LEN 32
|
||||||
|
|
||||||
|
#define WIFI_JOIN_IBSS_NO_SCAN 0
|
||||||
|
#define WIFI_JOIN_IBSS_BG_SCAN 1
|
||||||
|
#define WIFI_JOIN_IBSS_BG_NO_SCAN 2
|
||||||
|
|
||||||
|
static long syz_80211_join_ibss(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
|
||||||
|
{
|
||||||
|
char* interface = (char*)a0;
|
||||||
|
uint8* ssid = (uint8*)a1;
|
||||||
|
int ssid_len = (int)a2;
|
||||||
|
int mode = (int)a3; // This parameter essentially determines whether it will perform a scan
|
||||||
|
|
||||||
|
struct nlmsg tmp_msg;
|
||||||
|
uint8 bssid[ETH_ALEN] = WIFI_IBSS_BSSID;
|
||||||
|
|
||||||
|
if (ssid_len < 0 || ssid_len > WIFI_MAX_SSID_LEN) {
|
||||||
|
debug("syz_80211_join_ibss: invalid ssid len %d\n", ssid_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode < 0 || mode > WIFI_JOIN_IBSS_BG_NO_SCAN) {
|
||||||
|
debug("syz_80211_join_ibss: invalid mode %d\n", mode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("syz_80211_join_ibss: socket creation failed, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nl80211_family_id = netlink_query_family_id(&tmp_msg, sock, "nl80211");
|
||||||
|
struct join_ibss_props ibss_props = {
|
||||||
|
.wiphy_freq = WIFI_DEFAULT_FREQUENCY,
|
||||||
|
.wiphy_freq_fixed = (mode == WIFI_JOIN_IBSS_NO_SCAN || mode == WIFI_JOIN_IBSS_BG_NO_SCAN),
|
||||||
|
.mac = bssid,
|
||||||
|
.ssid = ssid,
|
||||||
|
.ssid_len = ssid_len};
|
||||||
|
|
||||||
|
int ret = nl80211_setup_ibss_interface(&tmp_msg, sock, nl80211_family_id, interface, &ibss_props);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_join_ibss: failed set up IBSS network for %.32s\n", interface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == WIFI_JOIN_IBSS_NO_SCAN) {
|
||||||
|
ret = await_ifla_operstate(&tmp_msg, interface, IF_OPER_UP);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_join_ibss: await_ifla_operstate failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -129,6 +129,7 @@ static bool flag_cgroups;
|
|||||||
static bool flag_close_fds;
|
static bool flag_close_fds;
|
||||||
static bool flag_devlink_pci;
|
static bool flag_devlink_pci;
|
||||||
static bool flag_vhci_injection;
|
static bool flag_vhci_injection;
|
||||||
|
static bool flag_wifi;
|
||||||
|
|
||||||
static bool flag_collect_cover;
|
static bool flag_collect_cover;
|
||||||
static bool flag_dedup_cover;
|
static bool flag_dedup_cover;
|
||||||
@ -492,6 +493,7 @@ void parse_env_flags(uint64 flags)
|
|||||||
flag_close_fds = flags & (1 << 10);
|
flag_close_fds = flags & (1 << 10);
|
||||||
flag_devlink_pci = flags & (1 << 11);
|
flag_devlink_pci = flags & (1 << 11);
|
||||||
flag_vhci_injection = flags & (1 << 12);
|
flag_vhci_injection = flags & (1 << 12);
|
||||||
|
flag_wifi = flags & (1 << 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SYZ_EXECUTOR_USES_FORK_SERVER
|
#if SYZ_EXECUTOR_USES_FORK_SERVER
|
||||||
|
@ -125,6 +125,7 @@ func commonDefines(p *prog.Prog, opts Options) map[string]bool {
|
|||||||
"SYZ_HANDLE_SEGV": opts.HandleSegv,
|
"SYZ_HANDLE_SEGV": opts.HandleSegv,
|
||||||
"SYZ_REPRO": opts.Repro,
|
"SYZ_REPRO": opts.Repro,
|
||||||
"SYZ_TRACE": opts.Trace,
|
"SYZ_TRACE": opts.Trace,
|
||||||
|
"SYZ_WIFI": opts.Wifi,
|
||||||
"SYZ_EXECUTOR_USES_SHMEM": sysTarget.ExecutorUsesShmem,
|
"SYZ_EXECUTOR_USES_SHMEM": sysTarget.ExecutorUsesShmem,
|
||||||
"SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer,
|
"SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer,
|
||||||
}
|
}
|
||||||
|
@ -2338,7 +2338,8 @@ static bool write_file(const char* file, const char* what, ...)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || __NR_syz_genetlink_get_family_id
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || \
|
||||||
|
__NR_syz_genetlink_get_family_id || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -2432,7 +2433,8 @@ static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
|
|||||||
return ((struct nlmsgerr*)(hdr + 1))->error;
|
return ((struct nlmsgerr*)(hdr + 1))->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI || \
|
||||||
|
__NR_syz_80211_join_ibss || __NR_syz_80211_inject_frame
|
||||||
static int netlink_send(struct nlmsg* nlmsg, int sock)
|
static int netlink_send(struct nlmsg* nlmsg, int sock)
|
||||||
{
|
{
|
||||||
return netlink_send_ext(nlmsg, sock, 0, NULL);
|
return netlink_send_ext(nlmsg, sock, 0, NULL);
|
||||||
@ -2702,7 +2704,7 @@ static void netlink_add_neigh(struct nlmsg* nlmsg, int sock, const char* name,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES || SYZ_NET_INJECTION || SYZ_DEVLINK_PCI || SYZ_WIFI
|
||||||
static struct nlmsg nlmsg;
|
static struct nlmsg nlmsg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2944,6 +2946,257 @@ static void initialize_devlink_pci(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_inject_frame || __NR_syz_80211_join_ibss
|
||||||
|
|
||||||
|
#define WIFI_INITIAL_DEVICE_COUNT 2
|
||||||
|
#define WIFI_MAC_BASE \
|
||||||
|
{ \
|
||||||
|
0x08, 0x02, 0x11, 0x00, 0x00, 0x00 \
|
||||||
|
}
|
||||||
|
#define WIFI_IBSS_BSSID \
|
||||||
|
{ \
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50 \
|
||||||
|
}
|
||||||
|
#define WIFI_IBSS_SSID \
|
||||||
|
{ \
|
||||||
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 \
|
||||||
|
}
|
||||||
|
#define WIFI_DEFAULT_FREQUENCY 2412
|
||||||
|
#define WIFI_DEFAULT_SIGNAL 0
|
||||||
|
#define WIFI_DEFAULT_RX_RATE 1
|
||||||
|
#define HWSIM_CMD_REGISTER 1
|
||||||
|
#define HWSIM_CMD_FRAME 2
|
||||||
|
#define HWSIM_CMD_NEW_RADIO 4
|
||||||
|
#define HWSIM_ATTR_SUPPORT_P2P_DEVICE 14
|
||||||
|
#define HWSIM_ATTR_PERM_ADDR 22
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI || __NR_syz_80211_join_ibss
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#define IF_OPER_UP 6
|
||||||
|
struct join_ibss_props {
|
||||||
|
int wiphy_freq;
|
||||||
|
bool wiphy_freq_fixed;
|
||||||
|
uint8* mac;
|
||||||
|
uint8* ssid;
|
||||||
|
int ssid_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int set_interface_state(const char* interface_name, int on)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("set_interface_state: failed to open socket, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strcpy(ifr.ifr_name, interface_name);
|
||||||
|
int ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("set_interface_state: failed to execute SIOCGIFFLAGS, ret %d\n", ret);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on)
|
||||||
|
ifr.ifr_flags |= IFF_UP;
|
||||||
|
else
|
||||||
|
ifr.ifr_flags &= ~IFF_UP;
|
||||||
|
|
||||||
|
ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("set_interface_state: failed to execute SIOCSIFFLAGS, ret %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_set_interface(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex, uint32 iftype)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = NL80211_CMD_SET_INTERFACE;
|
||||||
|
netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFTYPE, &iftype, sizeof(iftype));
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("nl80211_set_interface failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_join_ibss(struct nlmsg* nlmsg, int sock, int nl80211_family, uint32 ifindex, struct join_ibss_props* props)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = NL80211_CMD_JOIN_IBSS;
|
||||||
|
netlink_init(nlmsg, nl80211_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_IFINDEX, &ifindex, sizeof(ifindex));
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_SSID, props->ssid, props->ssid_len);
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_WIPHY_FREQ, &(props->wiphy_freq), sizeof(props->wiphy_freq));
|
||||||
|
if (props->mac)
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_MAC, props->mac, ETH_ALEN);
|
||||||
|
if (props->wiphy_freq_fixed)
|
||||||
|
netlink_attr(nlmsg, NL80211_ATTR_FREQ_FIXED, NULL, 0);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("nl80211_join_ibss failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_ifla_operstate(struct nlmsg* nlmsg, int ifindex)
|
||||||
|
{
|
||||||
|
struct ifinfomsg info;
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.ifi_family = AF_UNSPEC;
|
||||||
|
info.ifi_index = ifindex;
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if (sock == -1) {
|
||||||
|
debug("get_ifla_operstate: socket failed: %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
netlink_init(nlmsg, RTM_GETLINK, 0, &info, sizeof(info));
|
||||||
|
int n;
|
||||||
|
int err = netlink_send_ext(nlmsg, sock, RTM_NEWLINK, &n);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
debug("get_ifla_operstate: failed to query: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rtattr* attr = IFLA_RTA(NLMSG_DATA(nlmsg->buf));
|
||||||
|
for (; RTA_OK(attr, n); attr = RTA_NEXT(attr, n)) {
|
||||||
|
if (attr->rta_type == IFLA_OPERSTATE)
|
||||||
|
return *((int32_t*)RTA_DATA(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int await_ifla_operstate(struct nlmsg* nlmsg, char* interface, int operstate)
|
||||||
|
{
|
||||||
|
int ifindex = if_nametoindex(interface);
|
||||||
|
while (true) {
|
||||||
|
usleep(1000);
|
||||||
|
int ret = get_ifla_operstate(nlmsg, ifindex);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret == operstate)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_setup_ibss_interface(struct nlmsg* nlmsg, int sock, int nl80211_family_id, char* interface, struct join_ibss_props* ibss_props)
|
||||||
|
{
|
||||||
|
int ifindex = if_nametoindex(interface);
|
||||||
|
if (ifindex == 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: if_nametoindex failed for %.32s, ret 0\n", interface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = nl80211_set_interface(nlmsg, sock, nl80211_family_id, ifindex, NL80211_IFTYPE_ADHOC);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: nl80211_set_interface failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_interface_state(interface, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: set_interface_state failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nl80211_join_ibss(nlmsg, sock, nl80211_family_id, ifindex, ibss_props);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("nl80211_setup_ibss_interface: nl80211_join_ibss failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
static int hwsim80211_create_device(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8 mac_addr[ETH_ALEN])
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_NEW_RADIO;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_SUPPORT_P2P_DEVICE, NULL, 0);
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_PERM_ADDR, mac_addr, ETH_ALEN);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim80211_create_device failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initialize_wifi_devices(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR
|
||||||
|
if (!flag_wifi)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
uint8 mac_addr[6] = WIFI_MAC_BASE;
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("initialize_wifi_devices: failed to create socket (%d)\n", errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwsim_family_id = netlink_query_family_id(&nlmsg, sock, "MAC80211_HWSIM");
|
||||||
|
int nl80211_family_id = netlink_query_family_id(&nlmsg, sock, "nl80211");
|
||||||
|
uint8 ssid[] = WIFI_IBSS_SSID;
|
||||||
|
uint8 bssid[] = WIFI_IBSS_BSSID;
|
||||||
|
struct join_ibss_props ibss_props = {
|
||||||
|
.wiphy_freq = WIFI_DEFAULT_FREQUENCY, .wiphy_freq_fixed = true, .mac = bssid, .ssid = ssid, .ssid_len = sizeof(ssid)};
|
||||||
|
|
||||||
|
for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
|
||||||
|
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\n", device_id);
|
||||||
|
char interface[6] = "wlan0";
|
||||||
|
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\n", device_id);
|
||||||
|
}
|
||||||
|
for (int device_id = 0; device_id < WIFI_INITIAL_DEVICE_COUNT; device_id++) {
|
||||||
|
char interface[6] = "wlan0";
|
||||||
|
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\n", device_id, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -7628,6 +7881,9 @@ static int do_sandbox_none(void)
|
|||||||
#endif
|
#endif
|
||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
#endif
|
#endif
|
||||||
loop();
|
loop();
|
||||||
doexit(1);
|
doexit(1);
|
||||||
@ -7669,6 +7925,9 @@ static int do_sandbox_setuid(void)
|
|||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
#endif
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
|
#endif
|
||||||
|
|
||||||
const int nobody = 65534;
|
const int nobody = 65534;
|
||||||
if (setgroups(0, NULL))
|
if (setgroups(0, NULL))
|
||||||
@ -7716,6 +7975,9 @@ static int namespace_sandbox_proc(void* arg)
|
|||||||
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
#if SYZ_EXECUTOR || SYZ_NET_DEVICES
|
||||||
initialize_netdevices();
|
initialize_netdevices();
|
||||||
#endif
|
#endif
|
||||||
|
#if SYZ_EXECUTOR || SYZ_WIFI
|
||||||
|
initialize_wifi_devices();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mkdir("./syz-tmp", 0777))
|
if (mkdir("./syz-tmp", 0777))
|
||||||
fail("mkdir(syz-tmp) failed");
|
fail("mkdir(syz-tmp) failed");
|
||||||
@ -9148,6 +9410,155 @@ static volatile long syz_fuse_handle_req(volatile long a0,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || __NR_syz_80211_inject_frame
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <linux/nl80211.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#define HWSIM_ATTR_RX_RATE 5
|
||||||
|
#define HWSIM_ATTR_SIGNAL 6
|
||||||
|
#define HWSIM_ATTR_ADDR_RECEIVER 1
|
||||||
|
#define HWSIM_ATTR_FRAME 3
|
||||||
|
|
||||||
|
#define WIFI_MAX_INJECT_LEN 2048
|
||||||
|
|
||||||
|
static int hwsim_register_socket(struct nlmsg* nlmsg, int sock, int hwsim_family)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_REGISTER;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim_register_device failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hwsim_inject_frame(struct nlmsg* nlmsg, int sock, int hwsim_family, uint8* mac_addr, uint8* data, int len)
|
||||||
|
{
|
||||||
|
struct genlmsghdr genlhdr;
|
||||||
|
uint32 rx_rate = WIFI_DEFAULT_RX_RATE;
|
||||||
|
uint32 signal = WIFI_DEFAULT_SIGNAL;
|
||||||
|
|
||||||
|
memset(&genlhdr, 0, sizeof(genlhdr));
|
||||||
|
genlhdr.cmd = HWSIM_CMD_FRAME;
|
||||||
|
netlink_init(nlmsg, hwsim_family, 0, &genlhdr, sizeof(genlhdr));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_RX_RATE, &rx_rate, sizeof(rx_rate));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_SIGNAL, &signal, sizeof(signal));
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_ADDR_RECEIVER, mac_addr, ETH_ALEN);
|
||||||
|
netlink_attr(nlmsg, HWSIM_ATTR_FRAME, data, len);
|
||||||
|
int err = netlink_send(nlmsg, sock);
|
||||||
|
if (err < 0) {
|
||||||
|
debug("hwsim_inject_frame failed: %s\n", strerror(-err));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long syz_80211_inject_frame(volatile long a0, volatile long a1, volatile long a2)
|
||||||
|
{
|
||||||
|
uint8* mac_addr = (uint8*)a0;
|
||||||
|
uint8* buf = (uint8*)a1;
|
||||||
|
int buf_len = (int)a2;
|
||||||
|
struct nlmsg tmp_msg;
|
||||||
|
|
||||||
|
if (buf_len < 0 || buf_len > WIFI_MAX_INJECT_LEN) {
|
||||||
|
debug("syz_80211_inject_frame: wrong buffer size %d\n", buf_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("syz_80211_inject_frame: socket creation failed, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwsim_family_id = netlink_query_family_id(&tmp_msg, sock, "MAC80211_HWSIM");
|
||||||
|
int ret = hwsim_register_socket(&tmp_msg, sock, hwsim_family_id);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_inject_frame: failed to register socket, ret %d\n", ret);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hwsim_inject_frame(&tmp_msg, sock, hwsim_family_id, mac_addr, buf, buf_len);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_inject_frame: failed to inject message, ret %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SYZ_EXECUTOR || __NR_syz_80211_join_ibss
|
||||||
|
|
||||||
|
#define WIFI_MAX_SSID_LEN 32
|
||||||
|
|
||||||
|
#define WIFI_JOIN_IBSS_NO_SCAN 0
|
||||||
|
#define WIFI_JOIN_IBSS_BG_SCAN 1
|
||||||
|
#define WIFI_JOIN_IBSS_BG_NO_SCAN 2
|
||||||
|
|
||||||
|
static long syz_80211_join_ibss(volatile long a0, volatile long a1, volatile long a2, volatile long a3)
|
||||||
|
{
|
||||||
|
char* interface = (char*)a0;
|
||||||
|
uint8* ssid = (uint8*)a1;
|
||||||
|
int ssid_len = (int)a2;
|
||||||
|
int mode = (int)a3;
|
||||||
|
|
||||||
|
struct nlmsg tmp_msg;
|
||||||
|
uint8 bssid[ETH_ALEN] = WIFI_IBSS_BSSID;
|
||||||
|
|
||||||
|
if (ssid_len < 0 || ssid_len > WIFI_MAX_SSID_LEN) {
|
||||||
|
debug("syz_80211_join_ibss: invalid ssid len %d\n", ssid_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode < 0 || mode > WIFI_JOIN_IBSS_BG_NO_SCAN) {
|
||||||
|
debug("syz_80211_join_ibss: invalid mode %d\n", mode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||||
|
if (sock < 0) {
|
||||||
|
debug("syz_80211_join_ibss: socket creation failed, errno %d\n", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nl80211_family_id = netlink_query_family_id(&tmp_msg, sock, "nl80211");
|
||||||
|
struct join_ibss_props ibss_props = {
|
||||||
|
.wiphy_freq = WIFI_DEFAULT_FREQUENCY,
|
||||||
|
.wiphy_freq_fixed = (mode == WIFI_JOIN_IBSS_NO_SCAN || mode == WIFI_JOIN_IBSS_BG_NO_SCAN),
|
||||||
|
.mac = bssid,
|
||||||
|
.ssid = ssid,
|
||||||
|
.ssid_len = ssid_len};
|
||||||
|
|
||||||
|
int ret = nl80211_setup_ibss_interface(&tmp_msg, sock, nl80211_family_id, interface, &ibss_props);
|
||||||
|
close(sock);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_join_ibss: failed set up IBSS network for %.32s\n", interface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == WIFI_JOIN_IBSS_NO_SCAN) {
|
||||||
|
ret = await_ifla_operstate(&tmp_msg, interface, IF_OPER_UP);
|
||||||
|
if (ret < 0) {
|
||||||
|
debug("syz_80211_join_ibss: await_ifla_operstate failed for %.32s, ret %d\n", interface, ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif GOOS_test
|
#elif GOOS_test
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -41,6 +41,7 @@ type Options struct {
|
|||||||
DevlinkPCI bool `json:"devlinkpci,omitempty"`
|
DevlinkPCI bool `json:"devlinkpci,omitempty"`
|
||||||
USB bool `json:"usb,omitempty"`
|
USB bool `json:"usb,omitempty"`
|
||||||
VhciInjection bool `json:"vhci,omitempty"`
|
VhciInjection bool `json:"vhci,omitempty"`
|
||||||
|
Wifi bool `json:"wifi,omitempty"`
|
||||||
|
|
||||||
UseTmpDir bool `json:"tmpdir,omitempty"`
|
UseTmpDir bool `json:"tmpdir,omitempty"`
|
||||||
HandleSegv bool `json:"segv,omitempty"`
|
HandleSegv bool `json:"segv,omitempty"`
|
||||||
@ -92,6 +93,9 @@ func (opts Options) Check(OS string) error {
|
|||||||
if opts.VhciInjection {
|
if opts.VhciInjection {
|
||||||
return errors.New("option VhciInjection without sandbox")
|
return errors.New("option VhciInjection without sandbox")
|
||||||
}
|
}
|
||||||
|
if opts.Wifi {
|
||||||
|
return errors.New("option Wifi without sandbox")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if opts.Sandbox == sandboxNamespace && !opts.UseTmpDir {
|
if opts.Sandbox == sandboxNamespace && !opts.UseTmpDir {
|
||||||
// This is borken and never worked.
|
// This is borken and never worked.
|
||||||
@ -142,6 +146,9 @@ func (opts Options) checkLinuxOnly(OS string) error {
|
|||||||
if opts.VhciInjection {
|
if opts.VhciInjection {
|
||||||
return fmt.Errorf("option VHCI is not supported on %v", OS)
|
return fmt.Errorf("option VHCI is not supported on %v", OS)
|
||||||
}
|
}
|
||||||
|
if opts.Wifi {
|
||||||
|
return fmt.Errorf("option Wifi is not supported on %v", OS)
|
||||||
|
}
|
||||||
if opts.Sandbox == sandboxNamespace ||
|
if opts.Sandbox == sandboxNamespace ||
|
||||||
(opts.Sandbox == sandboxSetuid && !(OS == openbsd || OS == freebsd || OS == netbsd)) ||
|
(opts.Sandbox == sandboxSetuid && !(OS == openbsd || OS == freebsd || OS == netbsd)) ||
|
||||||
opts.Sandbox == sandboxAndroid {
|
opts.Sandbox == sandboxAndroid {
|
||||||
@ -171,6 +178,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options {
|
|||||||
CloseFDs: true,
|
CloseFDs: true,
|
||||||
DevlinkPCI: true,
|
DevlinkPCI: true,
|
||||||
VhciInjection: true,
|
VhciInjection: true,
|
||||||
|
Wifi: true,
|
||||||
UseTmpDir: true,
|
UseTmpDir: true,
|
||||||
HandleSegv: true,
|
HandleSegv: true,
|
||||||
Repro: true,
|
Repro: true,
|
||||||
@ -185,6 +193,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options {
|
|||||||
opts.DevlinkPCI = false
|
opts.DevlinkPCI = false
|
||||||
opts.USB = false
|
opts.USB = false
|
||||||
opts.VhciInjection = false
|
opts.VhciInjection = false
|
||||||
|
opts.Wifi = false
|
||||||
}
|
}
|
||||||
if cfg.Sandbox == "" || cfg.Sandbox == "setuid" {
|
if cfg.Sandbox == "" || cfg.Sandbox == "setuid" {
|
||||||
opts.NetReset = false
|
opts.NetReset = false
|
||||||
@ -266,6 +275,7 @@ func defaultFeatures(value bool) Features {
|
|||||||
"devlink_pci": {"setup devlink PCI device", value},
|
"devlink_pci": {"setup devlink PCI device", value},
|
||||||
"usb": {"setup and use /dev/raw-gadget for USB emulation", value},
|
"usb": {"setup and use /dev/raw-gadget for USB emulation", value},
|
||||||
"vhci": {"setup and use /dev/vhci for hci packet injection", value},
|
"vhci": {"setup and use /dev/vhci for hci packet injection", value},
|
||||||
|
"wifi": {"setup and use mac80211_hwsim for wifi emulation", value},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +236,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": true,
|
"devlink_pci": true,
|
||||||
"usb": true,
|
"usb": true,
|
||||||
"vhci": true,
|
"vhci": true,
|
||||||
|
"wifi": true,
|
||||||
}},
|
}},
|
||||||
{"none", "none", false, map[string]bool{
|
{"none", "none", false, map[string]bool{
|
||||||
"tun": false,
|
"tun": false,
|
||||||
@ -247,6 +248,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": false,
|
"devlink_pci": false,
|
||||||
"usb": false,
|
"usb": false,
|
||||||
"vhci": false,
|
"vhci": false,
|
||||||
|
"wifi": false,
|
||||||
}},
|
}},
|
||||||
{"all", "none", true, map[string]bool{
|
{"all", "none", true, map[string]bool{
|
||||||
"tun": true,
|
"tun": true,
|
||||||
@ -258,6 +260,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": true,
|
"devlink_pci": true,
|
||||||
"usb": true,
|
"usb": true,
|
||||||
"vhci": true,
|
"vhci": true,
|
||||||
|
"wifi": true,
|
||||||
}},
|
}},
|
||||||
{"", "none", true, map[string]bool{
|
{"", "none", true, map[string]bool{
|
||||||
"tun": false,
|
"tun": false,
|
||||||
@ -269,6 +272,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": false,
|
"devlink_pci": false,
|
||||||
"usb": false,
|
"usb": false,
|
||||||
"vhci": false,
|
"vhci": false,
|
||||||
|
"wifi": false,
|
||||||
}},
|
}},
|
||||||
{"none", "all", true, map[string]bool{
|
{"none", "all", true, map[string]bool{
|
||||||
"tun": false,
|
"tun": false,
|
||||||
@ -280,6 +284,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": false,
|
"devlink_pci": false,
|
||||||
"usb": false,
|
"usb": false,
|
||||||
"vhci": false,
|
"vhci": false,
|
||||||
|
"wifi": false,
|
||||||
}},
|
}},
|
||||||
{"none", "", true, map[string]bool{
|
{"none", "", true, map[string]bool{
|
||||||
"tun": true,
|
"tun": true,
|
||||||
@ -291,6 +296,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": true,
|
"devlink_pci": true,
|
||||||
"usb": true,
|
"usb": true,
|
||||||
"vhci": true,
|
"vhci": true,
|
||||||
|
"wifi": true,
|
||||||
}},
|
}},
|
||||||
{"tun,net_dev", "none", true, map[string]bool{
|
{"tun,net_dev", "none", true, map[string]bool{
|
||||||
"tun": true,
|
"tun": true,
|
||||||
@ -302,6 +308,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": false,
|
"devlink_pci": false,
|
||||||
"usb": false,
|
"usb": false,
|
||||||
"vhci": false,
|
"vhci": false,
|
||||||
|
"wifi": false,
|
||||||
}},
|
}},
|
||||||
{"none", "cgroups,net_dev", true, map[string]bool{
|
{"none", "cgroups,net_dev", true, map[string]bool{
|
||||||
"tun": true,
|
"tun": true,
|
||||||
@ -313,6 +320,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": true,
|
"devlink_pci": true,
|
||||||
"usb": true,
|
"usb": true,
|
||||||
"vhci": true,
|
"vhci": true,
|
||||||
|
"wifi": true,
|
||||||
}},
|
}},
|
||||||
{"close_fds", "none", true, map[string]bool{
|
{"close_fds", "none", true, map[string]bool{
|
||||||
"tun": false,
|
"tun": false,
|
||||||
@ -324,6 +332,7 @@ func TestParseFeaturesFlags(t *testing.T) {
|
|||||||
"devlink_pci": false,
|
"devlink_pci": false,
|
||||||
"usb": false,
|
"usb": false,
|
||||||
"vhci": false,
|
"vhci": false,
|
||||||
|
"wifi": false,
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -28,6 +28,7 @@ const (
|
|||||||
FeatureDevlinkPCI
|
FeatureDevlinkPCI
|
||||||
FeatureUSBEmulation
|
FeatureUSBEmulation
|
||||||
FeatureVhciInjection
|
FeatureVhciInjection
|
||||||
|
FeatureWifiEmulation
|
||||||
numFeatures
|
numFeatures
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ func Check(target *prog.Target) (*Features, error) {
|
|||||||
FeatureDevlinkPCI: {Name: "devlink PCI setup", Reason: unsupported},
|
FeatureDevlinkPCI: {Name: "devlink PCI setup", Reason: unsupported},
|
||||||
FeatureUSBEmulation: {Name: "USB emulation", Reason: unsupported},
|
FeatureUSBEmulation: {Name: "USB emulation", Reason: unsupported},
|
||||||
FeatureVhciInjection: {Name: "hci packet injection", Reason: unsupported},
|
FeatureVhciInjection: {Name: "hci packet injection", Reason: unsupported},
|
||||||
|
FeatureWifiEmulation: {Name: "wifi device emulation", Reason: unsupported},
|
||||||
}
|
}
|
||||||
if noHostChecks(target) {
|
if noHostChecks(target) {
|
||||||
return res, nil
|
return res, nil
|
||||||
|
@ -29,6 +29,7 @@ func init() {
|
|||||||
checkFeature[FeatureDevlinkPCI] = checkDevlinkPCI
|
checkFeature[FeatureDevlinkPCI] = checkDevlinkPCI
|
||||||
checkFeature[FeatureUSBEmulation] = checkUSBEmulation
|
checkFeature[FeatureUSBEmulation] = checkUSBEmulation
|
||||||
checkFeature[FeatureVhciInjection] = checkVhciInjection
|
checkFeature[FeatureVhciInjection] = checkVhciInjection
|
||||||
|
checkFeature[FeatureWifiEmulation] = checkWifiEmulation
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCoverage() string {
|
func checkCoverage() string {
|
||||||
@ -219,3 +220,10 @@ func checkDevlinkPCI() string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkWifiEmulation() string {
|
||||||
|
if err := osutil.IsAccessible("/sys/class/mac80211_hwsim/"); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
@ -186,6 +186,11 @@ func isVhciInjectionSupported(c *prog.Syscall, target *prog.Target, sandbox stri
|
|||||||
return reason == "", reason
|
return reason == "", reason
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isWifiEmulationSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
|
||||||
|
reason := checkWifiEmulation()
|
||||||
|
return reason == "", reason
|
||||||
|
}
|
||||||
|
|
||||||
func isSyzKvmSetupCPUSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
|
func isSyzKvmSetupCPUSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
|
||||||
switch c.Name {
|
switch c.Name {
|
||||||
case "syz_kvm_setup_cpu$x86":
|
case "syz_kvm_setup_cpu$x86":
|
||||||
@ -284,9 +289,11 @@ var syzkallSupport = map[string]func(*prog.Syscall, *prog.Target, string) (bool,
|
|||||||
"syz_io_uring_setup": isSyzIoUringSupported,
|
"syz_io_uring_setup": isSyzIoUringSupported,
|
||||||
// syz_memcpy_off is only used for io_uring descriptions, thus, enable it
|
// syz_memcpy_off is only used for io_uring descriptions, thus, enable it
|
||||||
// only if io_uring syscalls are enabled.
|
// only if io_uring syscalls are enabled.
|
||||||
"syz_memcpy_off": isSyzIoUringSupported,
|
"syz_memcpy_off": isSyzIoUringSupported,
|
||||||
"syz_btf_id_by_name": isBtfVmlinuxSupported,
|
"syz_btf_id_by_name": isBtfVmlinuxSupported,
|
||||||
"syz_fuse_handle_req": isSyzFuseSupported,
|
"syz_fuse_handle_req": isSyzFuseSupported,
|
||||||
|
"syz_80211_inject_frame": isWifiEmulationSupported,
|
||||||
|
"syz_80211_join_ibss": isWifiEmulationSupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
|
func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) {
|
||||||
|
@ -41,6 +41,7 @@ const (
|
|||||||
FlagEnableCloseFds // close fds after each program
|
FlagEnableCloseFds // close fds after each program
|
||||||
FlagEnableDevlinkPCI // setup devlink PCI device
|
FlagEnableDevlinkPCI // setup devlink PCI device
|
||||||
FlagEnableVhciInjection // setup and use /dev/vhci for hci packet injection
|
FlagEnableVhciInjection // setup and use /dev/vhci for hci packet injection
|
||||||
|
FlagEnableWifi // setup and use mac80211_hwsim for wifi emulation
|
||||||
)
|
)
|
||||||
|
|
||||||
// Per-exec flags for ExecOpts.Flags.
|
// Per-exec flags for ExecOpts.Flags.
|
||||||
|
@ -202,6 +202,9 @@ func createStartOptions(cfg *mgrconfig.Config, features *host.Features, crashTyp
|
|||||||
if !features[host.FeatureVhciInjection].Enabled {
|
if !features[host.FeatureVhciInjection].Enabled {
|
||||||
opts.VhciInjection = false
|
opts.VhciInjection = false
|
||||||
}
|
}
|
||||||
|
if !features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
opts.Wifi = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
@ -891,6 +894,7 @@ var cSimplifies = append(progSimplifies, []Simplify{
|
|||||||
opts.DevlinkPCI = false
|
opts.DevlinkPCI = false
|
||||||
opts.USB = false
|
opts.USB = false
|
||||||
opts.VhciInjection = false
|
opts.VhciInjection = false
|
||||||
|
opts.Wifi = false
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
func(opts *csource.Options) bool {
|
func(opts *csource.Options) bool {
|
||||||
@ -958,6 +962,13 @@ var cSimplifies = append(progSimplifies, []Simplify{
|
|||||||
opts.VhciInjection = false
|
opts.VhciInjection = false
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
func(opts *csource.Options) bool {
|
||||||
|
if !opts.Wifi {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
opts.Wifi = false
|
||||||
|
return true
|
||||||
|
},
|
||||||
func(opts *csource.Options) bool {
|
func(opts *csource.Options) bool {
|
||||||
if !opts.UseTmpDir || opts.Sandbox == "namespace" || opts.Cgroups {
|
if !opts.UseTmpDir || opts.Sandbox == "namespace" || opts.Cgroups {
|
||||||
return false
|
return false
|
||||||
|
@ -405,6 +405,9 @@ func (ctx *Context) createSyzTest(p *prog.Prog, sandbox string, threaded, cov bo
|
|||||||
if ctx.Features[host.FeatureVhciInjection].Enabled {
|
if ctx.Features[host.FeatureVhciInjection].Enabled {
|
||||||
cfg.Flags |= ipc.FlagEnableVhciInjection
|
cfg.Flags |= ipc.FlagEnableVhciInjection
|
||||||
}
|
}
|
||||||
|
if ctx.Features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
cfg.Flags |= ipc.FlagEnableWifi
|
||||||
|
}
|
||||||
if ctx.Debug {
|
if ctx.Debug {
|
||||||
cfg.Flags |= ipc.FlagDebug
|
cfg.Flags |= ipc.FlagDebug
|
||||||
}
|
}
|
||||||
@ -440,6 +443,9 @@ func (ctx *Context) createCTest(p *prog.Prog, sandbox string, threaded bool, tim
|
|||||||
if ctx.Features[host.FeatureVhciInjection].Enabled {
|
if ctx.Features[host.FeatureVhciInjection].Enabled {
|
||||||
opts.VhciInjection = true
|
opts.VhciInjection = true
|
||||||
}
|
}
|
||||||
|
if ctx.Features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
opts.Wifi = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
src, err := csource.Write(p, opts)
|
src, err := csource.Write(p, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
51
sys/linux/net_80211.txt
Normal file
51
sys/linux/net_80211.txt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Copyright 2020 syzkaller project authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
include <linux/ieee80211.h>
|
||||||
|
|
||||||
|
type ieee80211_fixed_mac_addr[LAST] {
|
||||||
|
byte0 const[0x8, int8]
|
||||||
|
byte1 const[0x2, int8]
|
||||||
|
byte2 const[0x11, int8]
|
||||||
|
byte3 const[0x0, int8]
|
||||||
|
byte4 const[0x0, int8]
|
||||||
|
byte5 LAST
|
||||||
|
} [packed]
|
||||||
|
|
||||||
|
ieee80211_mac_addr [
|
||||||
|
device_a ieee80211_fixed_mac_addr[const[0x0, int8]]
|
||||||
|
device_b ieee80211_fixed_mac_addr[const[0x1, int8]]
|
||||||
|
broadcast array[const[0xff, int8], 6]
|
||||||
|
]
|
||||||
|
|
||||||
|
ieee80211_ssid [
|
||||||
|
random array[int8, 0:IEEE80211_MAX_SSID_LEN]
|
||||||
|
default_ibss_ssid array[const[0x1, int8], 6]
|
||||||
|
] [varlen]
|
||||||
|
|
||||||
|
type ieee80211_frame array[int8]
|
||||||
|
|
||||||
|
# Inject an 802.11 frame.
|
||||||
|
# mac_addr -- mac address of the device that will receive the message (actually it determines
|
||||||
|
# the network interface that will receive this message).
|
||||||
|
# buf -- raw 802.11 frame. It should neither include an FCS, nor leave space for it at the end of the frame.
|
||||||
|
syz_80211_inject_frame(mac_addr ptr[in, ieee80211_mac_addr], buf ptr[in, ieee80211_frame], buf_len len[buf])
|
||||||
|
|
||||||
|
# Pseudo system call that puts a specific interface into IBSS state and joins an IBSS network.
|
||||||
|
# Although it is done for all interfaces at executor initialization and the nl80211 commands that it executes
|
||||||
|
# are present in syzkaller descriptions of nl80211, experiments demonstrated that addition of this pseudo
|
||||||
|
# syscall provokes a much bigger number of issues.
|
||||||
|
# Also, this pseudo call makes it possible to put interfaces generated by sendmsg$NL80211_CMD_NEW_INTERFACE
|
||||||
|
# into an operable state at runtime.
|
||||||
|
syz_80211_join_ibss(interface ptr[in, string[devnames]], ssid ptr[in, ieee80211_ssid], ssid_len len[ssid], join_mode flags[join_ibss_modes])
|
||||||
|
|
||||||
|
# Modes of syz_80211_join_ibss operation:
|
||||||
|
# JOIN_IBSS_NO_SCAN -- channel scan is not performed and syz_80211_join_ibss waits until the interface reaches IF_OPER_UP
|
||||||
|
# JOIN_IBSS_BG_SCAN -- channel scan is performed (takes ~ 9 seconds), syz_80211_join_ibss does not await IF_OPER_UP
|
||||||
|
# JOIN_IBSS_BG_NO_SCAN -- channel scan is not performed, syz_80211_join_ibss does not await IF_OPER_UP
|
||||||
|
|
||||||
|
define JOIN_IBSS_NO_SCAN 0x0
|
||||||
|
define JOIN_IBSS_BG_SCAN 0x1
|
||||||
|
define JOIN_IBSS_BG_NO_SCAN 0x2
|
||||||
|
|
||||||
|
join_ibss_modes = JOIN_IBSS_NO_SCAN, JOIN_IBSS_BG_SCAN, JOIN_IBSS_BG_NO_SCAN
|
6
sys/linux/net_80211.txt.const
Normal file
6
sys/linux/net_80211.txt.const
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Code generated by syz-sysgen. DO NOT EDIT.
|
||||||
|
arches = 386, amd64, arm, arm64, mips64le, ppc64le, riscv64, s390x
|
||||||
|
IEEE80211_MAX_SSID_LEN = 32
|
||||||
|
JOIN_IBSS_BG_NO_SCAN = 2
|
||||||
|
JOIN_IBSS_BG_SCAN = 1
|
||||||
|
JOIN_IBSS_NO_SCAN = 0
|
@ -384,7 +384,7 @@ rtentry {
|
|||||||
# Note: lapb0, bpq0 and hwsim0 are only present in init namespace.
|
# Note: lapb0, bpq0 and hwsim0 are only present in init namespace.
|
||||||
# Note: for roseN and nrN we should use proc type, but for simplicity we currently use N=0.
|
# Note: for roseN and nrN we should use proc type, but for simplicity we currently use N=0.
|
||||||
# Note: netdevsim0 and netpci0 are renamed in initialize_devlink_ports()
|
# Note: netdevsim0 and netpci0 are renamed in initialize_devlink_ports()
|
||||||
devnames = "", "lo", "tunl0", "gre0", "gretap0", "ip_vti0", "ip6_vti0", "sit0", "ip6tnl0", "ip6gre0", "ip6gretap0", "bond0", "dummy0", "nr0", "rose0", "erspan0", "vlan0", "bridge0", "vcan0", "team0", "syz_tun", "veth0", "veth1", "veth0_to_bridge", "veth1_to_bridge", "veth0_to_bond", "veth1_to_bond", "veth0_to_team", "veth1_to_team", "bridge_slave_0", "bridge_slave_1", "bond_slave_0", "bond_slave_1", "team_slave_0", "team_slave_1", "syzkaller0", "syzkaller1", "veth0_to_hsr", "veth1_to_hsr", "hsr0", "ip6erspan0", "vxcan1", "caif0", "batadv0", "veth0_to_batadv", "veth1_to_batadv", "batadv_slave_0", "batadv_slave_1", "netdevsim0", "netpci0", "xfrm0", "veth0_virt_wifi", "veth1_virt_wifi", "virt_wifi0", "veth0_vlan", "veth1_vlan", "vlan0", "vlan1", "macvlan0", "macvlan1", "ipvlan0", "ipvlan1", "veth0_macvtap", "veth1_macvtap", "macvtap0", "macsec0", "geneve0", "geneve1", "wg0", "wg1", "wg2"
|
devnames = "", "lo", "tunl0", "gre0", "gretap0", "ip_vti0", "ip6_vti0", "sit0", "ip6tnl0", "ip6gre0", "ip6gretap0", "bond0", "dummy0", "nr0", "rose0", "erspan0", "vlan0", "bridge0", "vcan0", "team0", "syz_tun", "veth0", "veth1", "veth0_to_bridge", "veth1_to_bridge", "veth0_to_bond", "veth1_to_bond", "veth0_to_team", "veth1_to_team", "bridge_slave_0", "bridge_slave_1", "bond_slave_0", "bond_slave_1", "team_slave_0", "team_slave_1", "syzkaller0", "syzkaller1", "veth0_to_hsr", "veth1_to_hsr", "hsr0", "ip6erspan0", "vxcan1", "caif0", "batadv0", "veth0_to_batadv", "veth1_to_batadv", "batadv_slave_0", "batadv_slave_1", "netdevsim0", "netpci0", "xfrm0", "veth0_virt_wifi", "veth1_virt_wifi", "virt_wifi0", "veth0_vlan", "veth1_vlan", "vlan0", "vlan1", "macvlan0", "macvlan1", "ipvlan0", "ipvlan1", "veth0_macvtap", "veth1_macvtap", "macvtap0", "macsec0", "geneve0", "geneve1", "wg0", "wg1", "wg2", "wlan0", "wlan1"
|
||||||
|
|
||||||
type devname string[devnames, IFNAMSIZ]
|
type devname string[devnames, IFNAMSIZ]
|
||||||
|
|
||||||
|
9
sys/linux/test/80211_ibss
Normal file
9
sys/linux/test/80211_ibss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# requires: -sandbox=namespace
|
||||||
|
|
||||||
|
# Join IBSSS network
|
||||||
|
|
||||||
|
syz_80211_join_ibss(&AUTO='wlan0\x00', &AUTO=@default_ibss_ssid, 0x6, 0x0)
|
||||||
|
|
||||||
|
# Inject an arbitrary packet
|
||||||
|
|
||||||
|
syz_80211_inject_frame(&AUTO=@device_a, &AUTO="00112233445566778899", 0xa)
|
@ -121,6 +121,9 @@ func createIPCConfig(features *host.Features, config *ipc.Config) {
|
|||||||
if features[host.FeatureVhciInjection].Enabled {
|
if features[host.FeatureVhciInjection].Enabled {
|
||||||
config.Flags |= ipc.FlagEnableVhciInjection
|
config.Flags |= ipc.FlagEnableVhciInjection
|
||||||
}
|
}
|
||||||
|
if features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
config.Flags |= ipc.FlagEnableWifi
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
// nolint: funlen
|
||||||
|
@ -332,5 +332,8 @@ func createConfig(target *prog.Target,
|
|||||||
if featuresFlags["vhci"].Enabled && features[host.FeatureVhciInjection].Enabled {
|
if featuresFlags["vhci"].Enabled && features[host.FeatureVhciInjection].Enabled {
|
||||||
config.Flags |= ipc.FlagEnableVhciInjection
|
config.Flags |= ipc.FlagEnableVhciInjection
|
||||||
}
|
}
|
||||||
|
if featuresFlags["wifi"].Enabled && features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
config.Flags |= ipc.FlagEnableWifi
|
||||||
|
}
|
||||||
return config, execOpts
|
return config, execOpts
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ func main() {
|
|||||||
DevlinkPCI: features["devlink_pci"].Enabled,
|
DevlinkPCI: features["devlink_pci"].Enabled,
|
||||||
USB: features["usb"].Enabled,
|
USB: features["usb"].Enabled,
|
||||||
VhciInjection: features["vhci"].Enabled,
|
VhciInjection: features["vhci"].Enabled,
|
||||||
|
Wifi: features["wifi"].Enabled,
|
||||||
UseTmpDir: *flagUseTmpDir,
|
UseTmpDir: *flagUseTmpDir,
|
||||||
HandleSegv: *flagHandleSegv,
|
HandleSegv: *flagHandleSegv,
|
||||||
Repro: *flagRepro,
|
Repro: *flagRepro,
|
||||||
|
@ -153,6 +153,8 @@ func createCRepro(bug *dashapi.LoadBugResp) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Although liter complains about this function, it does not seem complex.
|
||||||
|
// nolint: gocyclo
|
||||||
func createProg2CArgs(bug *dashapi.LoadBugResp, opts csource.Options, file string) []string {
|
func createProg2CArgs(bug *dashapi.LoadBugResp, opts csource.Options, file string) []string {
|
||||||
haveEnableFlag := containsCommit("dfd609eca1871f01757d6b04b19fc273c87c14e5")
|
haveEnableFlag := containsCommit("dfd609eca1871f01757d6b04b19fc273c87c14e5")
|
||||||
haveRepeatFlag := containsCommit("b25fc7b83119e8dca728a199fd92e24dd4c33fa4")
|
haveRepeatFlag := containsCommit("b25fc7b83119e8dca728a199fd92e24dd4c33fa4")
|
||||||
@ -232,6 +234,10 @@ func createProg2CArgs(bug *dashapi.LoadBugResp, opts csource.Options, file strin
|
|||||||
enable = append(enable, "vhci")
|
enable = append(enable, "vhci")
|
||||||
flags = append(flags, "-vhci")
|
flags = append(flags, "-vhci")
|
||||||
}
|
}
|
||||||
|
if opts.Wifi {
|
||||||
|
enable = append(enable, "wifi")
|
||||||
|
flags = append(flags, "-wifi")
|
||||||
|
}
|
||||||
if !haveEnableFlag {
|
if !haveEnableFlag {
|
||||||
args = append(args, flags...)
|
args = append(args, flags...)
|
||||||
} else if len(enable) != 0 {
|
} else if len(enable) != 0 {
|
||||||
|
@ -165,6 +165,9 @@ func createIPCConfig(target *prog.Target, features *host.Features, featuresFlags
|
|||||||
if featuresFlags["vhci"].Enabled && features[host.FeatureVhciInjection].Enabled {
|
if featuresFlags["vhci"].Enabled && features[host.FeatureVhciInjection].Enabled {
|
||||||
config.Flags |= ipc.FlagEnableVhciInjection
|
config.Flags |= ipc.FlagEnableVhciInjection
|
||||||
}
|
}
|
||||||
|
if featuresFlags["wifi"].Enabled && features[host.FeatureWifiEmulation].Enabled {
|
||||||
|
config.Flags |= ipc.FlagEnableWifi
|
||||||
|
}
|
||||||
return config, execOpts, nil
|
return config, execOpts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user