Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 1 | #include <errno.h> |
| 2 | #include "config.h" |
| 3 | #if HAVE_SYS_CAPABILITY_H |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 4 | #include <linux/types.h> |
| 5 | #include <sys/capability.h> |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 6 | #endif |
| 7 | #include <sys/prctl.h> |
Garrett Cooper | e8530df | 2010-12-21 11:37:57 -0800 | [diff] [blame] | 8 | #include "test.h" |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 9 | |
Cyril Hrubis | 4590c29 | 2011-02-07 18:30:37 +0100 | [diff] [blame] | 10 | #ifndef SECBIT_KEEP_CAPS |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 11 | #define SECBIT_KEEP_CAPS (1<<4) |
Cyril Hrubis | 4590c29 | 2011-02-07 18:30:37 +0100 | [diff] [blame] | 12 | #endif |
| 13 | |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 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"; |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 29 | int TST_TOTAL = 1; |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 30 | |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 31 | #if (HAVE_LINUX_SECUREBITS_H && HAVE_LIBCAP) |
| 32 | #include <linux/securebits.h> |
| 33 | |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 34 | static int eff_caps_empty(cap_t c) |
| 35 | { |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 36 | int i, ret, empty = 1; |
Cyril Hrubis | 4590c29 | 2011-02-07 18:30:37 +0100 | [diff] [blame] | 37 | cap_flag_value_t v; |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 38 | |
| 39 | for (i = 0; i < CAP_LAST_CAP; i++) { |
| 40 | ret = cap_get_flag(c, i, CAP_PERMITTED, &v); |
Zeng Linggang | 09db137 | 2014-08-06 15:17:32 +0800 | [diff] [blame] | 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 | } |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 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 | } |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 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); |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 78 | if (ret) |
| 79 | tst_brkm(TERRNO | TFAIL, NULL, "setuid failed"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 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) { |
Cyril Hrubis | 526fdf8 | 2014-12-04 14:35:01 +0100 | [diff] [blame] | 87 | tst_brkm(TFAIL, NULL, "expected to keep privs but did not"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 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 */ |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 95 | tst_brkm(TFAIL, NULL, "expected to drop privs but did not"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 96 | } |
| 97 | |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 98 | int main(int argc, char *argv[]) |
| 99 | { |
| 100 | int ret, whichtest; |
| 101 | |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 102 | tst_require_root(NULL); |
| 103 | |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 104 | ret = prctl(PR_GET_KEEPCAPS); |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 105 | if (ret) |
| 106 | tst_brkm(TBROK, NULL, "keepcaps was already set?"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 107 | |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 108 | if (argc < 2) |
| 109 | tst_brkm(TBROK, NULL, "Usage: %s <tescase_num>", argv[0]); |
| 110 | |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 111 | whichtest = atoi(argv[1]); |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 112 | if (whichtest < 1 || whichtest > 3) |
| 113 | tst_brkm(TFAIL, NULL, "Valid tests are 1-3"); |
| 114 | |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 115 | switch (whichtest) { |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 116 | case 1: |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 117 | do_setuid(EXPECT_NOPRIVS); /* does not return */ |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 118 | case 2: |
| 119 | ret = prctl(PR_SET_KEEPCAPS, 1); |
| 120 | if (ret == -1) { |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 121 | tst_brkm(TFAIL | TERRNO, NULL, |
| 122 | "PR_SET_KEEPCAPS failed"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 123 | } |
| 124 | ret = prctl(PR_GET_KEEPCAPS); |
| 125 | if (!ret) { |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 126 | tst_brkm(TFAIL | TERRNO, NULL, |
| 127 | "PR_SET_KEEPCAPS did not set keepcaps"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 128 | } |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 129 | do_setuid(EXPECT_PRIVS); /* does not return */ |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 130 | case 3: |
| 131 | ret = prctl(PR_GET_SECUREBITS); |
| 132 | ret = prctl(PR_SET_SECUREBITS, ret | SECBIT_KEEP_CAPS); |
| 133 | if (ret == -1) { |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 134 | tst_brkm(TFAIL | TERRNO, NULL, |
| 135 | "PR_SET_SECUREBITS failed"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 136 | } |
| 137 | ret = prctl(PR_GET_KEEPCAPS); |
| 138 | if (!ret) { |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 139 | tst_brkm(TFAIL | TERRNO, NULL, |
| 140 | "PR_SET_SECUREBITS did not set keepcaps"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 141 | } |
Cyril Hrubis | bba458c | 2012-10-17 15:04:10 +0200 | [diff] [blame] | 142 | do_setuid(EXPECT_PRIVS); /* does not return */ |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 143 | default: |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 144 | tst_brkm(TFAIL, NULL, "Valid tests are 1-3"); |
Subrata Modak | 12bb83d | 2010-10-13 12:45:43 +0530 | [diff] [blame] | 145 | } |
Cyril Hrubis | 4590c29 | 2011-02-07 18:30:37 +0100 | [diff] [blame] | 146 | } |
Cyril Hrubis | c220729 | 2012-10-17 15:23:02 +0200 | [diff] [blame] | 147 | |
| 148 | #else |
| 149 | |
| 150 | int main(void) |
| 151 | { |
Zeng Linggang | 4c35f5b | 2014-10-08 15:49:00 +0800 | [diff] [blame] | 152 | tst_brkm(TCONF, NULL, "linux/securebits.h or libcap does not exist."); |
Cyril Hrubis | c220729 | 2012-10-17 15:23:02 +0200 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | #endif /* HAVE_LIBCAP */ |