1#!/bin/bash
2#
3# Run through a series of tests to try out the various capability
4# manipulations posible through exec.
5#
6# [Run this as root in a root-enabled process tree.]
7
8try_capsh () {
9    echo "TEST: ./capsh $*"
10    ./capsh "$@"
11    if [ $? -ne 0 ]; then
12	echo FAILED
13	return 1
14    else
15	echo PASSED
16	return 0
17    fi
18}
19
20fail_capsh () {
21    echo -n "EXPECT FAILURE: "
22    try_capsh "$@"
23    if [ $? -eq 1 ]; then
24	echo "[WHICH MEANS A PASS!]"
25	return 0
26    else
27	echo "Undesired result - aborting"
28	echo "PROBLEM TEST: $*"
29	exit 1
30    fi
31}
32
33pass_capsh () {
34    echo -n "EXPECT SUCCESS: "
35    try_capsh "$@"
36    if [ $? -eq 0 ]; then
37	return 0
38    else
39	echo "Undesired result - aborting"
40	echo "PROBLEM TEST: $*"
41	exit 1
42    fi
43}
44
45pass_capsh --print
46
47
48# Make a local non-setuid-0 version of capsh and call it privileged
49cp ./capsh ./privileged && chmod -s ./privileged
50if [ $? -ne 0 ]; then
51    echo "Failed to copy capsh for capability manipulation"
52    exit 1
53fi
54
55# Give it the forced capability it could need
56./setcap all=ep ./privileged
57if [ $? -ne 0 ]; then
58    echo "Failed to set all capabilities on file"
59    exit 1
60fi
61./setcap cap_setuid,cap_setgid=ep ./privileged
62if [ $? -ne 0 ]; then
63    echo "Failed to set limited capabilities on privileged file"
64    exit 1
65fi
66
67# Explore keep_caps support
68pass_capsh --keep=0 --keep=1 --keep=0 --keep=1 --print
69
70rm -f tcapsh
71cp capsh tcapsh
72chown root.root tcapsh
73chmod u+s tcapsh
74ls -l tcapsh
75
76# leverage keep caps maintain capabilities accross a change of uid
77# from setuid root to capable luser (as per wireshark/dumpcap 0.99.7)
78pass_capsh --uid=500 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --uid=500 --caps=\"cap_net_raw,cap_net_admin=pie\" --print"
79
80# This fails, on 2.6.24, but shouldn't
81pass_capsh --uid=500 -- -c "./tcapsh --keep=1 --caps=\"cap_net_raw,cap_net_admin=ip\" --uid=500 --forkfor=10 --caps= --print --killit=9 --print"
82
83# only continue with these if --secbits is supported
84./capsh --secbits=0x2f > /dev/null 2>&1
85if [ $? -ne 0 ]; then
86    echo "unable to test securebits manipulation - assume not supported (PASS)"
87    rm -f tcapsh
88    rm -f privileged
89    exit 0
90fi
91
92pass_capsh --secbits=42 --print
93fail_capsh --secbits=32 --keep=1 --keep=0 --print
94pass_capsh --secbits=10 --keep=0 --keep=1 --print
95fail_capsh --secbits=47 -- -c "./tcapsh --user=nobody"
96
97rm -f tcapsh
98
99# Suppress uid=0 privilege
100fail_capsh --secbits=47 --print -- -c "./capsh --user=nobody"
101
102# suppress uid=0 privilege and test this privileged
103pass_capsh --secbits=0x2f --print -- -c "./privileged --user=nobody"
104
105# observe that the bounding set can be used to suppress this forced capability
106fail_capsh --drop=cap_setuid --secbits=0x2f --print -- -c "./privileged --user=nobody"
107
108# change the way the capability is obtained (make it inheritable)
109./setcap cap_setuid,cap_setgid=ei ./privileged
110
111# Note, the bounding set (edited with --drop) only limits p
112# capabilities, not i's.
113pass_capsh --secbits=47 --inh=cap_setuid,cap_setgid --drop=cap_setuid \
114    --uid=500 --print -- -c "./privileged --user=nobody"
115
116rm -f ./privileged
117
118# test that we do not support capabilities on setuid shell-scripts
119cat > hack.sh <<EOF
120#!/bin/bash
121mypid=\$\$
122caps=\$(./getpcaps \$mypid 2>&1 | cut -d: -f2)
123if [ "\$caps" != " =" ]; then
124  echo "Shell script got [\$caps] - you should upgrade your kernel"
125  exit 1
126else
127  ls -l \$0
128  echo "Good, no capabilities [\$caps] for this setuid-0 shell script"
129fi
130exit 0
131EOF
132chmod +xs hack.sh
133./capsh --uid=500 --inh=none --print -- ./hack.sh
134status=$?
135rm -f ./hack.sh
136if [ $status -ne 0 ]; then
137    echo "shell scripts can have capabilities (bug)"
138    exit 1
139fi
140
141# Max lockdown
142pass_capsh --keep=1 --user=nobody --caps=cap_setpcap=ep \
143    --drop=all --secbits=0x2f --caps= --print
144
145# Verify we can chroot
146pass_capsh --chroot=$(/bin/pwd)
147pass_capsh --chroot=$(/bin/pwd) ==
148fail_capsh --chroot=$(/bin/pwd) -- -c "echo oops"
149