Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/mac/bsdextended/matches_test.sh
#!/bin/sh | #!/bin/sh | ||||
# | # | ||||
# $FreeBSD$ | # $FreeBSD$ | ||||
# | # | ||||
uidrange="60000:100000" | uidrange="60000:100000" | ||||
gidrange="60000:100000" | gidrange="60000:100000" | ||||
uidinrange="nobody" | uidinrange="nobody" | ||||
uidoutrange="daemon" | uidoutrange="daemon" | ||||
gidinrange="nobody" # We expect $uidinrange in this group | gidinrange="nobody" # We expect $uidinrange in this group | ||||
gidoutrange="daemon" # We expect $uidinrange in this group | gidoutrange="daemon" # We expect $uidinrange in this group | ||||
test_num=1 | |||||
pass() | |||||
{ | |||||
echo "ok $test_num # $@" | |||||
: $(( test_num += 1 )) | |||||
} | |||||
fail() | check_ko() | ||||
ngie: Where is this called in the new code? | |||||
{ | { | ||||
echo "not ok $test_num # $@" | |||||
: $(( test_num += 1 )) | |||||
} | |||||
# | |||||
# Setup | |||||
# | |||||
: ${TMPDIR=/tmp} | |||||
if [ $(id -u) -ne 0 ]; then | |||||
echo "1..0 # SKIP test must be run as root" | |||||
exit 0 | |||||
fi | |||||
if ! sysctl -N security.mac.bsdextended >/dev/null 2>&1; then | if ! sysctl -N security.mac.bsdextended >/dev/null 2>&1; then | ||||
echo "1..0 # SKIP mac_bsdextended(4) support isn't available" | atf_skip "mac_bsdextended(4) support isn't available" | ||||
exit 0 | |||||
fi | fi | ||||
if [ "$TMPDIR" != "/tmp" ]; then | } | ||||
if ! chmod -Rf 0755 $TMPDIR; then | |||||
echo "1..0 # SKIP failed to chmod $TMPDIR" | setup() | ||||
exit 0 | { | ||||
fi | playground=$(mktemp -d $TMPDIR/tmp.XXXXXXX) \ | ||||
fi | || atf_fail "failed to create temporary directory" | ||||
if ! playground=$(mktemp -d $TMPDIR/tmp.XXXXXXX); then | echo $playground > playground | ||||
echo "1..0 # SKIP failed to create temporary directory" | mdmfs -s 25m md $playground \ | ||||
exit 0 | || atf_fail "failed to mount md device" | ||||
fi | |||||
trap "rmdir $playground" EXIT INT TERM | |||||
if ! mdmfs -s 25m md $playground; then | |||||
echo "1..0 # SKIP failed to mount md device" | |||||
exit 0 | |||||
fi | |||||
chmod a+rwx $playground | chmod a+rwx $playground | ||||
md_device=$(mount -p | grep "$playground" | awk '{ gsub(/^\/dev\//, "", $1); print $1 }') | md_device=$(mount -p | grep "$playground" | awk '{ gsub(/^\/dev\//, "", $1); print $1 }') | ||||
trap "umount -f $playground; mdconfig -d -u $md_device; rmdir $playground" EXIT INT TERM | |||||
if [ -z "$md_device" ]; then | if [ -z "$md_device" ]; then | ||||
mount -p | grep $playground | atf_fail "md device not properly attached to the system" | ||||
echo "1..0 # SKIP md device not properly attached to the system" | |||||
fi | fi | ||||
echo $md_device > md_device | |||||
ugidfw remove 1 | ugidfw remove 1 | ||||
file1=$playground/test-$uidinrange | |||||
file2=$playground/test-$uidoutrange | |||||
cat > $playground/test-script.sh <<'EOF' | cat > $playground/test-script.sh <<'EOF' | ||||
#!/bin/sh | #!/bin/sh | ||||
: > $1 | : > $1 | ||||
EOF | EOF | ||||
if [ $? -ne 0 ]; then | if [ $? -ne 0 ]; then | ||||
echo "1..0 # SKIP failed to create test script" | atf_fail "failed to create test script" | ||||
exit 0 | |||||
fi | fi | ||||
echo "1..30" | |||||
file1=$playground/test-$uidinrange | |||||
file2=$playground/test-$uidoutrange | |||||
command1="sh $playground/test-script.sh $file1" | command1="sh $playground/test-script.sh $file1" | ||||
command2="sh $playground/test-script.sh $file2" | command2="sh $playground/test-script.sh $file2" | ||||
desc="$uidinrange file" | desc="$uidinrange file" | ||||
if su -m $uidinrange -c "$command1"; then | if ! su -m $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
chown "$uidinrange":"$gidinrange" $file1 | chown "$uidinrange":"$gidinrange" $file1 | ||||
chmod a+w $file1 | chmod a+w $file1 | ||||
desc="$uidoutrange file" | desc="$uidoutrange file" | ||||
if $command2; then | if ! $command2; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
chown "$uidoutrange":"$gidoutrange" $file2 | chown "$uidoutrange":"$gidoutrange" $file2 | ||||
chmod a+w $file2 | chmod a+w $file2 | ||||
} | |||||
# | cleanup() | ||||
# No rules | { | ||||
# | if [ -n playground ]; then | ||||
umount -f $( cat playground ) | |||||
ngieUnsubmitted Done Inline ActionsWhy isn't this filename parameterized at the global level? ngie: Why isn't this filename parameterized at the global level? | |||||
asomersAuthorUnsubmitted Done Inline ActionsBecause it's the result of mktemp. Though, now that we're using ATF, it doesn't have to be. I'll change it. asomers: Because it's the result of `mktemp`. Though, now that we're using ATF, it doesn't have to be. | |||||
fi | |||||
if [ -f md_device ]; then | |||||
mdconfig -d -u $( cat md_device ) | |||||
fi | |||||
} | |||||
atf_test_case no_rules cleanup | |||||
no_rules_head() | |||||
{ | |||||
atf_set "require.user" "root" | |||||
} | |||||
no_rules_body() | |||||
{ | |||||
setup | |||||
desc="no rules $uidinrange" | desc="no rules $uidinrange" | ||||
if su -fm $uidinrange -c "$command1"; then | if ! su -fm $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
desc="no rules $uidoutrange" | desc="no rules $uidoutrange" | ||||
if su -fm $uidoutrange -c "$command1"; then | if ! su -fm $uidoutrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
} | |||||
no_rules_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
# | atf_test_case subject_match_on_uid cleanup | ||||
# Subject Match on uid | subject_match_on_uid_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
subject_match_on_uid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object mode rasx | ugidfw set 1 subject uid $uidrange object mode rasx | ||||
desc="subject uid in range" | desc="subject uid in range" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="subject uid out range" | desc="subject uid out range" | ||||
if su -fm $uidoutrange -c "$command1"; then | if ! su -fm $uidoutrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
# | } | ||||
# Subject Match on gid | subject_match_on_uid_cleanup() | ||||
# | { | ||||
cleanup | |||||
} | |||||
atf_test_case subject_match_on_gid cleanup | |||||
subject_match_on_gid_head() | |||||
{ | |||||
atf_set "require.user" "root" | |||||
} | |||||
subject_match_on_gid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject gid $gidrange object mode rasx | ugidfw set 1 subject gid $gidrange object mode rasx | ||||
desc="subject gid in range" | desc="subject gid in range" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="subject gid out range" | desc="subject gid out range" | ||||
if su -fm $uidoutrange -c "$command1"; then | if ! su -fm $uidoutrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
} | |||||
subject_match_on_gid_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
if which jail >/dev/null; then | atf_test_case subject_match_on_jail cleanup | ||||
# | subject_match_on_jail_head() | ||||
# Subject Match on jail | { | ||||
# | atf_set "require.progs" "jail" | ||||
rm -f $playground/test-jail | atf_set "require.user" "root" | ||||
} | |||||
subject_match_on_jail_body() | |||||
{ | |||||
setup | |||||
atf_expect_fail "this testcase fails (see bug # 205481)" | |||||
desc="subject matching jailid" | desc="subject matching jailid" | ||||
jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"` | jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"` | ||||
ugidfw set 1 subject jailid $jailid object mode rasx | ugidfw set 1 subject jailid $jailid object mode rasx | ||||
sleep 10 | sleep 10 | ||||
if [ -f $playground/test-jail ]; then | if [ -f $playground/test-jail ]; then | ||||
fail "TODO $desc: this testcase fails (see bug # 205481)" | atf_fail "$desc" | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
rm -f $playground/test-jail | rm -f $playground/test-jail | ||||
desc="subject nonmatching jailid" | desc="subject nonmatching jailid" | ||||
jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"` | jailid=`jail -i / localhost 127.0.0.1 /usr/sbin/daemon -f /bin/sh -c "(sleep 5; touch $playground/test-jail) &"` | ||||
sleep 10 | sleep 10 | ||||
if [ -f $playground/test-jail ]; then | if ! [ -f $playground/test-jail ]; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
else | } | ||||
# XXX: kyua is too dumb to parse skip ranges, still.. | subject_match_on_jail_cleanup() | ||||
pass "skip jail(8) not installed" | { | ||||
pass "skip jail(8) not installed" | cleanup | ||||
fi | } | ||||
# | atf_test_case object_uid cleanup | ||||
# Object uid | object_uid_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
object_uid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject object uid $uidrange mode rasx | ugidfw set 1 subject object uid $uidrange mode rasx | ||||
desc="object uid in range" | desc="object uid in range" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="object uid out range" | desc="object uid out range" | ||||
if su -fm $uidinrange -c "$command2"; then | if ! su -fm $uidinrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
ugidfw set 1 subject object uid $uidrange mode rasx | ugidfw set 1 subject object uid $uidrange mode rasx | ||||
desc="object uid in range (different subject)" | desc="object uid in range (different subject)" | ||||
if su -fm $uidoutrange -c "$command1"; then | if su -fm $uidoutrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="object uid out range (different subject)" | desc="object uid out range (different subject)" | ||||
if su -fm $uidoutrange -c "$command2"; then | if ! su -fm $uidoutrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
# | } | ||||
# Object gid | object_uid_cleanup() | ||||
# | { | ||||
cleanup | |||||
} | |||||
atf_test_case object_gid cleanup | |||||
object_gid_head() | |||||
{ | |||||
atf_set "require.user" "root" | |||||
} | |||||
object_gid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject object gid $uidrange mode rasx | ugidfw set 1 subject object gid $uidrange mode rasx | ||||
desc="object gid in range" | desc="object gid in range" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="object gid out range" | desc="object gid out range" | ||||
if su -fm $uidinrange -c "$command2"; then | if ! su -fm $uidinrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
desc="object gid in range (different subject)" | desc="object gid in range (different subject)" | ||||
if su -fm $uidoutrange -c "$command1"; then | if su -fm $uidoutrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
desc="object gid out range (different subject)" | desc="object gid out range (different subject)" | ||||
if su -fm $uidoutrange -c "$command2"; then | if ! su -fm $uidoutrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
} | |||||
object_gid_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
# | atf_test_case object_filesys cleanup | ||||
# Object filesys | object_filesys_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
object_filesys_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object filesys / mode rasx | ugidfw set 1 subject uid $uidrange object filesys / mode rasx | ||||
desc="object out of filesys" | desc="object out of filesys" | ||||
if su -fm $uidinrange -c "$command1"; then | if ! su -fm $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
ugidfw set 1 subject uid $uidrange object filesys $playground mode rasx | ugidfw set 1 subject uid $uidrange object filesys $playground mode rasx | ||||
desc="object in filesys" | desc="object in filesys" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
} | |||||
subject_match_on__cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
# | atf_test_case object_suid cleanup | ||||
# Object suid | object_suid_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
object_suid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object suid mode rasx | ugidfw set 1 subject uid $uidrange object suid mode rasx | ||||
desc="object notsuid" | desc="object notsuid" | ||||
if su -fm $uidinrange -c "$command1"; then | if ! su -fm $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
chmod u+s $file1 | chmod u+s $file1 | ||||
desc="object suid" | desc="object suid" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
chmod u-s $file1 | chmod u-s $file1 | ||||
# | } | ||||
# Object sgid | object_suid_cleanup() | ||||
# | { | ||||
cleanup | |||||
} | |||||
atf_test_case object_sgid cleanup | |||||
object_sgid_head() | |||||
{ | |||||
atf_set "require.user" "root" | |||||
ngieUnsubmitted Not Done Inline ActionsWhy not set this property in the Makefile? ngie: Why not set this property in the Makefile? | |||||
asomersAuthorUnsubmitted Done Inline ActionsI generally prefer to set those things in the test file because it's more granular. It's done per testcase here, whereas it must be per test program if done in the Makefile. Do you think I should change it? asomers: I generally prefer to set those things in the test file because it's more granular. It's done… | |||||
} | |||||
object_sgid_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object sgid mode rasx | ugidfw set 1 subject uid $uidrange object sgid mode rasx | ||||
desc="object notsgid" | desc="object notsgid" | ||||
if su -fm $uidinrange -c "$command1"; then | if ! su -fm $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
chmod g+s $file1 | chmod g+s $file1 | ||||
desc="object sgid" | desc="object sgid" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
chmod g-s $file1 | chmod g-s $file1 | ||||
} | |||||
object_sgid_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
# | atf_test_case object_uid_matches_subject cleanup | ||||
# Object uid matches subject | object_uid_matches_subject_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
object_uid_matches_subject_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object uid_of_subject mode rasx | ugidfw set 1 subject uid $uidrange object uid_of_subject mode rasx | ||||
desc="object uid notmatches subject" | desc="object uid notmatches subject" | ||||
if su -fm $uidinrange -c "$command2"; then | if ! su -fm $uidinrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
desc="object uid matches subject" | desc="object uid matches subject" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
} | |||||
object_uid_matches_subject_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
# | atf_test_case object_gid_matches_subject cleanup | ||||
# Object gid matches subject | object_gid_matches_subject_head() | ||||
# | { | ||||
atf_set "require.user" "root" | |||||
} | |||||
object_gid_matches_subject_body() | |||||
{ | |||||
setup | |||||
ugidfw set 1 subject uid $uidrange object gid_of_subject mode rasx | ugidfw set 1 subject uid $uidrange object gid_of_subject mode rasx | ||||
ngieUnsubmitted Not Done Inline ActionsWouldn't it be a good idea here (and elsewhere) to check the return code from ugidfw, etc? ngie: Wouldn't it be a good idea here (and elsewhere) to check the return code from ugidfw, etc? | |||||
asomersAuthorUnsubmitted Done Inline ActionsYeah, probably. asomers: Yeah, probably. | |||||
desc="object gid notmatches subject" | desc="object gid notmatches subject" | ||||
if su -fm $uidinrange -c "$command2"; then | if ! su -fm $uidinrange -c "$command2"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
desc="object gid matches subject" | desc="object gid matches subject" | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
# | } | ||||
# Object type | object_gid_matches_subject_cleanup() | ||||
# | { | ||||
cleanup | |||||
} | |||||
atf_test_case object_type cleanup | |||||
object_type_head() | |||||
{ | |||||
atf_set "require.user" "root" | |||||
} | |||||
object_type_body() | |||||
{ | |||||
setup | |||||
desc="object not type" | desc="object not type" | ||||
ugidfw set 1 subject uid $uidrange object type dbclsp mode rasx | ugidfw set 1 subject uid $uidrange object type dbclsp mode rasx | ||||
if su -fm $uidinrange -c "$command1"; then | if ! su -fm $uidinrange -c "$command1"; then | ||||
pass $desc | atf_fail $desc | ||||
else | |||||
fail $desc | |||||
fi | fi | ||||
desc="object type" | desc="object type" | ||||
ugidfw set 1 subject uid $uidrange object type r mode rasx | ugidfw set 1 subject uid $uidrange object type r mode rasx | ||||
if su -fm $uidinrange -c "$command1"; then | if su -fm $uidinrange -c "$command1"; then | ||||
ngieUnsubmitted Not Done Inline ActionsWhy not use atf_check with an inverted exit code check? ngie: Why not use `atf_check` with an inverted exit code check? | |||||
asomersAuthorUnsubmitted Done Inline ActionsSure. It will remove the failure descriptions, but those aren't very useful anyway. asomers: Sure. It will remove the failure descriptions, but those aren't very useful anyway. | |||||
fail $desc | atf_fail $desc | ||||
else | |||||
pass $desc | |||||
fi | fi | ||||
} | |||||
object_type_cleanup() | |||||
{ | |||||
cleanup | |||||
} | |||||
atf_init_test_cases() | |||||
{ | |||||
atf_add_test_case no_rules | |||||
atf_add_test_case subject_match_on_uid | |||||
atf_add_test_case subject_match_on_gid | |||||
atf_add_test_case subject_match_on_jail | |||||
atf_add_test_case object_uid | |||||
atf_add_test_case object_gid | |||||
atf_add_test_case object_filesys | |||||
atf_add_test_case object_suid | |||||
atf_add_test_case object_sgid | |||||
atf_add_test_case object_uid_matches_subject | |||||
atf_add_test_case object_gid_matches_subject | |||||
atf_add_test_case object_type | |||||
} |
Where is this called in the new code?