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