#!/bin/bash # Copyright (c) 2010 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # This utility finds the different processes in a running instance of Chrome. # It then attempts to identify their types (e.g. browser, extension, plugin, # zygote, renderer). It also prints out information on whether a sandbox is # active and what type of sandbox has been identified. # This script is likely to only work on Linux or systems that closely mimick # Linux's /proc filesystem. [ -x /proc/self/exe ] || { echo "This script cannot be run on your system" >&2 exit 1 } # Find the browser's process id. If there are multiple active instances of # Chrome, the caller can provide a pid on the command line. The provided pid # must match a process in the browser's process hierarchy. When using the # zygote inside of the setuid sandbox, renderers are in a process tree separate # from the browser process. You cannot use any of their pids. # If no pid is provided on the command line, the script will randomly pick # one of the running instances. if [ $# -eq 0 ]; then pid=$(ls -l /proc/*/exe 2>/dev/null | sed '/\/chrome\( .deleted.\)\?$/s,.*/proc/\([^/]*\)/exe.*,\1,;t;d' | while read p; do xargs -0 </proc/$p/cmdline 2>/dev/null|grep -q -- --type= && continue echo "$p" break done) else pid="$1" fi ls -l "/proc/$pid/exe" 2>/dev/null|egrep -q '/chrome( .deleted.)?$' || { echo "Cannot find any running instance of Chrome" >&2; exit 1; } while :; do ppid="$(ps h --format ppid --pid "$pid" 2>/dev/null)" [ -n "$ppid" ] || { echo "Cannot find any running instance of Chrome" >&2; exit 1; } ls -l "/proc/$ppid/exe" 2>/dev/null|egrep -q '/chrome( .deleted.)?$' && pid="$ppid" || break done xargs -0 </proc/$p/cmdline 2>/dev/null|grep -q -- --type= && { echo "Cannot find any running instance of Chrome" >&2; exit 1; } # Iterate over child processes and try to identify them identify() { local child cmd foundzygote plugin seccomp type foundzygote=0 for child in $(ps h --format pid --ppid $1); do cmd="$(xargs -0 </proc/$child/cmdline|sed 's/ -/\n-/g')" 2>/dev/null type="$(echo "$cmd" | sed 's/--type=//;t1;d;:1;q')" case $type in '') echo "Process $child is part of the browser" identify "$child" ;; extension) echo "Process $child is an extension" ;; plugin) plugin="$(echo "$cmd" | sed 's/--plugin-path=//;t1;d;:1 s,.*/lib,,;s,.*/npwrapper[.]lib,,;s,^np,,;s,[.]so$,,;q')" echo "Process $child is a \"$plugin\" plugin" identify "$child" ;; renderer|worker|gpu-process) # The seccomp sandbox has exactly one child process that has no other # threads. This is the trusted helper process. seccomp="$(ps h --format pid --ppid $child|xargs)" if [ -d /proc/$child/cwd/. ]; then if [ $(echo "$seccomp" | wc -w) -eq 1 ] && [ $(ls /proc/$seccomp/task 2>/dev/null | wc -w) -eq 1 ] && ls -l /proc/$seccomp/exe 2>/dev/null | egrep -q '/chrome( .deleted.)?$'; then echo "Process $child is a sandboxed $type (seccomp helper:" \ "$seccomp)" else echo "Process $child is a $type" identify "$child" fi else if [ $(echo "$seccomp" | wc -w) -eq 1 ]; then echo "Process $child is a setuid sandboxed $type (seccomp" \ "helper: $seccomp)" else echo "Process $child is a $type; setuid sandbox is active" identify "$child" fi fi ;; zygote) foundzygote=1 echo "Process $child is the zygote" identify "$child" ;; *) echo "Process $child is of unknown type \"$type\"" identify "$child" ;; esac done return $foundzygote } cmpcmdline() { # Checks that the command line arguments for pid $1 are a superset of the # commandline arguments for pid $2. # Any additional function arguments $3, $4, ... list options that should # be ignored for the purpose of this comparison. local pida="$1" local pidb="$2" shift; shift local super=("$@" $(xargs -0 </proc/"$pida"/cmdline)) 2>/dev/null local sub=($(xargs -0 </proc/"$pidb"/cmdline)) 2>/dev/null local i j [ ${#sub[*]} -eq 0 -o ${#super[*]} -eq 0 ] && return 1 for i in $(seq 0 $((${#sub[*]}-1))); do for j in $(seq 0 $((${#super[*]}-1))); do [ "x${sub[$i]}" = "x${super[$j]}" ] && continue 2 done return 1 done return 0 } echo "The browser's main pid is: $pid" if identify "$pid"; then # The zygote can make it difficult to locate renderers, as the setuid # sandbox causes it to be reparented to "init". When this happens, we can # no longer associate it with the browser with 100% certainty. We make a # best effort by comparing command line strings. for i in $(ps h --format pid --ppid 1); do if cmpcmdline "$pid" "$i" "--type=zygote"; then echo -n "Process $i is the zygote" [ -d /proc/$i/cwd/. ] || echo -n "; setuid sandbox is active" echo identify "$i" fi done fi