1 #!/bin/bash 2 # Copyright (c) 2012 The Chromium OS Authors. 3 # 4 # Based on: 5 # http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/view/head:/scripts/kernel-security/ptrace/ptrace-restrictions.sh 6 # Copyright (C) 2010-2011 Canonical Ltd. 7 # License: GPLv3 8 # Author: Kees Cook <kees.cook (at] canonical.com> 9 set -e 10 if [ "$(whoami)" = "root" ]; then 11 echo "Cannot be root for this test" >&2 12 exit 1 13 fi 14 15 export LANG=C 16 pid= 17 dir= 18 19 function start_sleeper() 20 { 21 dir=$(mktemp -d -t sleeper-XXXXXX) 22 mkfifo "$dir"/status 23 ./sleeper "$1" 120 >"$dir"/status & 24 pid=$! 25 # Wait for sleeper to start up. 26 read status < "$dir"/status 27 } 28 29 function kill_sleeper() 30 { 31 disown $pid 32 kill $pid 33 rm -rf "$dir" 34 } 35 36 rc=0 37 38 # Check we can see direct children. 39 OUT=$(gdb -ex run -ex quit --batch ./sleeper </dev/null 2>&1) 40 if echo "$OUT" | grep -q 'Quit anyway'; then 41 echo "ok: children correctly allow ptrace" 42 else 43 echo "FAIL: Children unexpectedly not allow ptrace" 44 rc=1 45 fi 46 47 # Check we can't see cousins. 48 sleep 120 & 49 pid=$! 50 OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1) 51 if echo "$OUT" | grep -q 'Operation not permitted'; then 52 echo "ok: cousins correctly not allow ptrace" 53 else 54 echo "FAIL: cousins unexpectedly allow ptrace" 55 rc=1 56 fi 57 58 # Validate we can see cousin /proc entries. 59 if ls -la /proc/$pid/exe >/dev/null 2>&1; then 60 echo "ok: cousins correctly visible in /proc" 61 else 62 echo "FAIL: cousins unexpectedly invisible in /proc" 63 rc=1 64 fi 65 66 # Check we can't attach to init. 67 OUT=$(gdb -ex "attach 1" -ex "quit" --batch </dev/null 2>&1) 68 if echo "$OUT" | grep -q 'Operation not permitted'; then 69 echo "ok: init correctly not allowing ptrace" 70 else 71 echo "FAIL: init unexpectedly allowed ptrace" 72 rc=1 73 fi 74 75 # Check we can't see init. 76 if ! ls -la /proc/1/exe >/dev/null 2>&1; then 77 echo "ok: init correctly invisible in /proc" 78 else 79 echo "FAIL: init unexpectedly visible in /proc" 80 rc=1 81 fi 82 83 # Drop the sleep process and destroy it without disrupting the shell. 84 disown $pid 85 kill $pid 86 87 # Validate that prctl(PR_SET_PTRACER, 0, ...) works to delete tracer. 88 start_sleeper 0 89 OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1) 90 prctl="prctl(PR_SET_PTRACER, 0, ...)" 91 if echo "$OUT" | grep -q 'Operation not permitted'; then 92 echo "ok: $prctl correctly not allowed ptrace" 93 else 94 echo "FAIL: $prctl unexpectedly allowed ptrace" 95 rc=1 96 fi 97 kill_sleeper 98 99 # Validate near ancestor allowed with PR_SET_PTRACER use. 100 start_sleeper $$ 101 OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1) 102 prctl="prctl(PR_SET_PTRACER, parent, ...)" 103 if echo "$OUT" | grep -q 'Quit anyway'; then 104 echo "ok: $prctl correctly allowed ptrace" 105 else 106 echo "FAIL: $prctl unexpectedly not allowed ptrace" 107 rc=1 108 fi 109 kill_sleeper 110 111 # Validate distant ancestor allowed with PR_SET_PTRACER use. 112 start_sleeper 1 113 OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1) 114 prctl="prctl(PR_SET_PTRACER, 1, ...)" 115 if echo "$OUT" | grep -q 'Quit anyway'; then 116 echo "ok: $prctl correctly allowed ptrace" 117 else 118 echo "FAIL: $prctl unexpectedly not allowed ptrace" 119 rc=1 120 fi 121 kill_sleeper 122 123 # Validate -1 disables protection. 124 start_sleeper -1 125 OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1) 126 prctl="prctl(PR_SET_PTRACER, -1, ...)" 127 if echo "$OUT" | grep -q 'Quit anyway'; then 128 echo "ok: $prctl correctly allowed ptrace" 129 else 130 echo "FAIL: $prctl unexpectedly not allowed ptrace" 131 rc=1 132 fi 133 kill_sleeper 134 135 exit $rc 136