Home | History | Annotate | Download | only in securebits
      1 #include <errno.h>
      2 #include "config.h"
      3 #if HAVE_SYS_CAPABILITY_H
      4 #include <linux/types.h>
      5 #include <sys/capability.h>
      6 #endif
      7 #include <sys/prctl.h>
      8 #include "test.h"
      9 
     10 #ifndef SECBIT_KEEP_CAPS
     11 #define SECBIT_KEEP_CAPS (1<<4)
     12 #endif
     13 
     14 /* Tests:
     15 	1. drop capabilities at setuid if KEEPCAPS is not set and
     16 	   new user is nonroot
     17 	2. keep capabilities if set and new user is nonroot
     18 	   a. do with prctl(PR_SET_KEEPCAPS)
     19 	   (call this test 2)
     20 	   b. do with prctl(PR_SET_SECUREBITS, SECURE_KEEP_CAPS)
     21 	   (call this test 3)
     22    TODO: test that exec clears KEEPCAPS
     23    	(just create a simple executable that checks PR_GET_KEEPCAPS
     24 	 results, and execute that as test 4 after doing PR_SET_KEEPCAPS).
     25    TODO: all of the other securebits tests.
     26  */
     27 
     28 char *TCID = "keepcaps";
     29 int TST_TOTAL = 1;
     30 
     31 #if (HAVE_LINUX_SECUREBITS_H && HAVE_LIBCAP)
     32 #include <linux/securebits.h>
     33 
     34 static int eff_caps_empty(cap_t c)
     35 {
     36 	int i, ret, empty = 1;
     37 	cap_flag_value_t v;
     38 
     39 	for (i = 0; i < CAP_LAST_CAP; i++) {
     40 		ret = cap_get_flag(c, i, CAP_PERMITTED, &v);
     41 		/*
     42 		 * If the value of CAP_LAST_CAP in linux/capability.h is greater
     43 		 * than the value in the capability.h which is used to create
     44 		 * libcap.so. Then cap_get_flag returns -1, and errno is set to
     45 		 * EINVAL.
     46 		 */
     47 		if (ret == -1) {
     48 			tst_brkm(TBROK | TERRNO, NULL,
     49 				"Not expected. Please check arguments.");
     50 		}
     51 		if (ret || v)
     52 			empty = 0;
     53 	}
     54 
     55 	return empty;
     56 }
     57 
     58 static int am_privileged(void)
     59 {
     60 	int am_privileged = 1;
     61 
     62 	cap_t cap = cap_get_proc();
     63 	if (eff_caps_empty(cap))
     64 		am_privileged = 0;
     65 	cap_free(cap);
     66 
     67 	return am_privileged;
     68 }
     69 
     70 #define EXPECT_NOPRIVS 0
     71 #define EXPECT_PRIVS 1
     72 static void do_setuid(int expect_privs)
     73 {
     74 	int ret;
     75 	int have_privs;
     76 
     77 	ret = setuid(1000);
     78 	if (ret)
     79 		tst_brkm(TERRNO | TFAIL, NULL, "setuid failed");
     80 
     81 	have_privs = am_privileged();
     82 	if (have_privs && expect_privs == EXPECT_PRIVS) {
     83 		tst_resm(TPASS, "kept privs as expected");
     84 		tst_exit();
     85 	}
     86 	if (!have_privs && expect_privs == EXPECT_PRIVS) {
     87 		tst_brkm(TFAIL, NULL, "expected to keep privs but did not");
     88 	}
     89 	if (!have_privs && expect_privs == EXPECT_NOPRIVS) {
     90 		tst_resm(TPASS, "dropped privs as expected");
     91 		tst_exit();
     92 	}
     93 
     94 	/* have_privs && EXPECT_NOPRIVS */
     95 	tst_brkm(TFAIL, NULL, "expected to drop privs but did not");
     96 }
     97 
     98 int main(int argc, char *argv[])
     99 {
    100 	int ret, whichtest;
    101 
    102 	tst_require_root();
    103 
    104 	ret = prctl(PR_GET_KEEPCAPS);
    105 	if (ret)
    106 		tst_brkm(TBROK, NULL, "keepcaps was already set?");
    107 
    108 	if (argc < 2)
    109 		tst_brkm(TBROK, NULL, "Usage: %s <tescase_num>", argv[0]);
    110 
    111 	whichtest = atoi(argv[1]);
    112 	if (whichtest < 1 || whichtest > 3)
    113 		tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
    114 
    115 	switch (whichtest) {
    116 	case 1:
    117 		do_setuid(EXPECT_NOPRIVS);	/* does not return */
    118 	case 2:
    119 		ret = prctl(PR_SET_KEEPCAPS, 1);
    120 		if (ret == -1) {
    121 			tst_brkm(TFAIL | TERRNO, NULL,
    122 				 "PR_SET_KEEPCAPS failed");
    123 		}
    124 		ret = prctl(PR_GET_KEEPCAPS);
    125 		if (!ret) {
    126 			tst_brkm(TFAIL | TERRNO, NULL,
    127 				 "PR_SET_KEEPCAPS did not set keepcaps");
    128 		}
    129 		do_setuid(EXPECT_PRIVS);	/* does not return */
    130 	case 3:
    131 		ret = prctl(PR_GET_SECUREBITS);
    132 		ret = prctl(PR_SET_SECUREBITS, ret | SECBIT_KEEP_CAPS);
    133 		if (ret == -1) {
    134 			tst_brkm(TFAIL | TERRNO, NULL,
    135 				 "PR_SET_SECUREBITS failed");
    136 		}
    137 		ret = prctl(PR_GET_KEEPCAPS);
    138 		if (!ret) {
    139 			tst_brkm(TFAIL | TERRNO, NULL,
    140 				 "PR_SET_SECUREBITS did not set keepcaps");
    141 		}
    142 		do_setuid(EXPECT_PRIVS);	/* does not return */
    143 	default:
    144 		tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
    145 	}
    146 }
    147 
    148 #else
    149 
    150 int main(void)
    151 {
    152 	tst_brkm(TCONF, NULL, "linux/securebits.h or libcap does not exist.");
    153 }
    154 
    155 #endif /* HAVE_LIBCAP */
    156