| # Copyright (c) 2010 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 dbus |
| import logging |
| import os.path |
| import socket |
| |
| from autotest_lib.client.bin import test, utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros import constants, cros_ui, login |
| |
| |
| class security_RestartJob(test.test): |
| """Verifies that RestartJob cannot be abused to execute arbitrary processes. |
| """ |
| version = 1 |
| |
| |
| _FLAGFILE = '/tmp/security_RestartJob_regression' |
| |
| |
| def _ps(self, proc=constants.BROWSER): |
| """Grab the oldest pid for a process named |proc|.""" |
| pscmd = 'ps -C %s -o pid --no-header | head -1' % proc |
| return utils.system_output(pscmd) |
| |
| |
| def run_once(self): |
| login.wait_for_browser() |
| bus = dbus.SystemBus() |
| proxy = bus.get_object('org.chromium.SessionManager', |
| '/org/chromium/SessionManager') |
| sessionmanager = dbus.Interface(proxy, |
| 'org.chromium.SessionManagerInterface') |
| |
| # We can't just start our own sacrificial process to let |
| # 'session_manager' kill, because it knows which processes it's |
| # managing, so we have to locate the pid of Chrome. |
| pid = int(self._ps()) |
| |
| # Craft a malicious replacement for the target process. |
| cmd = 'touch %s' % self._FLAGFILE |
| |
| # Try to get our malicious replacement to run. |
| logging.info('Calling RestartJob(%s, \'%s\')', pid, cmd) |
| try: |
| if sessionmanager.RestartJob(pid, cmd): |
| raise error.TestFail( |
| 'RestartJob regression, see crbug.com/193322') |
| except dbus.DBusException as e: |
| logging.info(e.get_dbus_message()) |
| pass |
| |
| if os.path.exists(self._FLAGFILE): |
| raise error.TestFail('RestartJob regression, see crbug.com/189233') |
| |
| # Try to get our malicious replacement to run via RestartJobWithAuth. |
| try: |
| remote, local = socket.socketpair(socket.AF_UNIX) |
| logging.info('Calling RestartJobWithAuth(<socket>, \'%s\')', cmd) |
| if sessionmanager.RestartJobWithAuth(dbus.types.UnixFd(remote), |
| cmd): |
| raise error.TestFail('RestartJobWithAuth regression!') |
| except dbus.DBusException as e: |
| logging.info(e.get_dbus_message()) |
| pass |
| except OSError as e: |
| raise error.TestError('Could not create sockets for creds: %s', e) |
| finally: |
| try: |
| local.close() |
| except OSError: |
| pass |
| |
| if os.path.exists(self._FLAGFILE): |
| raise error.TestFail('RestartJobWithAuth regression!') |
| |
| |
| def cleanup(self): |
| # Clean up, since this test killed Chrome. |
| cros_ui.nuke() |