Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add vHCI, a driver which allows to send and receive USB pack...



details:   https://anonhg.NetBSD.org/src/rev/1d1c8b35c533
branches:  trunk
changeset: 459502:1d1c8b35c533
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sat Sep 14 06:57:51 2019 +0000

description:
Add vHCI, a driver which allows to send and receive USB packets directly
from userland via /dev/vhci. Using this, it becomes possible to test and
fuzz the USB stack and all the USB drivers without having the associated
hardware.

The vHCI device has four ports independently addressable.

For each xfer on each port, we create two packets: a setup packet (which
indicates mostly the type of request) and a data packet (which contains
the raw data). These packets are processed by read and write operations
on /dev/vhci: userland poll-reads it to fetch usb_device_request_t
structures, and dispatches the requests depending on bRequest and
bmRequestType.

A few ioctls are available:

        VHCI_IOC_GET_INFO   - Get the current status
        VHCI_IOC_SET_PORT   - Choose a vHCI port
        VHCI_IOC_USB_ATTACH - Attach a USB device on the current port
        VHCI_IOC_USB_DETACH - Detach the USB device on the current port

vHCI has already allowed me to automatically find several bugs in the USB
stack and its drivers.

diffstat:

 etc/MAKEDEV.tmpl            |     7 +-
 sys/arch/amd64/conf/GENERIC |     8 +-
 sys/conf/files              |     7 +-
 sys/conf/majors             |     3 +-
 sys/dev/usb/vhci.c          |  1131 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 1151 insertions(+), 5 deletions(-)

diffs (truncated from 1235 to 300 lines):

diff -r 132e8489d37d -r 1d1c8b35c533 etc/MAKEDEV.tmpl
--- a/etc/MAKEDEV.tmpl  Fri Sep 13 20:56:29 2019 +0000
+++ b/etc/MAKEDEV.tmpl  Sat Sep 14 06:57:51 2019 +0000
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#      $NetBSD: MAKEDEV.tmpl,v 1.205 2019/07/29 17:53:20 gdt Exp $
+#      $NetBSD: MAKEDEV.tmpl,v 1.206 2019/09/14 06:57:52 maxv Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -286,6 +286,7 @@
 #      twe     3ware Escalade control interface
 #      uk*     unknown SCSI device
 #      veriexec Veriexec fingerprint loader
+#      vhci    virtual host controller interface
 #      video*  video capture devices
 #      view*   generic interface to graphic displays (Amiga)
 #      wsfont* console font control
@@ -1792,6 +1793,10 @@
        mkdev veriexec c %veriexec_chr% 0 600
        ;;
 
+vhci)
+       mkdev vhci c %vhci% 0
+       ;;
+
 ttyv[0-9]*)
        unit=${i#ttyv}
        mkdev ttyv$unit c %pc_chr% $unit
diff -r 132e8489d37d -r 1d1c8b35c533 sys/arch/amd64/conf/GENERIC
--- a/sys/arch/amd64/conf/GENERIC       Fri Sep 13 20:56:29 2019 +0000
+++ b/sys/arch/amd64/conf/GENERIC       Sat Sep 14 06:57:51 2019 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.534 2019/08/09 08:01:06 rin Exp $
+# $NetBSD: GENERIC,v 1.535 2019/09/14 06:57:51 maxv Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident         "GENERIC-$Revision: 1.534 $"
+#ident         "GENERIC-$Revision: 1.535 $"
 
 maxusers       64              # estimated number of users
 
@@ -890,6 +890,9 @@
 
 # USB Controller and Devices
 
+# Virtual USB controller
+#pseudo-device vhci
+
 # PCI USB controllers
 xhci*  at pci? dev ? function ?        # eXtensible Host Controller
 ehci*  at pci? dev ? function ?        # Enhanced Host Controller
@@ -908,6 +911,7 @@
 slhci* at pcmcia? function ?           # ScanLogic SL811HS
 
 # USB bus support
+#usb*  at vhci?
 usb*   at xhci?
 usb*   at ehci?
 usb*   at ohci?
diff -r 132e8489d37d -r 1d1c8b35c533 sys/conf/files
--- a/sys/conf/files    Fri Sep 13 20:56:29 2019 +0000
+++ b/sys/conf/files    Sat Sep 14 06:57:51 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.1238 2019/09/02 20:09:29 riastradh Exp $
+#      $NetBSD: files,v 1.1239 2019/09/14 06:57:52 maxv Exp $
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
 version        20171118
@@ -1290,6 +1290,11 @@
 device xhci: usbus, usbroothub, usb_dma
 file   dev/usb/xhci.c                  xhci                    needs-flag
 
+# vHCI USB controller
+#
+defpseudodev vhci: usbus, usbroothub
+file   dev/usb/vhci.c                  vhci                    needs-flag
+
 # Mentor graphics OTG IP
 device motg: usbus, usbroothub
 file   dev/usb/motg.c                  motg                    needs-flag
diff -r 132e8489d37d -r 1d1c8b35c533 sys/conf/majors
--- a/sys/conf/majors   Fri Sep 13 20:56:29 2019 +0000
+++ b/sys/conf/majors   Sat Sep 14 06:57:51 2019 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.87 2019/05/18 08:38:00 mlelstv Exp $
+# $NetBSD: majors,v 1.88 2019/09/14 06:57:52 maxv Exp $
 #
 # Device majors for Machine-Independent drivers.
 #
@@ -86,3 +86,4 @@
 # Major 352 is reserved for external/cddl/osnet/dev/fbt/fbt.c
 # Major 353 is reserved for external/cddl/osnet/dev/sdt/sdt.c
 device-major ipmi      char 354                   ipmi
+device-major vhci      char 346            vhci
diff -r 132e8489d37d -r 1d1c8b35c533 sys/dev/usb/vhci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/usb/vhci.c        Sat Sep 14 06:57:51 2019 +0000
@@ -0,0 +1,1131 @@
+/*     $NetBSD: vhci.c,v 1.1 2019/09/14 06:57:52 maxv Exp $ */
+
+/*
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Maxime Villard.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.1 2019/09/14 06:57:52 maxv Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_usb.h"
+#endif
+
+#include <sys/param.h>
+
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mman.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+
+#include <machine/endian.h>
+
+#include "ioconf.h"
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+
+#include <dev/usb/usbroothub.h>
+
+#define VHCI_DEBUG
+
+#ifdef VHCI_DEBUG
+#define DPRINTF(fmt, ...)      printf(fmt, __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)      __nothing
+#endif
+
+static usbd_status vhci_open(struct usbd_pipe *);
+static void vhci_softintr(void *);
+
+static struct usbd_xfer *vhci_allocx(struct usbd_bus *, unsigned int);
+static void vhci_freex(struct usbd_bus *, struct usbd_xfer *);
+static void vhci_get_lock(struct usbd_bus *, kmutex_t **);
+static int vhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *,
+    void *, int);
+
+static const struct usbd_bus_methods vhci_bus_methods = {
+       .ubm_open =     vhci_open,
+       .ubm_softint =  vhci_softintr,
+       .ubm_dopoll =   NULL,
+       .ubm_allocx =   vhci_allocx,
+       .ubm_freex =    vhci_freex,
+       .ubm_getlock =  vhci_get_lock,
+       .ubm_rhctrl =   vhci_roothub_ctrl,
+};
+
+static usbd_status vhci_device_ctrl_transfer(struct usbd_xfer *);
+static usbd_status vhci_device_ctrl_start(struct usbd_xfer *);
+static void vhci_device_ctrl_abort(struct usbd_xfer *);
+static void vhci_device_ctrl_close(struct usbd_pipe *);
+static void vhci_device_ctrl_cleartoggle(struct usbd_pipe *);
+static void vhci_device_ctrl_done(struct usbd_xfer *);
+
+static const struct usbd_pipe_methods vhci_device_ctrl_methods = {
+       .upm_init =             NULL,
+       .upm_fini =             NULL,
+       .upm_transfer =         vhci_device_ctrl_transfer,
+       .upm_start =            vhci_device_ctrl_start,
+       .upm_abort =            vhci_device_ctrl_abort,
+       .upm_close =            vhci_device_ctrl_close,
+       .upm_cleartoggle =      vhci_device_ctrl_cleartoggle,
+       .upm_done =             vhci_device_ctrl_done,
+};
+
+static usbd_status vhci_root_intr_transfer(struct usbd_xfer *);
+static usbd_status vhci_root_intr_start(struct usbd_xfer *);
+static void vhci_root_intr_abort(struct usbd_xfer *);
+static void vhci_root_intr_close(struct usbd_pipe *);
+static void vhci_root_intr_cleartoggle(struct usbd_pipe *);
+static void vhci_root_intr_done(struct usbd_xfer *);
+
+static const struct usbd_pipe_methods vhci_root_intr_methods = {
+       .upm_init =             NULL,
+       .upm_fini =             NULL,
+       .upm_transfer =         vhci_root_intr_transfer,
+       .upm_start =            vhci_root_intr_start,
+       .upm_abort =            vhci_root_intr_abort,
+       .upm_close =            vhci_root_intr_close,
+       .upm_cleartoggle =      vhci_root_intr_cleartoggle,
+       .upm_done =             vhci_root_intr_done,
+};
+
+typedef struct vhci_packet {
+       LIST_ENTRY(vhci_packet) portlist;
+       LIST_ENTRY(vhci_packet) xferlist;
+       struct usbd_xfer *xfer; /* also vxfer */
+       uint8_t *buf;
+       size_t size;
+       size_t cursor;
+} vhci_packet_t;
+
+typedef LIST_HEAD(, vhci_packet) vhci_packet_list_t;
+
+typedef struct {
+       kmutex_t lock;
+       int status;
+       int change;
+       struct {
+               vhci_packet_list_t usb_to_host;
+               vhci_packet_list_t host_to_usb;
+       } pkts_device_ctrl;
+} vhci_port_t;
+
+typedef struct {
+       struct usbd_pipe pipe;
+} vhci_pipe_t;
+
+typedef struct vhci_xfer {
+       /* General. */
+       struct usbd_xfer xfer;
+
+       /* vHCI-specific. */
+       size_t refcnt;
+       vhci_port_t *port;
+       vhci_packet_list_t pkts;
+       LIST_ENTRY(vhci_xfer) freelist;
+} vhci_xfer_t;
+
+typedef LIST_HEAD(, vhci_xfer) vhci_xfer_list_t;
+
+#define VHCI_INDEX2PORT(idx)   (idx)
+#define VHCI_NPORTS            4
+
+typedef struct {
+       device_t sc_dev;
+
+       struct usbd_bus sc_bus;
+       bool sc_dying;
+       kmutex_t sc_lock;
+
+       /*
+        * Intr Root. Used to attach the devices.
+        */
+       struct usbd_xfer *sc_intrxfer;
+
+       /*
+        * The ports. Zero is for the roothub, one and beyond for the USB
+        * devices.
+        */
+       size_t sc_nports;
+       vhci_port_t sc_port[VHCI_NPORTS];
+
+       device_t sc_child; /* /dev/usb# device */
+} vhci_softc_t;
+
+typedef struct {
+       u_int port;
+       vhci_softc_t *softc;
+} vhci_fd_t;
+
+extern struct cfdriver vhci_cd;



Home | Main Index | Thread Index | Old Index