1# Copyright 2015 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 dbus 6import logging 7import os.path 8import socket 9 10from autotest_lib.client.bin import test, utils 11from autotest_lib.client.common_lib import error 12from autotest_lib.client.cros import constants, cros_ui, login 13 14 15class security_RestartJob(test.test): 16 """Verifies that RestartJob cannot be abused to execute arbitrary processes. 17 """ 18 version = 1 19 20 21 _FLAGFILE = '/tmp/security_RestartJob_regression' 22 23 24 def _ps(self, proc=constants.BROWSER): 25 """Grab the oldest pid for a process named |proc|.""" 26 pscmd = 'ps -C %s -o pid --no-header | head -1' % proc 27 return utils.system_output(pscmd) 28 29 30 def run_once(self): 31 """Main test code.""" 32 login.wait_for_browser() 33 bus = dbus.SystemBus() 34 proxy = bus.get_object('org.chromium.SessionManager', 35 '/org/chromium/SessionManager') 36 sessionmanager = dbus.Interface(proxy, 37 'org.chromium.SessionManagerInterface') 38 39 # Craft a malicious replacement for the target process. 40 cmd = ['touch', self._FLAGFILE] 41 42 # Try to get our malicious replacement to run via RestartJob. 43 try: 44 remote, local = socket.socketpair(socket.AF_UNIX) 45 logging.info('Calling RestartJob(<socket>, %r)', cmd) 46 sessionmanager.RestartJob(dbus.types.UnixFd(remote), cmd) 47 # Fails if the RestartJob call doesn't generate an error. 48 raise error.TestFail('RestartJob regression!') 49 except dbus.DBusException as e: 50 logging.info(e.get_dbus_message()) 51 pass 52 except OSError as e: 53 raise error.TestError('Could not create sockets for creds: %s', e) 54 finally: 55 try: 56 local.close() 57 except OSError: 58 pass 59 60 if os.path.exists(self._FLAGFILE): 61 raise error.TestFail('RestartJobWithAuth regression!') 62 63 64 def cleanup(self): 65 """Reset the UI, since this test killed Chrome.""" 66 cros_ui.nuke() 67