Commit 7bae0432 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Greg Kroah-Hartman

usb: core: add option of only authorizing internal devices

On Chrome OS we want to use USBguard to potentially limit access to USB
devices based on policy. We however to do not want to wait for userspace to
come up before initializing fixed USB devices to not regress our boot
times.

This patch adds option to instruct the kernel to only authorize devices
connected to the internal ports. Previously we could either authorize
all or none (or, by default, we'd only authorize wired devices).

The behavior is controlled via usbcore.authorized_default command line
option.
Signed-off-by: default avatarDmitry Torokhov <dtor@chromium.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ca942a0e
...@@ -4697,7 +4697,8 @@ ...@@ -4697,7 +4697,8 @@
usbcore.authorized_default= usbcore.authorized_default=
[USB] Default USB device authorization: [USB] Default USB device authorization:
(default -1 = authorized except for wireless USB, (default -1 = authorized except for wireless USB,
0 = not authorized, 1 = authorized) 0 = not authorized, 1 = authorized, 2 = authorized
if device connected to internal port)
usbcore.autosuspend= usbcore.autosuspend=
[USB] The autosuspend time delay (in seconds) used [USB] The autosuspend time delay (in seconds) used
......
...@@ -34,7 +34,9 @@ $ echo 1 > /sys/bus/usb/devices/usbX/authorized_default ...@@ -34,7 +34,9 @@ $ echo 1 > /sys/bus/usb/devices/usbX/authorized_default
By default, Wired USB devices are authorized by default to By default, Wired USB devices are authorized by default to
connect. Wireless USB hosts deauthorize by default all new connected connect. Wireless USB hosts deauthorize by default all new connected
devices (this is so because we need to do an authentication phase devices (this is so because we need to do an authentication phase
before authorizing). before authorizing). Writing "2" to the authorized_default attribute
causes kernel to only authorize by default devices connected to internal
USB ports.
Example system lockdown (lame) Example system lockdown (lame)
......
...@@ -373,13 +373,19 @@ static const u8 ss_rh_config_descriptor[] = { ...@@ -373,13 +373,19 @@ static const u8 ss_rh_config_descriptor[] = {
* -1 is authorized for all devices except wireless (old behaviour) * -1 is authorized for all devices except wireless (old behaviour)
* 0 is unauthorized for all devices * 0 is unauthorized for all devices
* 1 is authorized for all devices * 1 is authorized for all devices
* 2 is authorized for internal devices
*/ */
static int authorized_default = -1; #define USB_AUTHORIZE_WIRED -1
#define USB_AUTHORIZE_NONE 0
#define USB_AUTHORIZE_ALL 1
#define USB_AUTHORIZE_INTERNAL 2
static int authorized_default = USB_AUTHORIZE_WIRED;
module_param(authorized_default, int, S_IRUGO|S_IWUSR); module_param(authorized_default, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(authorized_default, MODULE_PARM_DESC(authorized_default,
"Default USB device authorization: 0 is not authorized, 1 is " "Default USB device authorization: 0 is not authorized, 1 is "
"authorized, -1 is authorized except for wireless USB (default, " "authorized, 2 is authorized for internal devices, -1 is "
"old behaviour"); "authorized except for wireless USB (default, old behaviour");
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
...@@ -884,7 +890,7 @@ static ssize_t authorized_default_show(struct device *dev, ...@@ -884,7 +890,7 @@ static ssize_t authorized_default_show(struct device *dev,
struct usb_hcd *hcd; struct usb_hcd *hcd;
hcd = bus_to_hcd(usb_bus); hcd = bus_to_hcd(usb_bus);
return snprintf(buf, PAGE_SIZE, "%u\n", !!HCD_DEV_AUTHORIZED(hcd)); return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
} }
static ssize_t authorized_default_store(struct device *dev, static ssize_t authorized_default_store(struct device *dev,
...@@ -900,11 +906,8 @@ static ssize_t authorized_default_store(struct device *dev, ...@@ -900,11 +906,8 @@ static ssize_t authorized_default_store(struct device *dev,
hcd = bus_to_hcd(usb_bus); hcd = bus_to_hcd(usb_bus);
result = sscanf(buf, "%u\n", &val); result = sscanf(buf, "%u\n", &val);
if (result == 1) { if (result == 1) {
if (val) hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); val : USB_DEVICE_AUTHORIZE_ALL;
else
clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
result = size; result = size;
} else { } else {
result = -EINVAL; result = -EINVAL;
...@@ -2748,18 +2751,26 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -2748,18 +2751,26 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_info(hcd->self.controller, "%s\n", hcd->product_desc); dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
/* Keep old behaviour if authorized_default is not in [0, 1]. */ switch (authorized_default) {
if (authorized_default < 0 || authorized_default > 1) { case USB_AUTHORIZE_NONE:
if (hcd->wireless) hcd->dev_policy = USB_DEVICE_AUTHORIZE_NONE;
clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); break;
else
set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); case USB_AUTHORIZE_ALL:
} else { hcd->dev_policy = USB_DEVICE_AUTHORIZE_ALL;
if (authorized_default) break;
set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
else case USB_AUTHORIZE_INTERNAL:
clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags); hcd->dev_policy = USB_DEVICE_AUTHORIZE_INTERNAL;
break;
case USB_AUTHORIZE_WIRED:
default:
hcd->dev_policy = hcd->wireless ?
USB_DEVICE_AUTHORIZE_NONE : USB_DEVICE_AUTHORIZE_ALL;
break;
} }
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* per default all interfaces are authorized */ /* per default all interfaces are authorized */
......
...@@ -46,8 +46,7 @@ ...@@ -46,8 +46,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include "usb.h" #include "hub.h"
const char *usbcore_name = "usbcore"; const char *usbcore_name = "usbcore";
...@@ -536,6 +535,27 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus) ...@@ -536,6 +535,27 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
return hcd->wireless; return hcd->wireless;
} }
static bool usb_dev_authorized(struct usb_device *dev, struct usb_hcd *hcd)
{
struct usb_hub *hub;
if (!dev->parent)
return true; /* Root hub always ok [and always wired] */
switch (hcd->dev_policy) {
case USB_DEVICE_AUTHORIZE_NONE:
default:
return false;
case USB_DEVICE_AUTHORIZE_ALL:
return true;
case USB_DEVICE_AUTHORIZE_INTERNAL:
hub = usb_hub_to_struct_hub(dev->parent);
return hub->ports[dev->portnum - 1]->connect_type ==
USB_PORT_CONNECT_TYPE_HARD_WIRED;
}
}
/** /**
* usb_alloc_dev - usb device constructor (usbcore-internal) * usb_alloc_dev - usb device constructor (usbcore-internal)
...@@ -663,12 +683,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, ...@@ -663,12 +683,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->connect_time = jiffies; dev->connect_time = jiffies;
dev->active_duration = -jiffies; dev->active_duration = -jiffies;
#endif #endif
if (root_hub) /* Root hub always ok [and always wired] */
dev->authorized = 1; dev->authorized = usb_dev_authorized(dev, usb_hcd);
else { if (!root_hub)
dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd);
dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0; dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
}
return dev; return dev;
} }
EXPORT_SYMBOL_GPL(usb_alloc_dev); EXPORT_SYMBOL_GPL(usb_alloc_dev);
......
...@@ -72,6 +72,12 @@ struct giveback_urb_bh { ...@@ -72,6 +72,12 @@ struct giveback_urb_bh {
struct usb_host_endpoint *completing_ep; struct usb_host_endpoint *completing_ep;
}; };
enum usb_dev_authorize_policy {
USB_DEVICE_AUTHORIZE_NONE = 0,
USB_DEVICE_AUTHORIZE_ALL = 1,
USB_DEVICE_AUTHORIZE_INTERNAL = 2,
};
struct usb_hcd { struct usb_hcd {
/* /*
...@@ -117,7 +123,6 @@ struct usb_hcd { ...@@ -117,7 +123,6 @@ struct usb_hcd {
#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */
#define HCD_FLAG_DEAD 6 /* controller has died? */ #define HCD_FLAG_DEAD 6 /* controller has died? */
#define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */ #define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */
#define HCD_FLAG_DEV_AUTHORIZED 8 /* authorize devices? */
/* The flags can be tested using these macros; they are likely to /* The flags can be tested using these macros; they are likely to
* be slightly faster than test_bit(). * be slightly faster than test_bit().
...@@ -142,8 +147,7 @@ struct usb_hcd { ...@@ -142,8 +147,7 @@ struct usb_hcd {
* or they require explicit user space authorization; this bit is * or they require explicit user space authorization; this bit is
* settable through /sys/class/usb_host/X/authorized_default * settable through /sys/class/usb_host/X/authorized_default
*/ */
#define HCD_DEV_AUTHORIZED(hcd) \ enum usb_dev_authorize_policy dev_policy;
((hcd)->flags & (1U << HCD_FLAG_DEV_AUTHORIZED))
/* Flags that get set only during HCD registration or removal. */ /* Flags that get set only during HCD registration or removal. */
unsigned rh_registered:1;/* is root hub registered? */ unsigned rh_registered:1;/* is root hub registered? */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment