aboutsummaryrefslogtreecommitdiffstats
path: root/docs/linux
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2020-12-15 22:40:49 +0100
committerDmitry Vyukov <dvyukov@google.com>2020-12-16 05:50:12 +0100
commit649595c630f7581dc8aba66a183381b2a923d9e6 (patch)
tree6fc7ebe5dfd676f26cd4a4234c88cd92c9e45d02 /docs/linux
parent0053126c583f5ddf1e8092ab75db8d8446891897 (diff)
docs: update USB documentation
Minor updates and readability improvements.
Diffstat (limited to 'docs/linux')
-rw-r--r--docs/linux/external_fuzzing_usb.md56
1 files changed, 25 insertions, 31 deletions
diff --git a/docs/linux/external_fuzzing_usb.md b/docs/linux/external_fuzzing_usb.md
index 6f78fd867..0161add21 100644
--- a/docs/linux/external_fuzzing_usb.md
+++ b/docs/linux/external_fuzzing_usb.md
@@ -1,62 +1,58 @@
External USB fuzzing for Linux kernel
=====================================
-Syzkaller supports fuzzing the Linux kernel USB subsystem externally
-(as it would be done by plugging in a physical USB device with e.g. [Facedancer](https://github.com/usb-tools/Facedancer)).
-This allowed to find over [200 bugs](/docs/linux/found_bugs_usb.md) in the Linux kernel USB stack so far.
-This is still in development and things might change.
+Syzkaller supports fuzzing the Linux kernel USB subsystem externally (as can be done by plugging in a programmable USB device like [Facedancer](https://github.com/usb-tools/Facedancer)). This allowed finding over [300 bugs](/docs/linux/found_bugs_usb.md) in the Linux kernel USB stack so far.
USB fuzzing support consists of 3 parts:
-1. Syzkaller changes that are now in the mainline, see the [Internals](/docs/linux/external_fuzzing_usb.md#Internals) section for details.
-2. Kernel interface for USB device emulation called [Raw Gadget](https://github.com/xairy/raw-gadget), which is now in the mainline.
-3. KCOV changes that allow to collect coverage from background threads and interrupts, that are now in the mainline.
+1. Syzkaller changes; see the [Internals](/docs/linux/external_fuzzing_usb.md#Internals) section for details.
+2. Kernel interface for USB device emulation called [Raw Gadget](https://github.com/xairy/raw-gadget), which is now in the mainline kernel.
+3. KCOV changes that allow to collect coverage from background kernel threads and interrupts, which are now in the mainline kernel.
-Some (partly outdated) details can be found in the OffensiveCon 2019 "Coverage-Guided USB Fuzzing with Syzkaller" talk
-([slides](https://docs.google.com/presentation/d/1z-giB9kom17Lk21YEjmceiNUVYeI6yIaG5_gZ3vKC-M/edit?usp=sharing), [video](https://www.youtube.com/watch?v=1MD5JV6LfxA)).
+See the OffensiveCon 2019 [Coverage-Guided USB Fuzzing with Syzkaller](https://docs.google.com/presentation/d/1z-giB9kom17Lk21YEjmceiNUVYeI6yIaG5_gZ3vKC-M/edit?usp=sharing) talk ([video](https://www.youtube.com/watch?v=1MD5JV6LfxA)) for some (partially outdated) details.
As USB fuzzing requires kernel side support, for non-mainline kernels you need all mainline patches that touch `drivers/usb/gadget/udc/dummy_hcd.c`, `drivers/usb/gadget/legacy/raw_gadget.c` and `kernel/kcov.c`.
## Internals
-Currently syzkaller defines 6 USB pseudo-syscalls (see [this](/sys/linux/vusb.txt) for syzkaller descriptions of these pseudo-syscalls and [this](/executor/common_usb.h) for their implementation; the implementation relies on the Raw Gadget interface linked above):
+Currently, syzkaller defines 6 USB pseudo-syscalls (see [syzlang descriptions](/sys/linux/vusb.txt) and [pseudo-syscalls](/executor/common_usb.h) [implementation](https://github.com/xairy/syzkaller/blob/up-usb-docs/executor/common_usb_linux.h), which relies on the Raw Gadget interface linked above):
1. `syz_usb_connect` - connects a USB device. Handles all requests to the control endpoint until a `SET_CONFIGURATION` request is received.
-2. `syz_usb_connect_ath9k` - connects an `ath9k` USB device. Compared to `syz_usb_connect` this syscalls also handles firmware download requests that happen after the `SET_CONFIGURATION` for the `ath9k` driver.
+2. `syz_usb_connect_ath9k` - connects an `ath9k` USB device. Compared to `syz_usb_connect`, this syscall also handles firmware download requests that happen after `SET_CONFIGURATION` for the `ath9k` driver.
3. `syz_usb_disconnect` - disconnects a USB device.
4. `syz_usb_control_io` - sends or receives a control message over endpoint 0.
5. `syz_usb_ep_write` - sends a message to a non-control endpoint.
6. `syz_usb_ep_read` - receives a message from a non-control endpoint.
-Current USB descriptions are targeted at a few different layers:
+These pseudo-syscalls targeted at a few different layers:
-1. USB core enumeration process is targeted by the generic `syz_usb_connect` pseudo-syscall. As the USB device descriptor fields for this pseudo-syscall get [patched](/sys/linux/init_vusb.go) by syzkaller runtime, `syz_usb_connect` also briefly targets enumaration process of various USB drivers.
-2. Enumeration process for class-specific drivers is targeted by `syz_usb_connect$hid`, `syz_usb_connect$cdc_ecm`, etc. pseudo-syscalls (the device descriptors provided to them have fixed identifying USB IDs to always match to the same USB class driver) accompanied by matching `syz_usb_control_io$*` pseudo-syscalls.
-3. Subsequent communication through non-control endpoints for class-specific drivers is not targeted by existing descriptions yet for any of the supported classes, but can be triggered through generic `syz_usb_ep_write` and `syz_usb_ep_read` pseudo-syscalls.
+1. USB core enumeration process is targeted by the generic `syz_usb_connect` variant. As the USB device descriptor fields for this pseudo-syscall get [patched](/sys/linux/init_vusb.go) by syzkaller runtime, `syz_usb_connect` also briefly targets the enumeration process of various USB drivers.
+2. Enumeration process for class-specific drivers is targeted by `syz_usb_connect$hid`, `syz_usb_connect$cdc_ecm`, etc. (the device descriptors provided to them have fixed identifying USB IDs to always match to the same USB class driver) accompanied by matching `syz_usb_control_io$*` pseudo-syscalls.
+3. Subsequent communication through non-control endpoints for class-specific drivers is not targeted by existing descriptions yet for any of the supported classes. But it can be triggered through generic `syz_usb_ep_write` and `syz_usb_ep_read` pseudo-syscalls.
4. Enumeration process for device-specific drivers is not covered by existing descriptions yet.
5. Subsequent communication through non-control endpoints for device-specific drivers is partially described only for `ath9k` driver via `syz_usb_connect_ath9k`, `syz_usb_ep_write$ath9k_ep1` and `syz_usb_ep_write$ath9k_ep2` pseudo-syscalls.
-syzkaller USB runtests are [here](/sys/linux/test/) and start with `vusb` prefix. To run:
+There are [runtests](/sys/linux/test/) for USB pseudo-syscalls. They are named starting with the `vusb` prefix and can be run with:
```
./bin/syz-runtest -config=usb-manager.cfg -tests=vusb
```
-## TODO list
+## Things to improve
-The core support for USB fuzzing is now in place, but there are still some things that could be done:
+The core support for USB fuzzing is in place, but there's still a place for improvements:
-1. Remove device from `usb_devices` on disconnect in executor.
+1. Remove the device from `usb_devices` in `syz_usb_disconnect` and don't call `lookup_usb_index` multiple times within `syz_usb_connect`. Currently, this causes some reproducers to have the `repeat` flag set when it's not required.
2. Add descriptions for more relevant USB classes and drivers.
-3. Look for TODOs in [sys/linux/vusb.txt](/sys/linux/vusb.txt).
+3. Resolve TODOs from [sys/linux/vusb.txt](/sys/linux/vusb.txt).
4. Implement a proper way for dynamically extracting relevant USB ids from the kernel (a related [discussion](https://www.spinics.net/lists/linux-usb/msg187915.html)).
-5. Add a mode for standalone fuzzing of physical USB hosts (by using e.g. Raspberry Pi Zero, see below).
+5. Add a mode for standalone fuzzing of physical USB hosts (by using Raspberry Pi Zero, see below).
This includes at least: a. making sure that current USB emulation implementation works properly on different OSes (there are some [differences](https://github.com/RoganDawes/LOGITacker/blob/USB_host_enum/fingerprint_os.md#derive-the-os-from-the-fingerprint) in protocol implementation);
b. using USB requests coming from the host as a signal (like coverage) to enable "signal-driven" fuzzing,
c. making UDC driver name configurable for `syz-execprog` and `syz-prog2c`.
@@ -66,30 +62,28 @@ c. making UDC driver name configurable for `syz-execprog` and `syz-prog2c`.
## Setting up
-1. Checkout the `usb-fuzzer` branch from https://github.com/google/kasan
+1. Make sure the version of the kernel you're using is at least 5.7. It's recommended to backport all kernel patches that touch kcov, USB Raw Gadget, and USB Dummy UDC/HCD.
-2. Configure the kernel (at the very least `CONFIG_USB_RAW_GADGET=y` and `CONFIG_USB_DUMMY_HCD=y` need to be enabled).
+2. Configure the kernel: at the very least, `CONFIG_USB_RAW_GADGET=y` and `CONFIG_USB_DUMMY_HCD=y` must be enabled.
The easiest option is to use the [config](/dashboard/config/linux/upstream-usb.config) from the syzbot USB fuzzing instance.
3. Build the kernel.
-4. Optionally update syzkaller descriptions by extracting USB IDs using the instructions below.
+4. Optionally update syzkaller descriptions by extracting USB IDs using the [instructions](/docs/linux/external_fuzzing_usb.md#updating-syzkaller-usb-ids) below.
5. Enable `syz_usb_connect`, `syz_usb_disconnect`, `syz_usb_control_io`, `syz_usb_ep_write` and `syz_usb_ep_read` pseudo-syscalls in the manager config.
6. Set `sandbox` to `none` in the manager config.
-7. Pass `dummy_hcd.num=8` (or whatever number you use for `procs`) to the kernel command line in the maganer config.
+7. Pass `dummy_hcd.num=8` (or whatever number you use for `procs`) to the kernel command line in the manager config.
8. Run.
## Updating syzkaller USB IDs
-Syzkaller uses a list of hardcoded [USB IDs](/sys/linux/init_vusb_ids.go) that are [patched](/sys/linux/init_vusb.go) into the `syz_usb_connect` pseudo-syscall by syzkaller runtime.
-One of the ways to make syzkaller target only particular USB drivers is to alter that list.
-The instructions below describe a hackish way to generate syzkaller USB IDs for all USB drivers enabled in your .config.
+Syzkaller uses a list of hardcoded [USB IDs](/sys/linux/init_vusb_ids.go) that are [patched](/sys/linux/init_vusb.go) into `syz_usb_connect` by syzkaller runtime. One of the ways to make syzkaller target only particular USB drivers is to alter that list. The instructions below describe a hackish way to generate syzkaller USB IDs for all USB drivers enabled in your `.config`.
1. Apply [this](/tools/syz-usbgen/usb_ids.patch) kernel patch.
@@ -186,7 +180,7 @@ cp bin/linux_arm/syz-executor ~/syz-bin/
10. Build `syz-execprog` on your host machine for arm32 with `make TARGETARCH=arm execprog` and copy to `~/syz-bin` onto the SD card. You may try building syz-execprog on the Raspberry Pi itself, but that worked poorly for me due to large memory consumption during the compilation process.
-11. Make sure that ou can now execute syzkaller programs:
+11. Make sure that you can now execute syzkaller programs:
``` bash
cat socket.log
@@ -208,7 +202,7 @@ cp bin/linux_arm/syz-executor ~/syz-bin/
15. Insert the module with `sudo insmod raw_gadget.ko`.
-16. [Download](https://raw.githubusercontent.com/xairy/raw-gadget/master/examples/keyboard.c), build and run the [keyboard emulator program](https://github.com/xairy/raw-gadget/tree/master/examples):
+16. [Download](https://raw.githubusercontent.com/xairy/raw-gadget/master/examples/keyboard.c), build, and run the [keyboard emulator program](https://github.com/xairy/raw-gadget/tree/master/examples):
``` bash
# Get keyboard.c
@@ -227,7 +221,7 @@ cp bin/linux_arm/syz-executor ~/syz-bin/
18. Steps 19 through 21 are optional. You may use a UART console and a normal USB cable instead of ssh and Zero Stem.
-19. Follow [this](https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md) to setup Wi-Fi hotspot.
+19. Follow [this](https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md) to set up a Wi-Fi hotspot.
20. Follow [this](https://www.raspberrypi.org/documentation/remote-access/ssh/) to enable ssh.