chrome-process-identifier.sh 5.2 KB

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