112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#include <errno.h>
212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#include "config.h"
312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#if HAVE_SYS_CAPABILITY_H
4354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <linux/types.h>
5354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <sys/capability.h>
612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#endif
712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#include <sys/prctl.h>
8e8530df4da095b0ea36a9ff8118ab5ce906b3e84Garrett Cooper#include "test.h"
912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
104590c297cff4643bba8c730a62ce71889a22ca92Cyril Hrubis#ifndef SECBIT_KEEP_CAPS
11354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define SECBIT_KEEP_CAPS (1<<4)
124590c297cff4643bba8c730a62ce71889a22ca92Cyril Hrubis#endif
134590c297cff4643bba8c730a62ce71889a22ca92Cyril Hrubis
1412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak/* Tests:
1512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	1. drop capabilities at setuid if KEEPCAPS is not set and
1612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	   new user is nonroot
1712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	2. keep capabilities if set and new user is nonroot
1812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	   a. do with prctl(PR_SET_KEEPCAPS)
1912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	   (call this test 2)
2012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	   b. do with prctl(PR_SET_SECUREBITS, SECURE_KEEP_CAPS)
2112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	   (call this test 3)
2212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak   TODO: test that exec clears KEEPCAPS
2312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak   	(just create a simple executable that checks PR_GET_KEEPCAPS
2412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	 results, and execute that as test 4 after doing PR_SET_KEEPCAPS).
2512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak   TODO: all of the other securebits tests.
2612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak */
2712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
2812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modakchar *TCID = "keepcaps";
29bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubisint TST_TOTAL = 1;
3012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
314c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang#if (HAVE_LINUX_SECUREBITS_H && HAVE_LIBCAP)
324c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang#include <linux/securebits.h>
334c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang
3412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modakstatic int eff_caps_empty(cap_t c)
3512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak{
36bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis	int i, ret, empty = 1;
374590c297cff4643bba8c730a62ce71889a22ca92Cyril Hrubis	cap_flag_value_t v;
3812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
3912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	for (i = 0; i < CAP_LAST_CAP; i++) {
4012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = cap_get_flag(c, i, CAP_PERMITTED, &v);
4109db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		/*
4209db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		 * If the value of CAP_LAST_CAP in linux/capability.h is greater
4309db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		 * than the value in the capability.h which is used to create
4409db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		 * libcap.so. Then cap_get_flag returns -1, and errno is set to
4509db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		 * EINVAL.
4609db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		 */
4709db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		if (ret == -1) {
4809db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang			tst_brkm(TBROK | TERRNO, NULL,
4909db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang				"Not expected. Please check arguments.");
5009db1372e20f70ee60f14792ab6330bdba3d657fZeng Linggang		}
5112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		if (ret || v)
5212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak			empty = 0;
5312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	}
5412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
5512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	return empty;
5612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak}
5712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
5812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modakstatic int am_privileged(void)
5912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak{
6012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	int am_privileged = 1;
6112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
6212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	cap_t cap = cap_get_proc();
6312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	if (eff_caps_empty(cap))
6412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		am_privileged = 0;
6512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	cap_free(cap);
6612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
6712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	return am_privileged;
6812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak}
6912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
7012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#define EXPECT_NOPRIVS 0
7112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak#define EXPECT_PRIVS 1
7212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modakstatic void do_setuid(int expect_privs)
7312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak{
7412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	int ret;
7512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	int have_privs;
7612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
7712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	ret = setuid(1000);
784c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	if (ret)
794c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang		tst_brkm(TERRNO | TFAIL, NULL, "setuid failed");
8012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
8112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	have_privs = am_privileged();
8212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	if (have_privs && expect_privs == EXPECT_PRIVS) {
8312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		tst_resm(TPASS, "kept privs as expected");
8412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		tst_exit();
8512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	}
8612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	if (!have_privs && expect_privs == EXPECT_PRIVS) {
87526fdf8d8ea3b43b73de7cc25eb754f12702c8d2Cyril Hrubis		tst_brkm(TFAIL, NULL, "expected to keep privs but did not");
8812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	}
8912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	if (!have_privs && expect_privs == EXPECT_NOPRIVS) {
9012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		tst_resm(TPASS, "dropped privs as expected");
9112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		tst_exit();
9212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	}
9312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
9412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	/* have_privs && EXPECT_NOPRIVS */
954c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	tst_brkm(TFAIL, NULL, "expected to drop privs but did not");
9612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak}
9712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
9812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modakint main(int argc, char *argv[])
9912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak{
10012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	int ret, whichtest;
10112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
102d1e794d62b1bf619df8390535e4c2a58899b1145Cyril Hrubis	tst_require_root();
103bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis
10412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	ret = prctl(PR_GET_KEEPCAPS);
1054c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	if (ret)
1064c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang		tst_brkm(TBROK, NULL, "keepcaps was already set?");
1074c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang
1084c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	if (argc < 2)
1094c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang		tst_brkm(TBROK, NULL, "Usage: %s <tescase_num>", argv[0]);
11012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak
11112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	whichtest = atoi(argv[1]);
1124c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	if (whichtest < 1 || whichtest > 3)
1134c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang		tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
1144c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang
115bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis	switch (whichtest) {
11612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	case 1:
117bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis		do_setuid(EXPECT_NOPRIVS);	/* does not return */
11812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	case 2:
11912bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = prctl(PR_SET_KEEPCAPS, 1);
12012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		if (ret == -1) {
1214c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang			tst_brkm(TFAIL | TERRNO, NULL,
1224c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang				 "PR_SET_KEEPCAPS failed");
12312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		}
12412bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = prctl(PR_GET_KEEPCAPS);
12512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		if (!ret) {
1264c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang			tst_brkm(TFAIL | TERRNO, NULL,
1274c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang				 "PR_SET_KEEPCAPS did not set keepcaps");
12812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		}
129bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis		do_setuid(EXPECT_PRIVS);	/* does not return */
13012bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	case 3:
13112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = prctl(PR_GET_SECUREBITS);
13212bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = prctl(PR_SET_SECUREBITS, ret | SECBIT_KEEP_CAPS);
13312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		if (ret == -1) {
1344c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang			tst_brkm(TFAIL | TERRNO, NULL,
1354c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang				 "PR_SET_SECUREBITS failed");
13612bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		}
13712bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		ret = prctl(PR_GET_KEEPCAPS);
13812bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		if (!ret) {
1394c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang			tst_brkm(TFAIL | TERRNO, NULL,
1404c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang				 "PR_SET_SECUREBITS did not set keepcaps");
14112bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak		}
142bba458c56d16589f0bcbfe299709f6c3929e7e2eCyril Hrubis		do_setuid(EXPECT_PRIVS);	/* does not return */
14312bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	default:
1444c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang		tst_brkm(TFAIL, NULL, "Valid tests are 1-3");
14512bb83d825c7b58bb4fb3322620591c9fdf4ff5cSubrata Modak	}
1464590c297cff4643bba8c730a62ce71889a22ca92Cyril Hrubis}
147c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis
148c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis#else
149c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis
150c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubisint main(void)
151c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis{
1524c35f5b67afa11dabd902e5e4d85d6416e22fa3bZeng Linggang	tst_brkm(TCONF, NULL, "linux/securebits.h or libcap does not exist.");
153c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis}
154c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis
155c220729f1dea6e6eca696b255c01dfd4dc897df9Cyril Hrubis#endif /* HAVE_LIBCAP */
156