Hi !

I propose this new test for the setfsuid syscall.

The goal if this test is to check the fsuid is correctly handled by the
setfsuid syscall. To do so, the test creates a testfile as root with
permission 0644, then do a setuid and try to open the file RDWR. This
last open must fail since the process with new UID is not allowed to
open the file on write.

In a second step, the test does a fork to check the fsuid is correctly
passed to a son and the son behaves correctly regarding files, i.e.
it cannot open on write the test file.

Finally, the test falls back to the initial UID and try to open the file on
write. This open must succed.

Regards.

R.

-- 
Renaud Lottiaux

Kerlabs
Bâtiment Germanium
80, avenue des buttes de Coësmes
35700 Rennes - France
Phone : (+33|0)6 80 89 19 34
Fax   : (+33|0)2 99 84 71 71
Email : [EMAIL PROTECTED]
Web   : http://www.kerlabs.com/
Index: cvs/testcases/kernel/syscalls/setfsuid/setfsuid04.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ cvs/testcases/kernel/syscalls/setfsuid/setfsuid04.c	2008-08-14 16:20:02.000000000 +0200
@@ -0,0 +1,238 @@
+/*
+ *   Copyright (c) Kerlabs 2008.
+ */
+
+/*
+ * NAME
+ * 	setfsuid04.c
+ *
+ * DESCRIPTION
+ * 	Check if setfsuid behaves correctly with file permissions.
+ *      The test creates a file as ROOT with permissions 0644, does a setfsuid
+ *      and then tries to open the file with RDWR permissions.
+ *      The same test is done in a fork to check if new UIDs are correctly
+ *      passed to the son.
+ *
+ * USAGE:  <for command-line>
+ *  setfsuid04 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
+ *     where,  -c n : Run n copies concurrently.
+ *             -e   : Turn on errno logging.
+ *             -i n : Execute test n times.
+ *             -I x : Execute test for x seconds.
+ *             -P x : Pause for x seconds between iterations.
+ *             -t   : Turn on syscall timing.
+ *
+ * HISTORY
+ *	07/2001 Created by Renaud Lottiaux
+ *
+ * RESTRICTIONS
+ * 	Must be run as root.
+ */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef __GLIBC__
+#include <sys/fsuid.h>
+#endif
+#include "test.h"
+#include "usctest.h"
+#include <pwd.h>
+
+char *TCID = "setfsuid04";
+int TST_TOTAL = 1;
+extern int Tst_count;
+char nobody_uid[] = "nobody";
+char testfile[256] = "";
+struct passwd *ltpuser;
+
+int exp_enos[] = {EACCES, 0};
+int fd = -1;
+
+void setup(void);
+void cleanup(void);
+void do_master_child();
+
+int main(int ac, char **av)
+{
+	pid_t pid;
+	char *msg;			/* message returned from parse_opts */
+	int status;
+
+	/* parse standard options */
+	if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){
+		tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
+		/*NOTREACHED*/
+	}
+
+	/*
+	 * perform global setup for the test
+	 */
+	setup();
+
+	TEST_EXP_ENOS(exp_enos);
+
+	pid = FORK_OR_VFORK();
+	if (pid < 0)
+		tst_brkm(TBROK, cleanup, "Fork failed");
+	
+	if (pid == 0) {
+		do_master_child();
+	}
+	else {
+		waitpid(pid, &status, 0);
+		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+			tst_resm(WEXITSTATUS(status), "son process exits with error");
+	}
+
+	cleanup();
+	/*NOTREACHED*/
+
+	return(0);
+}
+
+/*
+ * do_master_child()
+ */
+void do_master_child()
+{
+	int lc;				/* loop counter */
+	int pid;
+	int status;
+
+	/* Check looping state if -i option is given */
+	for (lc = 0; TEST_LOOPING(lc); lc++) {
+		int tst_fd;
+
+		/* Reset Tst_count in case we are looping */
+		Tst_count = 0;
+
+		if (setfsuid(ltpuser->pw_uid) == -1) {
+			tst_brkm(TBROK, cleanup, 
+				 "setfsuid failed to set the euid to %d",
+				 ltpuser->pw_uid);
+		}
+
+		/* Test 1: Check the process with new uid cannot open the file
+		 *         with RDWR permissions.
+		 */
+		TEST(tst_fd = open(testfile, O_RDWR));
+
+		if (TEST_RETURN != -1) {
+			tst_resm(TFAIL, "call succeeded unexpectedly");
+			close(tst_fd);
+		}
+
+		if (TEST_ERRNO == EACCES) {
+			tst_resm(TPASS, "open returned errno EACCES");
+		} else {
+			tst_resm(TFAIL, "open returned unexpected errno - %d",
+				 TEST_ERRNO);
+			continue;
+		}
+
+		/* Test 2: Check a son process cannot open the file
+		 *         with RDWR permissions.
+		 */
+		pid = FORK_OR_VFORK();
+		if (pid < 0)
+			tst_brkm(TBROK, cleanup, "Fork failed");
+
+		if (pid == 0) {
+			int tst_fd2; 
+
+			/* Test to open the file in son process */
+			TEST(tst_fd2 = open(testfile, O_RDWR));
+
+			if (TEST_RETURN != -1) {
+				tst_resm(TFAIL, "call succeeded unexpectedly");
+				close(tst_fd2);
+			}
+
+			TEST_ERROR_LOG(TEST_ERRNO);
+			
+			if (TEST_ERRNO == EACCES) {
+				tst_resm(TPASS, "open returned errno EACCES");
+			} else {
+				tst_resm(TFAIL, "open returned unexpected errno - %d",
+					 TEST_ERRNO);
+			}
+			continue;
+		}
+		else {
+			/* Wait for son completion */
+			waitpid(pid, &status, 0);
+			if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+				exit(WEXITSTATUS(status));
+		}
+
+		/* Test 3: Fallback to initial uid and check we can again open
+		 *         the file with RDWR permissions.
+		 */
+		Tst_count++;
+		if (setfsuid(0) == -1) {
+			tst_brkm(TBROK, cleanup, 
+				 "setfsuid failed to set the euid to 0");
+		}
+
+		TEST(tst_fd = open(testfile, O_RDWR));
+
+		if (TEST_RETURN == -1) {
+			tst_resm(TFAIL, "open returned unexpected errno %d",
+				 TEST_ERRNO);
+			continue;
+		}
+		else {
+			tst_resm(TPASS, "open call succeeded");
+			close (tst_fd);
+		}
+	}
+}
+
+/*
+ * setup() - performs all ONE TIME setup for this test
+ */
+void
+setup(void)
+{
+        if (geteuid() != 0) {
+                tst_brkm(TBROK, tst_exit, "Test must be run as root");
+        }
+
+	ltpuser = getpwnam(nobody_uid);	
+
+	sprintf(testfile, "setfsuid04file%d.tst", getpid());
+
+	/* Create test file */
+	fd = open(testfile, O_CREAT | O_RDWR, 0644);
+	if (fd < 0)
+		tst_brkm(TBROK, cleanup, "cannot creat test file");
+
+	/* capture signals */
+	tst_sig(FORK, DEF_HANDLER, cleanup);
+
+	/* Pause if that option was specified */
+	TEST_PAUSE;
+}
+
+/*
+ * cleanup() - performs all the ONE TIME cleanup for this test at completion
+ * 	       or premature exit
+ */
+void
+cleanup(void)
+{
+	close (fd);
+	unlink(testfile);
+
+	/*
+	 * print timing status if that option was specified
+	 * print errno log if that option was specified
+	 */
+	TEST_CLEANUP;
+
+	/* exit with return code appropriate for results */
+	tst_exit();
+}

Attachment: signature.asc
Description: This is a digitally signed message part.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to