Home | History | Annotate | Download | only in security_DeviceJail_Lockdown
      1 # Copyright 2017 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import errno
      6 import fcntl
      7 import logging
      8 import struct
      9 from autotest_lib.client.bin import test, utils
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.client.cros import device_jail_test_base
     12 from autotest_lib.client.cros import device_jail_utils
     13 
     14 
     15 # Definitions here are found in the uapi header linux/usbdevice_fs.h.
     16 
     17 # struct usbdevfs_ioctl {
     18 #         int     ifno;
     19 #         int     ioctl_code;
     20 #         void __user *data;
     21 # };
     22 def usbdevfs_ioctl(ifno, ioctl_code):
     23     return struct.pack('iiP', ifno, ioctl_code, 0)
     24 # #define USBDEVFS_IOCTL             _IOWR('U', 18, struct usbdevfs_ioctl)
     25 USBDEVFS_IOCTL = (3 << 30) + \
     26                  (ord('U') << 8) + \
     27                  18 + \
     28                  (struct.calcsize('iiP') << 16)
     29 # #define USBDEVFS_DISCONNECT        _IO('U', 22)
     30 USBDEVFS_DISCONNECT = (ord('U') << 8) + 22
     31 
     32 
     33 class security_DeviceJail_Lockdown(device_jail_test_base.DeviceJailTestBase):
     34     """
     35     Simulate permission_broker locking the device down before letting us
     36     open it, and then try to perform a privileged operation such as
     37     disconnecting the kernel driver. If we are allowed to perform the
     38     operation, something is broken.
     39     """
     40     version = 1
     41 
     42     def _find_device_with_interface(self):
     43         usb_devices = device_jail_utils.get_usb_devices()
     44         if not usb_devices:
     45             error.TestNAError('No USB devices found')
     46 
     47         for device in usb_devices:
     48             if not device.children:
     49                 continue
     50             for child in device.children:
     51                 if child.device_type != 'usb_interface':
     52                     continue
     53                 return (device.device_node,
     54                         child.attributes.asint('bInterfaceNumber'))
     55 
     56         return (None, None)
     57 
     58 
     59     def run_once(self):
     60         dev_path, dev_intf = self._find_device_with_interface()
     61         if not dev_path:
     62             raise error.TestNAError('No suitable USB devices found')
     63         logging.info('Using device %s, interface %d', dev_path, dev_intf)
     64 
     65         with device_jail_utils.JailDevice(dev_path) as jail:
     66             f = jail.expect_open(device_jail_utils.REQUEST_ALLOW_WITH_LOCKDOWN)
     67             if not f:
     68                 raise error.TestError('Failed to open allowed jail')
     69 
     70             with f as fd:
     71                 try:
     72                     fcntl.ioctl(fd, USBDEVFS_IOCTL,
     73                                 usbdevfs_ioctl(dev_intf, USBDEVFS_DISCONNECT))
     74                 except IOError as e:
     75                     if e.errno != errno.EACCES:
     76                         raise error.TestError(
     77                             'Got wrong error from ioctl: %s' % e.strerror)
     78                 else:
     79                     raise error.TestError('ioctl was incorrectly allowed')
     80