# Copyright 2017 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import errno import fcntl import logging import struct from autotest_lib.client.bin import test, utils from autotest_lib.client.common_lib import error from autotest_lib.client.cros import device_jail_test_base from autotest_lib.client.cros import device_jail_utils # Definitions here are found in the uapi header linux/usbdevice_fs.h. # struct usbdevfs_ioctl { # int ifno; # int ioctl_code; # void __user *data; # }; def usbdevfs_ioctl(ifno, ioctl_code): return struct.pack('iiP', ifno, ioctl_code, 0) # #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl) USBDEVFS_IOCTL = (3 << 30) + \ (ord('U') << 8) + \ 18 + \ (struct.calcsize('iiP') << 16) # #define USBDEVFS_DISCONNECT _IO('U', 22) USBDEVFS_DISCONNECT = (ord('U') << 8) + 22 class security_DeviceJail_Lockdown(device_jail_test_base.DeviceJailTestBase): """ Simulate permission_broker locking the device down before letting us open it, and then try to perform a privileged operation such as disconnecting the kernel driver. If we are allowed to perform the operation, something is broken. """ version = 1 def _find_device_with_interface(self): usb_devices = device_jail_utils.get_usb_devices() if not usb_devices: error.TestNAError('No USB devices found') for device in usb_devices: if not device.children: continue for child in device.children: if child.device_type != 'usb_interface': continue return (device.device_node, child.attributes.asint('bInterfaceNumber')) return (None, None) def run_once(self): dev_path, dev_intf = self._find_device_with_interface() if not dev_path: raise error.TestNAError('No suitable USB devices found') logging.info('Using device %s, interface %d', dev_path, dev_intf) with device_jail_utils.JailDevice(dev_path) as jail: f = jail.expect_open(device_jail_utils.REQUEST_ALLOW_WITH_LOCKDOWN) if not f: raise error.TestError('Failed to open allowed jail') with f as fd: try: fcntl.ioctl(fd, USBDEVFS_IOCTL, usbdevfs_ioctl(dev_intf, USBDEVFS_DISCONNECT)) except IOError as e: if e.errno != errno.EACCES: raise error.TestError( 'Got wrong error from ioctl: %s' % e.strerror) else: raise error.TestError('ioctl was incorrectly allowed')