Blame 0120-usb-redir-Add-the-posibility-to-filter-out-certain-d.patch

Hans de Goede 1b1995
From bcc4748db3e991fbaa032fe9c0726288a8f1008d Mon Sep 17 00:00:00 2001
Hans de Goede 1b1995
From: Hans de Goede <hdegoede@redhat.com>
Hans de Goede 1b1995
Date: Thu, 12 Jan 2012 16:54:04 +0100
Hans de Goede 1b1995
Subject: [PATCH 120/140] usb-redir: Add the posibility to filter out certain
Hans de Goede 1b1995
 devices from redirecion
Hans de Goede 1b1995
Hans de Goede 1b1995
This patch adds the posibility to filter out certain devices from redirecion.
Hans de Goede 1b1995
To use this pass the filter property to -device usb-redir.  The filter
Hans de Goede 1b1995
property takes a string consisting of filter rules, the format for a rule is:
Hans de Goede 1b1995
<class>:<vendor>:<product>:<version>:<allow>
Hans de Goede 1b1995
Hans de Goede 1b1995
-1 can be used to allow any value for a field.
Hans de Goede 1b1995
Hans de Goede 1b1995
Muliple rules can be concatonated using | as a separator. Note that if
Hans de Goede 1b1995
a device matches none of the passed in rules, redirecting it will not be
Hans de Goede 1b1995
allowed!
Hans de Goede 1b1995
Hans de Goede 1b1995
Example:
Hans de Goede 1b1995
-device usb-redir,filter='-1:0x0781:0x5567:-1:0|0x08:-1:-1:-1:1'
Hans de Goede 1b1995
Hans de Goede 1b1995
This example will deny the Sandisk Cruzer Blade being redirected, as it
Hans de Goede 1b1995
has a usb id of 0781:5567, it will allow any other usb mass storage devices,
Hans de Goede 1b1995
and it will deny any other devices (the default for devices not matching any
Hans de Goede 1b1995
of the rules.
Hans de Goede 1b1995
Hans de Goede 1b1995
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Hans de Goede 1b1995
---
Hans de Goede 1b1995
 configure   |    2 +-
Hans de Goede 1b1995
 usb-redir.c |  115 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
Hans de Goede 1b1995
 2 files changed, 106 insertions(+), 11 deletions(-)
Hans de Goede 1b1995
Hans de Goede 1b1995
diff --git a/configure b/configure
Hans de Goede 1b1995
index 7ecf44e..c7e37df 100755
Hans de Goede 1b1995
--- a/configure
Hans de Goede 1b1995
+++ b/configure
Hans de Goede 1b1995
@@ -2541,7 +2541,7 @@ fi
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 # check for usbredirparser for usb network redirection support
Hans de Goede 1b1995
 if test "$usb_redir" != "no" ; then
Hans de Goede 1b1995
-    if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
Hans de Goede 1b1995
+    if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
Hans de Goede 1b1995
         usb_redir="yes"
Hans de Goede 1b1995
         usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
Hans de Goede 1b1995
         usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
Hans de Goede 1b1995
diff --git a/usb-redir.c b/usb-redir.c
Hans de Goede 1b1995
index 6e92f14..85f40d6 100644
Hans de Goede 1b1995
--- a/usb-redir.c
Hans de Goede 1b1995
+++ b/usb-redir.c
Hans de Goede 1b1995
@@ -34,6 +34,7 @@
Hans de Goede 1b1995
 #include <sys/ioctl.h>
Hans de Goede 1b1995
 #include <signal.h>
Hans de Goede 1b1995
 #include <usbredirparser.h>
Hans de Goede 1b1995
+#include <usbredirfilter.h>
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 #include "hw/usb.h"
Hans de Goede 1b1995
 
Hans de Goede 1b1995
@@ -72,6 +73,7 @@ struct USBRedirDevice {
Hans de Goede 1b1995
     /* Properties */
Hans de Goede 1b1995
     CharDriverState *cs;
Hans de Goede 1b1995
     uint8_t debug;
Hans de Goede 1b1995
+    char *filter_str;
Hans de Goede 1b1995
     /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
Hans de Goede 1b1995
     const uint8_t *read_buf;
Hans de Goede 1b1995
     int read_buf_size;
Hans de Goede 1b1995
@@ -84,6 +86,11 @@ struct USBRedirDevice {
Hans de Goede 1b1995
     struct endp_data endpoint[MAX_ENDPOINTS];
Hans de Goede 1b1995
     uint32_t packet_id;
Hans de Goede 1b1995
     QTAILQ_HEAD(, AsyncURB) asyncq;
Hans de Goede 1b1995
+    /* Data for device filtering */
Hans de Goede 1b1995
+    struct usb_redir_device_connect_header device_info;
Hans de Goede 1b1995
+    struct usb_redir_interface_info_header interface_info;
Hans de Goede 1b1995
+    struct usbredirfilter_rule *filter_rules;
Hans de Goede 1b1995
+    int filter_rules_count;
Hans de Goede 1b1995
 };
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 struct AsyncURB {
Hans de Goede 1b1995
@@ -790,6 +797,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
Hans de Goede 1b1995
 static void usbredir_open_close_bh(void *opaque)
Hans de Goede 1b1995
 {
Hans de Goede 1b1995
     USBRedirDevice *dev = opaque;
Hans de Goede 1b1995
+    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
Hans de Goede 1b1995
 
Hans de Goede 1b1995
     usbredir_device_disconnect(dev);
Hans de Goede 1b1995
 
Hans de Goede 1b1995
@@ -820,7 +828,9 @@ static void usbredir_open_close_bh(void *opaque)
Hans de Goede 1b1995
         dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
Hans de Goede 1b1995
         dev->read_buf = NULL;
Hans de Goede 1b1995
         dev->read_buf_size = 0;
Hans de Goede 1b1995
-        usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+        usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
Hans de Goede 1b1995
+        usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
Hans de Goede 1b1995
         usbredirparser_do_write(dev->parser);
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
 }
Hans de Goede 1b1995
@@ -908,6 +918,17 @@ static int usbredir_initfn(USBDevice *udev)
Hans de Goede 1b1995
         return -1;
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
 
Hans de Goede 1b1995
+    if (dev->filter_str) {
Hans de Goede 1b1995
+        i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
Hans de Goede 1b1995
+                                           &dev->filter_rules,
Hans de Goede 1b1995
+                                           &dev->filter_rules_count);
Hans de Goede 1b1995
+        if (i) {
Hans de Goede 1b1995
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
Hans de Goede 1b1995
+                          "a usb device filter string");
Hans de Goede 1b1995
+            return -1;
Hans de Goede 1b1995
+        }
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
     dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
Hans de Goede 1b1995
     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
Hans de Goede 1b1995
 
Hans de Goede 1b1995
@@ -956,6 +977,44 @@ static void usbredir_handle_destroy(USBDevice *udev)
Hans de Goede 1b1995
     if (dev->parser) {
Hans de Goede 1b1995
         usbredirparser_destroy(dev->parser);
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    free(dev->filter_rules);
Hans de Goede 1b1995
+}
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+static int usbredir_check_filter(USBRedirDevice *dev)
Hans de Goede 1b1995
+{
Hans de Goede 1b1995
+    if (dev->interface_info.interface_count == 0) {
Hans de Goede 1b1995
+        ERROR("No interface info for device\n");
Hans de Goede 1b1995
+        return -1;
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    if (dev->filter_rules) {
Hans de Goede 1b1995
+        if (!usbredirparser_peer_has_cap(dev->parser,
Hans de Goede 1b1995
+                                    usb_redir_cap_connect_device_version)) {
Hans de Goede 1b1995
+            ERROR("Device filter specified and peer does not have the "
Hans de Goede 1b1995
+                  "connect_device_version capability\n");
Hans de Goede 1b1995
+            return -1;
Hans de Goede 1b1995
+        }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+        if (usbredirfilter_check(
Hans de Goede 1b1995
+                dev->filter_rules,
Hans de Goede 1b1995
+                dev->filter_rules_count,
Hans de Goede 1b1995
+                dev->device_info.device_class,
Hans de Goede 1b1995
+                dev->device_info.device_subclass,
Hans de Goede 1b1995
+                dev->device_info.device_protocol,
Hans de Goede 1b1995
+                dev->interface_info.interface_class,
Hans de Goede 1b1995
+                dev->interface_info.interface_subclass,
Hans de Goede 1b1995
+                dev->interface_info.interface_protocol,
Hans de Goede 1b1995
+                dev->interface_info.interface_count,
Hans de Goede 1b1995
+                dev->device_info.vendor_id,
Hans de Goede 1b1995
+                dev->device_info.product_id,
Hans de Goede 1b1995
+                dev->device_info.device_version_bcd,
Hans de Goede 1b1995
+                0) != 0) {
Hans de Goede 1b1995
+            return -1;
Hans de Goede 1b1995
+        }
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    return 0;
Hans de Goede 1b1995
 }
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 /*
Hans de Goede 1b1995
@@ -984,6 +1043,7 @@ static void usbredir_device_connect(void *priv,
Hans de Goede 1b1995
     struct usb_redir_device_connect_header *device_connect)
Hans de Goede 1b1995
 {
Hans de Goede 1b1995
     USBRedirDevice *dev = priv;
Hans de Goede 1b1995
+    const char *speed;
Hans de Goede 1b1995
 
Hans de Goede 1b1995
     if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
Hans de Goede 1b1995
         ERROR("Received device connect while already connected\n");
Hans de Goede 1b1995
@@ -992,26 +1052,48 @@ static void usbredir_device_connect(void *priv,
Hans de Goede 1b1995
 
Hans de Goede 1b1995
     switch (device_connect->speed) {
Hans de Goede 1b1995
     case usb_redir_speed_low:
Hans de Goede 1b1995
-        DPRINTF("attaching low speed device\n");
Hans de Goede 1b1995
+        speed = "low speed";
Hans de Goede 1b1995
         dev->dev.speed = USB_SPEED_LOW;
Hans de Goede 1b1995
         break;
Hans de Goede 1b1995
     case usb_redir_speed_full:
Hans de Goede 1b1995
-        DPRINTF("attaching full speed device\n");
Hans de Goede 1b1995
+        speed = "full speed";
Hans de Goede 1b1995
         dev->dev.speed = USB_SPEED_FULL;
Hans de Goede 1b1995
         break;
Hans de Goede 1b1995
     case usb_redir_speed_high:
Hans de Goede 1b1995
-        DPRINTF("attaching high speed device\n");
Hans de Goede 1b1995
+        speed = "high speed";
Hans de Goede 1b1995
         dev->dev.speed = USB_SPEED_HIGH;
Hans de Goede 1b1995
         break;
Hans de Goede 1b1995
     case usb_redir_speed_super:
Hans de Goede 1b1995
-        DPRINTF("attaching super speed device\n");
Hans de Goede 1b1995
+        speed = "super speed";
Hans de Goede 1b1995
         dev->dev.speed = USB_SPEED_SUPER;
Hans de Goede 1b1995
         break;
Hans de Goede 1b1995
     default:
Hans de Goede 1b1995
-        DPRINTF("attaching unknown speed device, assuming full speed\n");
Hans de Goede 1b1995
+        speed = "unknown speed";
Hans de Goede 1b1995
         dev->dev.speed = USB_SPEED_FULL;
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    if (usbredirparser_peer_has_cap(dev->parser,
Hans de Goede 1b1995
+                                    usb_redir_cap_connect_device_version)) {
Hans de Goede 1b1995
+        INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
Hans de Goede 1b1995
+             speed, device_connect->vendor_id, device_connect->product_id,
Hans de Goede 1b1995
+             device_connect->device_version_bcd >> 8,
Hans de Goede 1b1995
+             device_connect->device_version_bcd & 0xff,
Hans de Goede 1b1995
+             device_connect->device_class);
Hans de Goede 1b1995
+    } else {
Hans de Goede 1b1995
+        INFO("attaching %s device %04x:%04x class %02x\n", speed,
Hans de Goede 1b1995
+             device_connect->vendor_id, device_connect->product_id,
Hans de Goede 1b1995
+             device_connect->device_class);
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
     dev->dev.speedmask = (1 << dev->dev.speed);
Hans de Goede 1b1995
+    dev->device_info = *device_connect;
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    if (usbredir_check_filter(dev)) {
Hans de Goede 1b1995
+        WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
Hans de Goede 1b1995
+                device_connect->vendor_id, device_connect->product_id);
Hans de Goede 1b1995
+        return;
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
+
Hans de Goede 1b1995
     qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
Hans de Goede 1b1995
 }
Hans de Goede 1b1995
 
Hans de Goede 1b1995
@@ -1038,15 +1120,27 @@ static void usbredir_device_disconnect(void *priv)
Hans de Goede 1b1995
     for (i = 0; i < MAX_ENDPOINTS; i++) {
Hans de Goede 1b1995
         QTAILQ_INIT(&dev->endpoint[i].bufpq);
Hans de Goede 1b1995
     }
Hans de Goede 1b1995
+    dev->interface_info.interface_count = 0;
Hans de Goede 1b1995
 }
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 static void usbredir_interface_info(void *priv,
Hans de Goede 1b1995
     struct usb_redir_interface_info_header *interface_info)
Hans de Goede 1b1995
 {
Hans de Goede 1b1995
-    /* The intention is to allow specifying acceptable interface classes
Hans de Goede 1b1995
-       for redirection on the cmdline and in the future verify this here,
Hans de Goede 1b1995
-       and disconnect (or never connect) the device if a not accepted
Hans de Goede 1b1995
-       interface class is detected */
Hans de Goede 1b1995
+    USBRedirDevice *dev = priv;
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    dev->interface_info = *interface_info;
Hans de Goede 1b1995
+
Hans de Goede 1b1995
+    /*
Hans de Goede 1b1995
+     * If we receive interface info after the device has already been
Hans de Goede 1b1995
+     * connected (ie on a set_config), re-check the filter.
Hans de Goede 1b1995
+     */
Hans de Goede 1b1995
+    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
Hans de Goede 1b1995
+        if (usbredir_check_filter(dev)) {
Hans de Goede 1b1995
+            ERROR("Device no longer matches filter after interface info "
Hans de Goede 1b1995
+                  "change, disconnecting!\n");
Hans de Goede 1b1995
+            usbredir_device_disconnect(dev);
Hans de Goede 1b1995
+        }
Hans de Goede 1b1995
+    }
Hans de Goede 1b1995
 }
Hans de Goede 1b1995
 
Hans de Goede 1b1995
 static void usbredir_ep_info(void *priv,
Hans de Goede 1b1995
@@ -1356,6 +1450,7 @@ static struct USBDeviceInfo usbredir_dev_info = {
Hans de Goede 1b1995
     .qdev.props     = (Property[]) {
Hans de Goede 1b1995
         DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
Hans de Goede 1b1995
         DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
Hans de Goede 1b1995
+        DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
Hans de Goede 1b1995
         DEFINE_PROP_END_OF_LIST(),
Hans de Goede 1b1995
     },
Hans de Goede 1b1995
 };
Hans de Goede 1b1995
-- 
Hans de Goede 1b1995
1.7.9.3
Hans de Goede 1b1995