1 #!/bin/bash 2 3 # Copyright (c) 2010 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 # This utility finds the different processes in a running instance of Chrome. 8 # It then attempts to identify their types (e.g. browser, extension, plugin, 9 # zygote, renderer). It also prints out information on whether a sandbox is 10 # active and what type of sandbox has been identified. 11 12 # This script is likely to only work on Linux or systems that closely mimick 13 # Linux's /proc filesystem. 14 [ -x /proc/self/exe ] || { 15 echo "This script cannot be run on your system" >&2 16 exit 1 17 } 18 19 # Find the browser's process id. If there are multiple active instances of 20 # Chrome, the caller can provide a pid on the command line. The provided pid 21 # must match a process in the browser's process hierarchy. When using the 22 # zygote inside of the setuid sandbox, renderers are in a process tree separate 23 # from the browser process. You cannot use any of their pids. 24 # If no pid is provided on the command line, the script will randomly pick 25 # one of the running instances. 26 if [ $# -eq 0 ]; then 27 pid=$(ls -l /proc/*/exe 2>/dev/null | 28 sed '/\/chrome\( .deleted.\)\?$/s,.*/proc/\([^/]*\)/exe.*,\1,;t;d' | 29 while read p; do 30 xargs -0 </proc/$p/cmdline 2>/dev/null|grep -q -- --type= && continue 31 echo "$p" 32 break 33 done) 34 else 35 pid="$1" 36 fi 37 ls -l "/proc/$pid/exe" 2>/dev/null|egrep -q '/chrome( .deleted.)?$' || { 38 echo "Cannot find any running instance of Chrome" >&2; exit 1; } 39 while :; do 40 ppid="$(ps h --format ppid --pid "$pid" 2>/dev/null)" 41 [ -n "$ppid" ] || { 42 echo "Cannot find any running instance of Chrome" >&2; exit 1; } 43 ls -l "/proc/$ppid/exe" 2>/dev/null|egrep -q '/chrome( .deleted.)?$' && 44 pid="$ppid" || break 45 done 46 xargs -0 </proc/$p/cmdline 2>/dev/null|grep -q -- --type= && { 47 echo "Cannot find any running instance of Chrome" >&2; exit 1; } 48 49 # Iterate over child processes and try to identify them 50 identify() { 51 local child cmd foundzygote plugin seccomp type 52 foundzygote=0 53 for child in $(ps h --format pid --ppid $1); do 54 cmd="$(xargs -0 </proc/$child/cmdline|sed 's/ -/\n-/g')" 2>/dev/null 55 type="$(echo "$cmd" | sed 's/--type=//;t1;d;:1;q')" 56 case $type in 57 '') 58 echo "Process $child is part of the browser" 59 identify "$child" 60 ;; 61 extension) 62 echo "Process $child is an extension" 63 ;; 64 plugin) 65 plugin="$(echo "$cmd" | 66 sed 's/--plugin-path=//;t1;d;:1 67 s,.*/lib,,;s,.*/npwrapper[.]lib,,;s,^np,,;s,[.]so$,,;q')" 68 echo "Process $child is a \"$plugin\" plugin" 69 identify "$child" 70 ;; 71 renderer|worker|gpu-process) 72 # The seccomp sandbox has exactly one child process that has no other 73 # threads. This is the trusted helper process. 74 seccomp="$(ps h --format pid --ppid $child|xargs)" 75 if [ -d /proc/$child/cwd/. ]; then 76 if [ $(echo "$seccomp" | wc -w) -eq 1 ] && 77 [ $(ls /proc/$seccomp/task 2>/dev/null | wc -w) -eq 1 ] && 78 ls -l /proc/$seccomp/exe 2>/dev/null | 79 egrep -q '/chrome( .deleted.)?$'; then 80 echo "Process $child is a sandboxed $type (seccomp helper:" \ 81 "$seccomp)" 82 else 83 echo "Process $child is a $type" 84 identify "$child" 85 fi 86 else 87 if [ $(echo "$seccomp" | wc -w) -eq 1 ]; then 88 echo "Process $child is a setuid sandboxed $type (seccomp" \ 89 "helper: $seccomp)" 90 else 91 echo "Process $child is a $type; setuid sandbox is active" 92 identify "$child" 93 fi 94 fi 95 ;; 96 zygote) 97 foundzygote=1 98 echo "Process $child is the zygote" 99 identify "$child" 100 ;; 101 *) 102 echo "Process $child is of unknown type \"$type\"" 103 identify "$child" 104 ;; 105 esac 106 done 107 return $foundzygote 108 } 109 110 cmpcmdline() { 111 # Checks that the command line arguments for pid $1 are a superset of the 112 # commandline arguments for pid $2. 113 # Any additional function arguments $3, $4, ... list options that should 114 # be ignored for the purpose of this comparison. 115 local pida="$1" 116 local pidb="$2" 117 shift; shift 118 local super=("$@" $(xargs -0 </proc/"$pida"/cmdline)) 2>/dev/null 119 local sub=($(xargs -0 </proc/"$pidb"/cmdline)) 2>/dev/null 120 local i j 121 [ ${#sub[*]} -eq 0 -o ${#super[*]} -eq 0 ] && return 1 122 for i in $(seq 0 $((${#sub[*]}-1))); do 123 for j in $(seq 0 $((${#super[*]}-1))); do 124 [ "x${sub[$i]}" = "x${super[$j]}" ] && continue 2 125 done 126 return 1 127 done 128 return 0 129 } 130 131 132 echo "The browser's main pid is: $pid" 133 if identify "$pid"; then 134 # The zygote can make it difficult to locate renderers, as the setuid 135 # sandbox causes it to be reparented to "init". When this happens, we can 136 # no longer associate it with the browser with 100% certainty. We make a 137 # best effort by comparing command line strings. 138 for i in $(ps h --format pid --ppid 1); do 139 if cmpcmdline "$pid" "$i" "--type=zygote"; then 140 echo -n "Process $i is the zygote" 141 [ -d /proc/$i/cwd/. ] || echo -n "; setuid sandbox is active" 142 echo 143 identify "$i" 144 fi 145 done 146 fi 147