diff options
| author | Andrey Konovalov <andreyknvl@google.com> | 2020-12-15 22:40:49 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-12-16 05:50:12 +0100 |
| commit | 649595c630f7581dc8aba66a183381b2a923d9e6 (patch) | |
| tree | 6fc7ebe5dfd676f26cd4a4234c88cd92c9e45d02 /docs/linux | |
| parent | 0053126c583f5ddf1e8092ab75db8d8446891897 (diff) | |
docs: update USB documentation
Minor updates and readability improvements.
Diffstat (limited to 'docs/linux')
| -rw-r--r-- | docs/linux/external_fuzzing_usb.md | 56 |
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. |
