xref: /freebsd/tests/sys/mac/do/regression.c (revision 96bf349029d495c6aa2d67efc14b24aad7989e3b)
1*96bf3490SMark Johnston /*
2*96bf3490SMark Johnston  * Copyright (c) 2026 The FreeBSD Foundation
3*96bf3490SMark Johnston  *
4*96bf3490SMark Johnston  * This software was developed by Mark Johnston under sponsorship from
5*96bf3490SMark Johnston  * the FreeBSD Foundation.
6*96bf3490SMark Johnston  *
7*96bf3490SMark Johnston  * SPDX-License-Identifier: BSD-2-Clause
8*96bf3490SMark Johnston  */
9*96bf3490SMark Johnston 
10*96bf3490SMark Johnston #include <sys/sysctl.h>
11*96bf3490SMark Johnston #include <sys/ucred.h>
12*96bf3490SMark Johnston 
13*96bf3490SMark Johnston #include <errno.h>
14*96bf3490SMark Johnston #include <libgen.h>
15*96bf3490SMark Johnston #include <limits.h>
16*96bf3490SMark Johnston #include <pwd.h>
17*96bf3490SMark Johnston #include <stdio.h>
18*96bf3490SMark Johnston #include <stdlib.h>
19*96bf3490SMark Johnston #include <string.h>
20*96bf3490SMark Johnston 
21*96bf3490SMark Johnston #include <atf-c.h>
22*96bf3490SMark Johnston 
23*96bf3490SMark Johnston /*
24*96bf3490SMark Johnston  * Regression test for a bug which erroneously allowed the setcred() call below.
25*96bf3490SMark Johnston  */
26*96bf3490SMark Johnston ATF_TC(empty_supplementary_group_list);
ATF_TC_HEAD(empty_supplementary_group_list,tc)27*96bf3490SMark Johnston ATF_TC_HEAD(empty_supplementary_group_list, tc)
28*96bf3490SMark Johnston {
29*96bf3490SMark Johnston 	atf_tc_set_md_var(tc, "require.user", "root");
30*96bf3490SMark Johnston }
ATF_TC_BODY(empty_supplementary_group_list,tc)31*96bf3490SMark Johnston ATF_TC_BODY(empty_supplementary_group_list, tc)
32*96bf3490SMark Johnston {
33*96bf3490SMark Johnston 	struct setcred cred = SETCRED_INITIALIZER;
34*96bf3490SMark Johnston 	struct passwd *passwd;
35*96bf3490SMark Johnston 	const char *user;
36*96bf3490SMark Johnston 	char path[PATH_MAX], *progname, *rule;
37*96bf3490SMark Johnston 	int flags;
38*96bf3490SMark Johnston 
39*96bf3490SMark Johnston 	if (!atf_tc_has_config_var(tc, "unprivileged_user"))
40*96bf3490SMark Johnston 		atf_tc_skip("unprivileged_user not set");
41*96bf3490SMark Johnston 
42*96bf3490SMark Johnston 	user = atf_tc_get_config_var(tc, "unprivileged_user");
43*96bf3490SMark Johnston 	passwd = getpwnam(user);
44*96bf3490SMark Johnston 	ATF_REQUIRE(passwd != NULL);
45*96bf3490SMark Johnston 	ATF_REQUIRE_MSG(passwd->pw_uid != 0,
46*96bf3490SMark Johnston 	    "unprivileged user must not be root");
47*96bf3490SMark Johnston 	ATF_REQUIRE_MSG(passwd->pw_gid != 0,
48*96bf3490SMark Johnston 	    "unprivileged user group must not be wheel");
49*96bf3490SMark Johnston 
50*96bf3490SMark Johnston 	(void)asprintf(&rule, "uid=%d>uid=%d;gid=0>uid=0",
51*96bf3490SMark Johnston 	    passwd->pw_uid, passwd->pw_uid + 1);
52*96bf3490SMark Johnston 	ATF_REQUIRE(sysctlbyname("security.mac.do.rules",
53*96bf3490SMark Johnston 	    NULL, NULL, rule, strlen(rule)) == 0);
54*96bf3490SMark Johnston 
55*96bf3490SMark Johnston 	progname = basename(strdup(getprogname()));
56*96bf3490SMark Johnston 	(void)snprintf(path, sizeof(path), "%s/%s",
57*96bf3490SMark Johnston 	    atf_tc_get_config_var(tc, "srcdir"), progname);
58*96bf3490SMark Johnston 	ATF_REQUIRE(sysctlbyname("security.mac.do.exec_paths",
59*96bf3490SMark Johnston 	    NULL, NULL, path, strlen(path)) == 0);
60*96bf3490SMark Johnston 
61*96bf3490SMark Johnston 	ATF_REQUIRE(setgroups(0, NULL) == 0);
62*96bf3490SMark Johnston 	ATF_REQUIRE(setgid(passwd->pw_gid) == 0);
63*96bf3490SMark Johnston 	ATF_REQUIRE(setuid(passwd->pw_uid) == 0);
64*96bf3490SMark Johnston 
65*96bf3490SMark Johnston 	/*
66*96bf3490SMark Johnston 	 * Request the UID transition permitted by the first rule while also
67*96bf3490SMark Johnston 	 * setting all primary GIDs to 0.  MAC/do must reject this because GID 0
68*96bf3490SMark Johnston 	 * is not a primary GID of the current credential.
69*96bf3490SMark Johnston 	 */
70*96bf3490SMark Johnston 	cred.sc_uid = cred.sc_ruid = cred.sc_svuid = passwd->pw_uid + 1;
71*96bf3490SMark Johnston 	cred.sc_gid = cred.sc_rgid = cred.sc_svgid = 0;
72*96bf3490SMark Johnston 	flags = SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID |
73*96bf3490SMark Johnston 	    SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID;
74*96bf3490SMark Johnston 	ATF_REQUIRE_ERRNO(EPERM,
75*96bf3490SMark Johnston 	    setcred(flags, &cred, sizeof(cred)) == -1);
76*96bf3490SMark Johnston }
77*96bf3490SMark Johnston 
ATF_TP_ADD_TCS(tp)78*96bf3490SMark Johnston ATF_TP_ADD_TCS(tp)
79*96bf3490SMark Johnston {
80*96bf3490SMark Johnston 	ATF_TP_ADD_TC(tp, empty_supplementary_group_list);
81*96bf3490SMark Johnston 
82*96bf3490SMark Johnston 	return (atf_no_error());
83*96bf3490SMark Johnston }
84