Jorge Lucangeli Obes | 3ce29f4 | 2012-06-22 15:54:54 -0700 | [diff] [blame] | 1 | # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | |
Thieu Le | de232f5 | 2010-09-29 11:05:17 -0700 | [diff] [blame] | 6 | import os, subprocess, time, re |
Eric Li | e7c4cab | 2011-01-05 14:39:19 -0800 | [diff] [blame] | 7 | from autotest_lib.client.bin import utils |
Eric Li | c4d8f4a | 2010-12-10 09:49:23 -0800 | [diff] [blame] | 8 | from autotest_lib.client.common_lib import error |
Eric Li | e7c4cab | 2011-01-05 14:39:19 -0800 | [diff] [blame] | 9 | from autotest_lib.client.cros import cros_ui_test, login |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 10 | |
Eric Li | e7c4cab | 2011-01-05 14:39:19 -0800 | [diff] [blame] | 11 | class security_RendererSandbox(cros_ui_test.UITest): |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 12 | version = 1 |
| 13 | render_pid = -1 |
| 14 | |
Antoine Labour | 2d20c3b | 2010-10-29 16:03:17 -0700 | [diff] [blame] | 15 | |
| 16 | def check_for_seccomp_sandbox(self): |
| 17 | # the seccomp sandbox has exactly one child process that has no |
| 18 | # other threads, this is the trusted helper process. |
| 19 | seccomp = subprocess.Popen(['ps', 'h', '--format', 'pid', |
| 20 | '--ppid', '%s' % self.render_pid], |
| 21 | stdout=subprocess.PIPE) |
| 22 | helper_processes = seccomp.communicate()[0].splitlines() |
| 23 | if len(helper_processes) != 1: |
| 24 | raise error.TestFail('Invalid number of Renderer child process') |
| 25 | |
| 26 | helper_pid = helper_processes[0].strip() |
| 27 | threads = os.listdir('/proc/%s/task' % helper_pid) |
| 28 | if len(threads) != 1: |
| 29 | raise error.TestFail('Invalid number of helper process threads') |
| 30 | |
| 31 | exe = os.readlink('/proc/%s/exe' % helper_pid) |
| 32 | pattern = re.compile('/chrome$') |
| 33 | chrome = pattern.search(exe) |
| 34 | if chrome == None: |
| 35 | raise error.TestFail('Invalid child process executable') |
| 36 | |
| 37 | |
| 38 | def check_for_suid_sandbox(self): |
| 39 | # for setuid sandbox, make sure there is no content in the CWD |
| 40 | # directory |
| 41 | cwd_contents = os.listdir('/proc/%s/cwd' % self.render_pid) |
| 42 | if len(cwd_contents) > 0: |
| 43 | raise error.TestFail('Contents present in the CWD directory') |
| 44 | |
| 45 | |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 46 | def run_once(self, time_to_wait=20): |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 47 | |
Radoslav Vasilev | 40fef15 | 2010-07-13 17:54:45 +0200 | [diff] [blame] | 48 | # wait till the page is loaded and poll for the renderer pid |
| 49 | # if renderer pid is found, it is stored in self.render_pid |
Eric Li | cb6a91a | 2010-12-08 17:08:09 -0800 | [diff] [blame] | 50 | utils.poll_for_condition( |
Radoslav Vasilev | 40fef15 | 2010-07-13 17:54:45 +0200 | [diff] [blame] | 51 | self._get_renderer_pid, |
| 52 | error.TestFail('Timed out waiting to obtain pid of renderer'), |
| 53 | time_to_wait) |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 54 | |
Thieu Le | de232f5 | 2010-09-29 11:05:17 -0700 | [diff] [blame] | 55 | # check if renderer is sandboxed |
| 56 | # for now, x86 renderer must be running in a seccomp sandbox and |
| 57 | # arm render must run in a setuid sandbox |
| 58 | arch = utils.get_arch() |
| 59 | if arch == 'i386': |
Antoine Labour | 2d20c3b | 2010-10-29 16:03:17 -0700 | [diff] [blame] | 60 | # Seccomp is currently disabled because of performance issues. See |
| 61 | # crosbug.com/8397 |
| 62 | # self.check_for_seccomp_sandbox() |
| 63 | self.check_for_suid_sandbox() |
Thieu Le | de232f5 | 2010-09-29 11:05:17 -0700 | [diff] [blame] | 64 | else: |
Antoine Labour | 2d20c3b | 2010-10-29 16:03:17 -0700 | [diff] [blame] | 65 | self.check_for_suid_sandbox() |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 66 | |
| 67 | |
| 68 | # queries pgrep for the pid of the renderer. since this function is passed |
Eric Li | cb6a91a | 2010-12-08 17:08:09 -0800 | [diff] [blame] | 69 | # as an argument to utils.poll_for_condition, the return values are set |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 70 | # to true/false depending on whether a pid has been found |
Jorge Lucangeli Obes | 3ce29f4 | 2012-06-22 15:54:54 -0700 | [diff] [blame] | 71 | def _get_renderer_pid(self): |
| 72 | pgrep = subprocess.Popen(['pgrep', '-f', '-l', 'type=renderer'], |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 73 | stdout=subprocess.PIPE) |
Jorge Lucangeli Obes | 3ce29f4 | 2012-06-22 15:54:54 -0700 | [diff] [blame] | 74 | procs = pgrep.communicate()[0].splitlines() |
| 75 | pids = [] |
| 76 | # we're adding '--ignored= --type=renderer' to the GPU process cmdline |
| 77 | # to fix http://code.google.com/p/chromium/issues/detail?id=129884 |
| 78 | # this confuses 'pgrep' above, returning the pid of the GPU process, |
| 79 | # which is not sandboxed, as the pid of a renderer, breaking the test |
| 80 | for proc in procs: |
| 81 | if '--ignored= --type=renderer' not in proc: |
| 82 | pids.append(proc.split()[0]) |
| 83 | |
Radoslav Vasilev | 289b496 | 2010-07-09 10:40:16 +0200 | [diff] [blame] | 84 | if pids: |
| 85 | self.render_pid = pids[0] |
| 86 | return True |
| 87 | else: |
Thieu Le | de232f5 | 2010-09-29 11:05:17 -0700 | [diff] [blame] | 88 | return False |