Create testcase for p9auth kernel module: The p9auth module is a driver in the staging/ directory, which implements kernel functionality supporting plan 9-style setuid. Programs can be completely unprivileged, authorize themselves to a privileged server, and obtain a token which they can use to authorize a single setuid to a single specified new uid. This testcase runs three tests:
1. make sure we can't setuid without a hash (this is actually short-cut in the kernel code so it might be worthwhile having a separate test for having a hash, but an invalid one),
2. make sure we can setuid when there is a valid hash,
3. make sure we cannot setuid if there is a valid hash, but our original uid isn't the one specified in the token.
Changelog:
Sep 21: Comment README, add runp9auth.sh to the patch, and add the openssl check to checkp9auth.sh. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>.
diff --git a/README b/README
index 63dbc72..cec6e36 100644
--- a/README
+++ b/README
@@ -179,6 +179,17 @@
 ---------------------------------
 CONFIG_SECURITY_FILE_CAPABILITIES=y
 ---------------------------------
+Enabling Kernel Configuration to test p9auth security feature
+---------------------------------
+CONFIG_CRYPTO=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_PLAN9AUTH=m
+(Or CONFIG_PLAN9AUTH=y)
+You also will need openssl installed.
+You will also need to have an user named 'ltp'
+created to execute this test.
+---------------------------------
 Enabling Kernel Configuration to test SELinux security feature
 ---------------------------------
 Your Kernel should have been built with the following options to
diff --git a/runtest/p9auth b/runtest/p9auth
new file mode 100644
index 0000000..17b1550
--- /dev/null
+++ b/runtest/p9auth
@@ -0,0 +1,2 @@
+#DESCRIPTION:p9auth /dev/caphash module
+p9auth		runp9auth.sh
diff --git a/testcases/kernel/security/Makefile b/testcases/kernel/security/Makefile
index 862691a..3a26b22 100644
--- a/testcases/kernel/security/Makefile
+++ b/testcases/kernel/security/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = mmc_security filecaps integrity cap_bound
+SUBDIRS = mmc_security filecaps integrity cap_bound p9auth
 
 all:
 	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i ; done
diff --git a/testcases/kernel/security/p9auth/Makefile b/testcases/kernel/security/p9auth/Makefile
new file mode 100644
index 0000000..1c03e5b
--- /dev/null
+++ b/testcases/kernel/security/p9auth/Makefile
@@ -0,0 +1,40 @@
+################################################################################
+##                                                                            ##
+## Copyright (c) International Business Machines  Corp., 2008                 ##
+##                                                                            ##
+## This program is free software;  you can redistribute it and#or modify      ##
+## it under the terms of the GNU General Public License as published by       ##
+## the Free Software Foundation; either version 2 of the License, or          ##
+## (at your option) any later version.                                        ##
+##                                                                            ##
+## This program is distributed in the hope that it will be useful, but        ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
+## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
+## for more details.                                                          ##
+##                                                                            ##
+## You should have received a copy of the GNU General Public License          ##
+## along with this program;  if not, write to the Free Software               ##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
+##                                                                            ##
+################################################################################
+
+HAVE_P9AUTH := $(shell sh checkp9auth.sh yesno)
+
+SCRIPTS = runp9auth.sh checkp9auth.sh p9priv.sh p9unpriv.sh
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp -lcap
+
+ifeq ($(HAVE_P9AUTH),yes)
+SRCS    = $(wildcard *.c)
+TARGETS+= $(patsubst %.c,%,$(SRCS))
+endif
+
+all: $(TARGETS)
+
+INSTALLTARGETS = $(TARGETS) $(SCRIPTS)
+install: $(INSTALLTARGETS)
+	@set -e; for i in $(INSTALLTARGETS); do ln -f $$i ../../../bin/$$i ; chmod +x ../../../bin/$$i; done
+
+clean:
+	rm -f $(TARGETS) *.o unhex
diff --git a/testcases/kernel/security/p9auth/checkp9auth.sh b/testcases/kernel/security/p9auth/checkp9auth.sh
new file mode 100755
index 0000000..4365427
--- /dev/null
+++ b/testcases/kernel/security/p9auth/checkp9auth.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+################################################################################
+##                                                                            ##
+## Copyright (c) International Business Machines  Corp., 2009                 ##
+##                                                                            ##
+## This program is free software;  you can redistribute it and#or modify      ##
+## it under the terms of the GNU General Public License as published by       ##
+## the Free Software Foundation; either version 2 of the License, or          ##
+## (at your option) any later version.                                        ##
+##                                                                            ##
+## This program is distributed in the hope that it will be useful, but        ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
+## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
+## for more details.                                                          ##
+##                                                                            ##
+## You should have received a copy of the GNU General Public License          ##
+## along with this program;  if not, write to the Free Software               ##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
+##                                                                            ##
+################################################################################
+
+yesno=0
+if [ "$1" = "yesno" ]; then
+	yesno=1
+fi
+
+# check for openssl
+OPENSSL=`which openssl`
+if [ $? -ne 0 ]; then
+	if [ $yesno -eq 1 ]; then echo
+		echo "no"
+	else
+		echo "Openssl not installed.  Skipping p9auth tests."
+	fi
+	exit 1
+fi
+# and make sure openssl understands -hmac
+echo -n "501@0" > plain
+$OPENSSL sha1 -hmac ab plain > hexed
+if [ $? -ne 0 ]; then
+	if [ $yesno -eq 1 ]; then echo
+		echo "no"
+	else
+		echo "Openssl too old (no -hmac).  Skipping p9auth tests."
+	fi
+	exit 1
+fi
+
+majfile=/sys/module/p9auth/parameters/cap_major
+minfile=/sys/module/p9auth/parameters/cap_minor
+if [ ! -f "$majfile" ]; then
+	if [ $yesno -eq 1 ]; then echo
+		echo "no"
+	else
+		echo "p9auth not detected.  Skipping p9auth tests."
+	fi
+	exit 1
+fi
+
+if [ ! -c "/dev/caphash" ]; then
+	rm -f /dev/caphash
+	maj=`cat $majfile`
+	mknod /dev/caphash c $maj 0
+fi
+
+if [ ! -c "/dev/capuse" ]; then
+	rm -f /dev/capuse
+	min=`cat $minfile`
+	mknod /dev/capuse c $maj 1
+fi
+chmod ugo+w /dev/capuse
+
+if [ $yesno -eq 1 ]; then
+	echo "yes"
+else
+	echo "p9auth ready for testing"
+fi
+exit 0
diff --git a/testcases/kernel/security/p9auth/p9priv.sh b/testcases/kernel/security/p9auth/p9priv.sh
new file mode 100755
index 0000000..ad2eead
--- /dev/null
+++ b/testcases/kernel/security/p9auth/p9priv.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+################################################################################
+##                                                                            ##
+## Copyright (c) International Business Machines  Corp., 2009                 ##
+##                                                                            ##
+## This program is free software;  you can redistribute it and#or modify      ##
+## it under the terms of the GNU General Public License as published by       ##
+## the Free Software Foundation; either version 2 of the License, or          ##
+## (at your option) any later version.                                        ##
+##                                                                            ##
+## This program is distributed in the hope that it will be useful, but        ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
+## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
+## for more details.                                                          ##
+##                                                                            ##
+## You should have received a copy of the GNU General Public License          ##
+## along with this program;  if not, write to the Free Software               ##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
+##                                                                            ##
+################################################################################
+
+LTPTMP=/tmp/p9auth_ltp
+rm -rf $LTPTMP
+mkdir $LTPTMP
+chmod 755 $LTPTMP
+
+comms="$LTPTMP/childgo $LTPTMP/d/childready $LTPTMP/d/childfail $LTPTMP/d/childpass $LTPTMP/childexit"
+
+RM=`which rm`
+MKDIR=`which mkdir`
+CHOWN=`which chown`
+
+cleanup() {
+	$RM -rf $LTPTMP/d $comms
+	$MKDIR -p $LTPTMP/d
+	$CHOWN -R ltp $LTPTMP/d
+}
+
+if [ `id -u` -ne 0 ]; then
+	echo "Must start p9auth tests as root"
+	exit 1
+fi
+
+ltpuid=`grep ltp /etc/passwd | head -1 | awk -F: '{ print $3 '}`
+ret=$?
+if [ $? -ne 0 ]; then
+	echo "Failed to find ltp userid"
+	exit 1
+fi
+
+# TEST 1: ltp setuids to 0 but no valid hash
+# launch an unprivileged helper
+cleanup
+
+su ltp p9unpriv.sh &
+while [ ! -f $LTPTMP/d/childready ]; do :; done
+touch $LTPTMP/childgo
+while [ ! -f $LTPTMP/d/childfail -a ! -f $LTPTMP/d/childpass ]; do :; done;
+if [ -f $LTPTMP/d/childpass ]; then
+	echo "FAIL: child could setuid with bad hash"
+	exit 1
+fi
+echo "PASS: child couldn't setuid with bad hash"
+
+# TEST 2: ltp setuids to 0 with valid hash
+
+# create the hash.  randstr doesn't have to be int, but it's ok
+cleanup
+randstr=$RANDOM
+txt="$ltpuid@0"
+echo -n "$txt" > $LTPTMP/txtfile
+openssl sha1 -hmac "$randstr" $LTPTMP/txtfile | awk '{ print $2 '} > $LTPTMP/hex
+unhex < $LTPTMP/hex > /dev/caphash
+# give the child its token
+echo -n "$txt@$randstr" > $LTPTMP/d/txtfile
+chown ltp $LTPTMP/d/txtfile
+
+su ltp p9unpriv.sh &
+while [ ! -f $LTPTMP/d/childready ]; do :; done
+touch $LTPTMP/childgo
+while [ ! -f $LTPTMP/d/childfail -a ! -f $LTPTMP/d/childpass ]; do :; done;
+if [ -f $LTPTMP/d/childfail ]; then
+	echo "FAIL: child couldn't setuid with good hash"
+	exit 1
+fi
+echo "PASS: child could setuid with good hash"
+
+# TEST 3: 0 setuids to 0 with hash valid for ltp user
+cleanup
+randstr=$RANDOM
+txt="0@0"
+echo -n "$txt" > $LTPTMP/txtfile
+openssl sha1 -hmac "$randstr" $LTPTMP/txtfile | awk '{ print $2 '} > $LTPTMP/hex
+unhex < $LTPTMP/hex > /dev/caphash
+# give the child its token
+echo -n "$txt@$randstr" > $LTPTMP/d/txtfile
+chown ltp $LTPTMP/d/txtfile
+
+su ltp p9unpriv.sh &
+while [ ! -f $LTPTMP/d/childready ]; do :; done
+touch $LTPTMP/childgo
+while [ ! -f $LTPTMP/d/childfail -a ! -f $LTPTMP/d/childpass ]; do :; done;
+if [ -f $LTPTMP/d/childpass ]; then
+	echo "PASS: child could setuid from wrong source uid"
+	exit 1
+fi
+echo "PASS: child couldn't setuid from wrong source uid"
+
+touch $LTPTMP/childexit
+
+exit 0
diff --git a/testcases/kernel/security/p9auth/p9unpriv.sh b/testcases/kernel/security/p9auth/p9unpriv.sh
new file mode 100755
index 0000000..077b8ac
--- /dev/null
+++ b/testcases/kernel/security/p9auth/p9unpriv.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+################################################################################
+##                                                                            ##
+## Copyright (c) International Business Machines  Corp., 2009                 ##
+##                                                                            ##
+## This program is free software;  you can redistribute it and#or modify      ##
+## it under the terms of the GNU General Public License as published by       ##
+## the Free Software Foundation; either version 2 of the License, or          ##
+## (at your option) any later version.                                        ##
+##                                                                            ##
+## This program is distributed in the hope that it will be useful, but        ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
+## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
+## for more details.                                                          ##
+##                                                                            ##
+## You should have received a copy of the GNU General Public License          ##
+## along with this program;  if not, write to the Free Software               ##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
+##                                                                            ##
+################################################################################
+
+LTPTMP=/tmp/p9auth_ltp
+
+TOUCH=`which touch`
+ID=`which id`
+echo ltptmp is $LTPTMP
+
+myuid=`id -u`
+if [ "$myuid" -eq 0 ]; then
+	echo "Unprivileged child was started as root!"
+	exit 1
+fi
+
+$TOUCH $LTPTMP/d/childready
+
+while [ 1 ]; do
+	if [ -f $LTPTMP/childexit ]; then
+		exit 0
+	fi
+	if [ -f $LTPTMP/childgo ]; then
+		echo -n `cat $LTPTMP/d/txtfile` > /dev/capuse
+		if [ `$ID -u` -eq 0 ]; then
+			$TOUCH $LTPTMP/d/childpass
+		else
+			$TOUCH $LTPTMP/d/childfail
+		fi
+		exit 0
+	fi
+done
+
+exit 0
diff --git a/testcases/kernel/security/p9auth/runp9auth.sh b/testcases/kernel/security/p9auth/runp9auth.sh
new file mode 100755
index 0000000..b61844e
--- /dev/null
+++ b/testcases/kernel/security/p9auth/runp9auth.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+################################################################################
+##                                                                            ##
+## Copyright (c) International Business Machines  Corp., 2008                 ##
+##                                                                            ##
+## This program is free software;  you can redistribute it and#or modify      ##
+## it under the terms of the GNU General Public License as published by       ##
+## the Free Software Foundation; either version 2 of the License, or          ##
+## (at your option) any later version.                                        ##
+##                                                                            ##
+## This program is distributed in the hope that it will be useful, but        ##
+## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
+## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
+## for more details.                                                          ##
+##                                                                            ##
+## You should have received a copy of the GNU General Public License          ##
+## along with this program;  if not, write to the Free Software               ##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
+##                                                                            ##
+################################################################################
+
+checkp9auth.sh
+ret=$?
+if [ $ret -ne 0 ]; then
+	echo "p9auth module is not supported by this kernel."
+	exit 0
+fi
+
+exit_code=0
+
+p9priv.sh
+tmp=$?
+if [ $tmp -ne 0 ]; then
+	exit_code=$tmp
+fi
+
+exit $exit_code
diff --git a/testcases/kernel/security/p9auth/unhex.c b/testcases/kernel/security/p9auth/unhex.c
new file mode 100644
index 0000000..7c78b6a
--- /dev/null
+++ b/testcases/kernel/security/p9auth/unhex.c
@@ -0,0 +1,47 @@
+/******************************************************************************/
+/*                                                                            */
+/* Copyright (c) International Business Machines  Corp., 2008                 */
+/*                                                                            */
+/* This program is free software;  you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation; either version 2 of the License, or          */
+/* (at your option) any later version.                                        */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
+/* the GNU General Public License for more details.                           */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program;  if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    */
+/*                                                                            */
+/******************************************************************************/
+
+/*
+ * File: unhex.c
+ * Author: Serge Hallyn
+ * Purpose: Read a 40 char hex value from stdin, output 20 char byte
+ * value on stdout.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+	char in[41], out[20];
+	unsigned int v;
+	int i, ret;
+
+	ret = read(STDIN_FILENO, in, 40);
+	if (ret != 40)
+		return 1;
+	in[40] = '\0';
+	for (i = 0; i < 20; i++) {
+		sscanf(&in[2*i], "%02x", &v);
+		out[i] = v;
+	}
+	write(STDOUT_FILENO, out, 20);
+	return 0;
+}