blob: 8633b0cb14b74eb44f44f6b16ac1000f85bc2391 [file] [log] [blame]
Subrata Modak12bb83d2010-10-13 12:45:43 +05301#include <errno.h>
2#include "config.h"
3#if HAVE_SYS_CAPABILITY_H
Wanlong Gao354ebb42012-12-07 10:10:04 +08004#include <linux/types.h>
5#include <sys/capability.h>
Subrata Modak12bb83d2010-10-13 12:45:43 +05306#endif
7#include <sys/prctl.h>
Garrett Coopere8530df2010-12-21 11:37:57 -08008#include "test.h"
Subrata Modak12bb83d2010-10-13 12:45:43 +05309
Cyril Hrubis4590c292011-02-07 18:30:37 +010010#ifndef SECBIT_KEEP_CAPS
Wanlong Gao354ebb42012-12-07 10:10:04 +080011#define SECBIT_KEEP_CAPS (1<<4)
Cyril Hrubis4590c292011-02-07 18:30:37 +010012#endif
13
Subrata Modak12bb83d2010-10-13 12:45:43 +053014/* 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
28char *TCID = "keepcaps";
Cyril Hrubisbba458c2012-10-17 15:04:10 +020029int TST_TOTAL = 1;
Subrata Modak12bb83d2010-10-13 12:45:43 +053030
Zeng Linggang4c35f5b2014-10-08 15:49:00 +080031#if (HAVE_LINUX_SECUREBITS_H && HAVE_LIBCAP)
32#include <linux/securebits.h>
33
Subrata Modak12bb83d2010-10-13 12:45:43 +053034static int eff_caps_empty(cap_t c)
35{
Cyril Hrubisbba458c2012-10-17 15:04:10 +020036 int i, ret, empty = 1;
Cyril Hrubis4590c292011-02-07 18:30:37 +010037 cap_flag_value_t v;
Subrata Modak12bb83d2010-10-13 12:45:43 +053038
39 for (i = 0; i < CAP_LAST_CAP; i++) {
40 ret = cap_get_flag(c, i, CAP_PERMITTED, &v);
Zeng Linggang09db1372014-08-06 15:17:32 +080041 /*
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 Modak12bb83d2010-10-13 12:45:43 +053051 if (ret || v)
52 empty = 0;
53 }
54
55 return empty;
56}
57
58static 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 Modak12bb83d2010-10-13 12:45:43 +053069
70#define EXPECT_NOPRIVS 0
71#define EXPECT_PRIVS 1
72static void do_setuid(int expect_privs)
73{
74 int ret;
75 int have_privs;
76
77 ret = setuid(1000);
Zeng Linggang4c35f5b2014-10-08 15:49:00 +080078 if (ret)
79 tst_brkm(TERRNO | TFAIL, NULL, "setuid failed");
Subrata Modak12bb83d2010-10-13 12:45:43 +053080
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 Hrubis526fdf82014-12-04 14:35:01 +010087 tst_brkm(TFAIL, NULL, "expected to keep privs but did not");
Subrata Modak12bb83d2010-10-13 12:45:43 +053088 }
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 Linggang4c35f5b2014-10-08 15:49:00 +080095 tst_brkm(TFAIL, NULL, "expected to drop privs but did not");
Subrata Modak12bb83d2010-10-13 12:45:43 +053096}
97
Subrata Modak12bb83d2010-10-13 12:45:43 +053098int main(int argc, char *argv[])
99{
100 int ret, whichtest;
101
Cyril Hrubisbba458c2012-10-17 15:04:10 +0200102 tst_require_root(NULL);
103
Subrata Modak12bb83d2010-10-13 12:45:43 +0530104 ret = prctl(PR_GET_KEEPCAPS);
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800105 if (ret)
106 tst_brkm(TBROK, NULL, "keepcaps was already set?");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530107
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800108 if (argc < 2)
109 tst_brkm(TBROK, NULL, "Usage: %s <tescase_num>", argv[0]);
110
Subrata Modak12bb83d2010-10-13 12:45:43 +0530111 whichtest = atoi(argv[1]);
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800112 if (whichtest < 1 || whichtest > 3)
113 tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
114
Cyril Hrubisbba458c2012-10-17 15:04:10 +0200115 switch (whichtest) {
Subrata Modak12bb83d2010-10-13 12:45:43 +0530116 case 1:
Cyril Hrubisbba458c2012-10-17 15:04:10 +0200117 do_setuid(EXPECT_NOPRIVS); /* does not return */
Subrata Modak12bb83d2010-10-13 12:45:43 +0530118 case 2:
119 ret = prctl(PR_SET_KEEPCAPS, 1);
120 if (ret == -1) {
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800121 tst_brkm(TFAIL | TERRNO, NULL,
122 "PR_SET_KEEPCAPS failed");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530123 }
124 ret = prctl(PR_GET_KEEPCAPS);
125 if (!ret) {
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800126 tst_brkm(TFAIL | TERRNO, NULL,
127 "PR_SET_KEEPCAPS did not set keepcaps");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530128 }
Cyril Hrubisbba458c2012-10-17 15:04:10 +0200129 do_setuid(EXPECT_PRIVS); /* does not return */
Subrata Modak12bb83d2010-10-13 12:45:43 +0530130 case 3:
131 ret = prctl(PR_GET_SECUREBITS);
132 ret = prctl(PR_SET_SECUREBITS, ret | SECBIT_KEEP_CAPS);
133 if (ret == -1) {
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800134 tst_brkm(TFAIL | TERRNO, NULL,
135 "PR_SET_SECUREBITS failed");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530136 }
137 ret = prctl(PR_GET_KEEPCAPS);
138 if (!ret) {
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800139 tst_brkm(TFAIL | TERRNO, NULL,
140 "PR_SET_SECUREBITS did not set keepcaps");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530141 }
Cyril Hrubisbba458c2012-10-17 15:04:10 +0200142 do_setuid(EXPECT_PRIVS); /* does not return */
Subrata Modak12bb83d2010-10-13 12:45:43 +0530143 default:
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800144 tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
Subrata Modak12bb83d2010-10-13 12:45:43 +0530145 }
Cyril Hrubis4590c292011-02-07 18:30:37 +0100146}
Cyril Hrubisc2207292012-10-17 15:23:02 +0200147
148#else
149
150int main(void)
151{
Zeng Linggang4c35f5b2014-10-08 15:49:00 +0800152 tst_brkm(TCONF, NULL, "linux/securebits.h or libcap does not exist.");
Cyril Hrubisc2207292012-10-17 15:23:02 +0200153}
154
155#endif /* HAVE_LIBCAP */