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 5import errno 6import logging 7import os.path 8import pyudev 9import struct 10from autotest_lib.client.bin import test, utils 11from autotest_lib.client.common_lib import error 12from autotest_lib.client.cros import device_jail_test_base 13from autotest_lib.client.cros import device_jail_utils 14 15 16class security_DeviceJail_Detach(device_jail_test_base.DeviceJailTestBase): 17 """ 18 Simulate permission_broker detaching the kernel driver before we 19 open it, and then check to make sure it is really detached. Also, 20 check to make sure the driver is reattached after we close it. 21 """ 22 version = 1 23 24 def _get_multi_intf_device(self): 25 usb_devices = device_jail_utils.get_usb_devices() 26 if not usb_devices: 27 error.TestNAError('No USB devices found') 28 29 for device in usb_devices: 30 if device.attributes.asint('bNumInterfaces') > 1: 31 return device 32 33 return None 34 35 36 def _force_reattach_driver(self, intf, driver): 37 try: 38 with open('/sys/bus/usb/drivers/%s/bind' % driver, 39 'w') as bind_file: 40 bind_file.write(os.path.basename(intf)) 41 except IOError as e: 42 # This might happen if force-reattaching an earlier 43 # interface also reattached this one. Just ignore it. 44 pass 45 46 47 def _get_interface_drivers(self, device): 48 return { child.device_path : child.driver for child in device.children 49 if child.device_type == 'usb_interface' } 50 51 52 def run_once(self): 53 device = self._get_multi_intf_device() 54 if not device: 55 raise error.TestNAError('No suitable USB device found') 56 57 dev_path = device.device_node 58 pre_detach_drivers = self._get_interface_drivers(device) 59 logging.info('Found device %s', dev_path) 60 61 with device_jail_utils.JailDevice(dev_path) as jail: 62 # This should succeed and return a file. 63 f = jail.expect_open(device_jail_utils.REQUEST_ALLOW_WITH_DETACH) 64 if not f: 65 raise error.TestError('Failed to open allowed jail') 66 with f: 67 detach_drivers = self._get_interface_drivers(device) 68 post_detach_drivers = self._get_interface_drivers(device) 69 70 failed_detach = {} 71 failed_reattach = {} 72 for intf, driver in pre_detach_drivers.items(): 73 if detach_drivers[intf]: 74 failed_detach[intf] = driver 75 if driver != post_detach_drivers[intf]: 76 self._force_reattach_driver(intf, driver) 77 failed_reattach[intf] = driver 78 79 if failed_detach: 80 raise error.TestError('Drivers failed to detach from interfaces:\n' 81 + '\n'.join(intf for intf in failed_detach)) 82 if failed_reattach: 83 raise error.TestError('Drivers failed to reattach to interfaces:\n' 84 + '\n'.join(intf for intf in failed_reattach)) 85