Home | History | Annotate | Download | only in tools
      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