• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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