xref: /freebsd/sys/security/mac_do/mac_do.c (revision 0c2d64ce3da9c042da133c8b6d7391abb177f2c9)
1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
5  * Copyright (c) 2024, 2026, The FreeBSD Foundation
6  * Copyright (c) 2025 Kushagra Srivastava <kushagra1403@gmail.com>
7  *
8  * Portions of this software were developed by Olivier Certner
9  * <olce.freebsd@certner.fr> at Kumacom SARL under sponsorship from the FreeBSD
10  * Foundation.
11  */
12 
13 #include <sys/param.h>
14 #include <sys/systm.h>
15 #include <sys/ctype.h>
16 #include <sys/jail.h>
17 #include <sys/kernel.h>
18 #include <sys/limits.h>
19 #include <sys/lock.h>
20 #include <sys/malloc.h>
21 #include <sys/module.h>
22 #include <sys/mount.h>
23 #include <sys/mutex.h>
24 #include <sys/priv.h>
25 #include <sys/proc.h>
26 #include <sys/refcount.h>
27 #include <sys/rmlock.h>
28 #include <sys/socket.h>
29 #include <sys/stdarg.h>
30 #include <sys/sx.h>
31 #include <sys/sysctl.h>
32 #include <sys/ucred.h>
33 #include <sys/vnode.h>
34 
35 #include <security/mac/mac_policy.h>
36 
37 
38 #ifdef INVARIANTS
39 /*
40  * Should typically be moved to libkern (and perhaps libc) at some point, and be
41  * optimized if to be used outside of INVARIANTS.
42  */
43 static bool
is_zeroed(const void * const buf,const size_t size)44 is_zeroed(const void *const buf, const size_t size)
45 {
46 	const char *const p = buf;
47 
48 	for (size_t i = 0; i < size; ++i)
49 		if (p[i] != 0)
50 			return (false);
51 	return (true);
52 }
53 #endif
54 
55 static SYSCTL_NODE(_security_mac, OID_AUTO, do,
56     CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "mac_do policy controls");
57 
58 static int	do_enabled = 1;
59 SYSCTL_INT(_security_mac_do, OID_AUTO, enabled, CTLFLAG_RWTUN,
60     &do_enabled, 0, "Enforce do policy");
61 
62 static int	print_parse_error = 1;
63 SYSCTL_INT(_security_mac_do, OID_AUTO, print_parse_error, CTLFLAG_RWTUN,
64     &print_parse_error, 0, "Print parse errors on setting rules "
65     "(via sysctl(8)).");
66 
67 static MALLOC_DEFINE(M_MAC_DO, "mac_do", "mac_do(4) security module");
68 
69 #define MAX_RULE_STRING_SIZE	1024
70 _Static_assert(MAX_RULE_STRING_SIZE > 0,
71     "MAX_RULE_STRING_SIZE: No space for the NUL terminator!");
72 
73 #define MAX_EXEC_PATHS_SIZE	2048
74 #define MAX_EXEC_PATHS		8
75 _Static_assert(MAX_EXEC_PATHS_SIZE > 0,
76     "MAX_EXEC_PATHS_SIZE: No space for the NUL terminator!");
77 
78 struct rmlock mac_do_rml;
79 
80 static unsigned		osd_jail_slot;
81 static unsigned		osd_thread_slot;
82 
83 #define IT_INVALID	0 /* Must stay 0. */
84 #define IT_UID		1
85 #define IT_GID		2
86 #define IT_ANY		3
87 #define IT_LAST		IT_ANY
88 
89 static const char *id_type_to_str[] = {
90 	[IT_INVALID]	= "invalid",
91 	[IT_UID]	= "uid",
92 	[IT_GID]	= "gid",
93 	/* See also parse_id_type(). */
94 	[IT_ANY]	= "*",
95 };
96 
97 #define PARSE_ERROR_SIZE	256
98 
99 /*
100  * All functions having a parse error parameter must return through it a parse
101  * error object if and only if they return an error value (non-zero); else, NULL
102  * must be returned through it.
103  */
104 struct parse_error {
105 	size_t	pos;
106 	char	msg[PARSE_ERROR_SIZE];
107 };
108 
109 /*
110  * We assume that 'uid_t' and 'gid_t' are aliases to 'u_int' in conversions
111  * required for parsing rules specification strings.
112  */
113 _Static_assert(sizeof(uid_t) == sizeof(u_int) && (uid_t)-1 >= 0 &&
114     sizeof(gid_t) == sizeof(u_int) && (gid_t)-1 >= 0,
115     "mac_do(4) assumes that 'uid_t' and 'gid_t' are aliases to 'u_int'");
116 
117 /*
118  * Internal flags.
119  *
120  * They either apply as per-type (t) or per-ID (i) but are conflated because all
121  * per-ID flags are also valid as per-type ones to qualify the "current" (".")
122  * per-type flag.  Also, some of them are in fact exclusive, but we use one-hot
123  * encoding for simplicity.
124  *
125  * There is currently room for "only" 16 bits.  As these flags are purely
126  * internal, they can be renumbered and/or the underlying type changed as
127  * needed.
128  *
129  * See also the check_*() functions below.
130  */
131 typedef uint16_t	flags_t;
132 
133 /* (i,gid) Group can appear as a primary group. */
134 #define MDF_PRIMARY	(1u << 0)
135 /* (i,gid) Group can appear as a supplementary group. */
136 #define MDF_SUPP_ALLOW	(1u << 1)
137 /* (i,gid) Group must appear as a supplementary group. */
138 #define MDF_SUPP_MUST	(1u << 2)
139 /* (i,gid) Group must not appear as a supplementary group. */
140 #define MDF_SUPP_DONT	(1u << 3)
141 /* (i,gid) Mask to detect a supplementary group specification. */
142 #define MDF_SUPP_MASK	(MDF_SUPP_ALLOW | MDF_SUPP_MUST | MDF_SUPP_DONT)
143 #define MDF_ID_MASK	(MDF_PRIMARY | MDF_SUPP_MASK)
144 
145 /*
146  * (t) All IDs allowed.
147  *
148  * For GIDs, MDF_ANY only concerns primary groups.  The MDF_PRIMARY and
149  * MDF_SUPP_* flags do not apply to MDF_ANY, but can be present if MDF_CURRENT
150  * is present also, as for explicit IDs.
151  */
152 #define MDF_ANY			(1u << 8)
153 /* (t) Current IDs allowed. */
154 #define MDF_CURRENT		(1u << 9)
155 #define MDF_TYPE_COMMON_MASK	(MDF_ANY | MDF_CURRENT)
156 /* (t,gid) All IDs allowed as supplementary groups. */
157 #define MDF_ANY_SUPP		(1u << 10)
158 /* (t,gid) Some ID or MDF_CURRENT has MDF_SUPP_MUST or MDF_SUPP_DONT. */
159 #define MDF_MAY_REJ_SUPP	(1u << 11)
160 /* (t,gid) Some explicit ID (not MDF_CURRENT) has MDF_SUPP_MUST. */
161 #define MDF_EXPLICIT_SUPP_MUST	(1u << 12)
162 /*
163  * (t,gid) Whether any target clause is about primary groups.  Used during
164  * parsing only.
165  */
166 #define MDF_HAS_PRIMARY_CLAUSE	(1u << 13)
167 /*
168  * (t,gid) Whether any target clause is about supplementary groups.  Used during
169  * parsing only.
170  */
171 #define MDF_HAS_SUPP_CLAUSE	(1u << 14)
172 #define MDF_TYPE_GID_MASK	(MDF_ANY_SUPP | MDF_MAY_REJ_SUPP |	\
173     MDF_EXPLICIT_SUPP_MUST | MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE)
174 #define MDF_TYPE_MASK		(MDF_TYPE_COMMON_MASK | MDF_TYPE_GID_MASK)
175 
176 /*
177  * Persistent structures.
178  */
179 
180 struct id_spec {
181 	u_int		 id;
182 	flags_t		 flags; /* See MDF_* above. */
183 };
184 
185 /*
186  * This limits the number of target clauses per type to 65535.  With the current
187  * value of MAX_RULE_STRING_SIZE (1024), this is way more than enough anyway.
188  */
189 typedef uint16_t	 id_nb_t;
190 /* We only have a few IT_* types. */
191 typedef uint16_t	 id_type_t;
192 
193 struct rule {
194 	STAILQ_ENTRY(rule) r_entries;
195 	id_type_t	 from_type;
196 	u_int		 from_id;
197 	flags_t		 uid_flags; /* See MDF_* above. */
198 	id_nb_t		 uids_nb;
199 	flags_t		 gid_flags; /* See MDF_* above. */
200 	id_nb_t		 gids_nb;
201 	struct id_spec	*uids;
202 	struct id_spec	*gids;
203 };
204 
205 STAILQ_HEAD(rulehead, rule);
206 
207 struct rules {
208 	char		string[MAX_RULE_STRING_SIZE];
209 	struct rulehead	head;
210 };
211 
212 struct exec_paths {
213 	char exec_paths_str[MAX_EXEC_PATHS_SIZE];
214 	char exec_paths[MAX_EXEC_PATHS][PATH_MAX];
215 	int exec_path_count;
216 };
217 
218 /*
219  * Once in use, i.e., being pointed to by a jail, a configuration structure MUST
220  * NEVER CHANGE (except for the 'use_count' field).  This invariant is
221  * fundamental to correctness!
222  */
223 struct conf {
224 	struct rules rules;
225 	struct exec_paths exec_paths;
226 	volatile u_int	use_count __aligned(CACHE_LINE_SIZE);
227 };
228 
229 /*
230  * Temporary structures used to build a 'struct rule' above.
231  */
232 
233 struct id_elem {
234 	STAILQ_ENTRY(id_elem) ie_entries;
235 	struct id_spec spec;
236 };
237 
238 STAILQ_HEAD(id_list, id_elem);
239 
240 
241 #ifdef INVARIANTS
242 static void
check_type(const id_type_t type)243 check_type(const id_type_t type)
244 {
245 	if (type > IT_LAST)
246 		panic("Invalid type number %u", type);
247 }
248 
249 static void
panic_for_unexpected_flags(const id_type_t type,const flags_t flags,const char * const str)250 panic_for_unexpected_flags(const id_type_t type, const flags_t flags,
251     const char *const str)
252 {
253 	panic("ID type %s: Unexpected flags %u (%s), ", id_type_to_str[type],
254 	    flags, str);
255 }
256 
257 static void
check_type_and_id_flags(const id_type_t type,const flags_t flags)258 check_type_and_id_flags(const id_type_t type, const flags_t flags)
259 {
260 	const char *str;
261 
262 	check_type(type);
263 	switch (type) {
264 	case IT_UID:
265 		if (flags != 0) {
266 			str = "only 0 allowed";
267 			goto unexpected_flags;
268 		}
269 		break;
270 	case IT_GID:
271 		if ((flags & ~MDF_ID_MASK) != 0) {
272 			str = "only bits in MDF_ID_MASK allowed";
273 			goto unexpected_flags;
274 		}
275 		if (!powerof2(flags & MDF_SUPP_MASK)) {
276 			str = "only a single flag in MDF_SUPP_MASK allowed";
277 			goto unexpected_flags;
278 		}
279 		break;
280 	default:
281 		__assert_unreachable();
282 	}
283 	return;
284 
285 unexpected_flags:
286 	panic_for_unexpected_flags(type, flags, str);
287 }
288 
289 static void
check_type_and_id_spec(const id_type_t type,const struct id_spec * const is)290 check_type_and_id_spec(const id_type_t type, const struct id_spec *const is)
291 {
292 	check_type_and_id_flags(type, is->flags);
293 }
294 
295 static void
check_type_and_type_flags(const id_type_t type,const flags_t flags)296 check_type_and_type_flags(const id_type_t type, const flags_t flags)
297 {
298 	const char *str;
299 
300 	check_type_and_id_flags(type, flags & MDF_ID_MASK);
301 	if ((flags & ~MDF_ID_MASK & ~MDF_TYPE_MASK) != 0) {
302 		str = "only MDF_ID_MASK | MDF_TYPE_MASK bits allowed";
303 		goto unexpected_flags;
304 	}
305 	if ((flags & MDF_ANY) != 0 && (flags & MDF_CURRENT) != 0 &&
306 	    (type == IT_UID || (flags & MDF_PRIMARY) != 0)) {
307 		str = "MDF_ANY and MDF_CURRENT are exclusive for UIDs "
308 		    "or primary group GIDs";
309 		goto unexpected_flags;
310 	}
311 	if ((flags & MDF_ANY_SUPP) != 0 && (flags & MDF_CURRENT) != 0 &&
312 	    (flags & MDF_SUPP_MASK) != 0) {
313 		str = "MDF_SUPP_ANY and MDF_CURRENT with supplementary "
314 		    "groups specification are exclusive";
315 		goto unexpected_flags;
316 	}
317 	if (type == IT_GID &&
318 	    ((flags & MDF_PRIMARY) != 0 || (flags & MDF_ANY) != 0) &&
319 	    (flags & MDF_HAS_PRIMARY_CLAUSE) == 0) {
320 		str = "Presence of folded primary clause not reflected "
321 		    "by presence of MDF_HAS_PRIMARY_CLAUSE";
322 		goto unexpected_flags;
323 	}
324 	if (((flags & MDF_SUPP_MASK) != 0 || (flags & MDF_ANY_SUPP) != 0) &&
325 	    (flags & MDF_HAS_SUPP_CLAUSE) == 0) {
326 		str = "Presence of folded supplementary clause not reflected "
327 		    "by presence of MDF_HAS_SUPP_CLAUSE";
328 		goto unexpected_flags;
329 	}
330 	return;
331 
332 unexpected_flags:
333 	panic_for_unexpected_flags(type, flags, str);
334 }
335 #else /* !INVARIANTS */
336 #define check_type_and_id_flags(...)
337 #define check_type_and_id_spec(...)
338 #define check_type_and_type_flags(...)
339 #endif /* INVARIANTS */
340 
341 static bool
has_rules(const struct rules * const rules)342 has_rules(const struct rules *const rules)
343 {
344 	return (rules->string[0] != '\0');
345 }
346 
347 static bool
has_exec_paths(const struct exec_paths * const exec_paths)348 has_exec_paths(const struct exec_paths *const exec_paths)
349 {
350 	return (exec_paths->exec_paths_str[0] != '\0');
351 }
352 
353 /*
354  * Returns EALREADY if both flags have some overlap, or EINVAL if flags are
355  * incompatible, else 0 with flags successfully merged into 'dest'.
356  */
357 static int
coalesce_id_flags(const flags_t src,flags_t * const dest)358 coalesce_id_flags(const flags_t src, flags_t *const dest)
359 {
360 	flags_t res;
361 
362 	if ((src & *dest) != 0)
363 		return (EALREADY);
364 
365 	res = src | *dest;
366 
367 	/* Check for compatibility of supplementary flags, and coalesce. */
368 	if ((res & MDF_SUPP_MASK) != 0) {
369 		/* MDF_SUPP_DONT incompatible with the rest. */
370 		if ((res & MDF_SUPP_DONT) != 0 && (res & MDF_SUPP_MASK &
371 		    ~MDF_SUPP_DONT) != 0)
372 			return (EINVAL);
373 		/*
374 		 * Coalesce MDF_SUPP_ALLOW and MDF_SUPP_MUST into MDF_SUPP_MUST.
375 		 */
376 		if ((res & MDF_SUPP_ALLOW) != 0 && (res & MDF_SUPP_MUST) != 0)
377 			res &= ~MDF_SUPP_ALLOW;
378 	}
379 
380 	*dest = res;
381 	return (0);
382 }
383 
384 static void
toast_rules(struct rules * const rules)385 toast_rules(struct rules *const rules)
386 {
387 	struct rulehead *const head = &rules->head;
388 	struct rule *rule, *rule_next;
389 
390 	STAILQ_FOREACH_SAFE(rule, head, r_entries, rule_next) {
391 		free(rule->uids, M_MAC_DO);
392 		free(rule->gids, M_MAC_DO);
393 		free(rule, M_MAC_DO);
394 	}
395 	STAILQ_INIT(head);
396 }
397 
398 static inline void
init_rules(struct rules * const rules)399 init_rules(struct rules *const rules)
400 {
401 	MPASS(is_zeroed(rules, sizeof(*rules)));
402 	STAILQ_INIT(&rules->head);
403 }
404 
405 static inline void
init_exec_paths(struct exec_paths * const exec_paths)406 init_exec_paths(struct exec_paths *const exec_paths)
407 {
408 	MPASS(is_zeroed(exec_paths, sizeof(*exec_paths)));
409 }
410 
411 static struct conf *
new_conf(void)412 new_conf(void)
413 {
414 	struct conf *const conf = malloc(sizeof(*conf), M_MAC_DO,
415 	    M_WAITOK | M_ZERO);
416 
417 	init_rules(&conf->rules);
418 	init_exec_paths(&conf->exec_paths);
419 	refcount_init(&conf->use_count, 1);
420 
421 	return (conf);
422 }
423 
424 static bool
is_null_or_empty(const char * const s)425 is_null_or_empty(const char *const s)
426 {
427 	return (s == NULL || s[0] == '\0');
428 }
429 
430 /*
431  * String to unsigned int.
432  *
433  * Contrary to the "standard" strtou*() family of functions, do not tolerate
434  * spaces at start nor an empty string, and returns a status code, the 'u_int'
435  * result being returned through a passed pointer (if no error).
436  *
437  * We detour through 'quad_t' because in-kernel strto*() functions cannot set
438  * 'errno' and thus can't distinguish a true maximum value from one returned
439  * because of overflow.  We use 'quad_t' instead of 'u_quad_t' to support
440  * negative specifications (e.g., such as "-1" for UINT_MAX).
441  */
442 static int
strtoui_strict(const char * const restrict s,const char ** const restrict endptr,int base,u_int * result)443 strtoui_strict(const char *const restrict s, const char **const restrict endptr,
444     int base, u_int *result)
445 {
446 	char *ep;
447 	quad_t q;
448 
449 	/* Rule out spaces and empty specifications. */
450 	if (s[0] == '\0' || isspace(s[0])) {
451 		if (endptr != NULL)
452 			*endptr = s;
453 		return (EINVAL);
454 	}
455 
456 	q = strtoq(s, &ep, base);
457 	if (endptr != NULL)
458 		*endptr = ep;
459 	if (q < 0) {
460 		/* We allow specifying a negative number. */
461 		if (q < -(quad_t)UINT_MAX - 1 || q == QUAD_MIN)
462 			return (EOVERFLOW);
463 	} else {
464 		if (q > UINT_MAX || q == UQUAD_MAX)
465 			return (EOVERFLOW);
466 	}
467 
468 	*result = (u_int)q;
469 	return (0);
470 }
471 
472 /*
473  * strsep() variant skipping spaces and tabs.
474  *
475  * Skips spaces and tabs at beginning and end of the token before one of the
476  * 'delim' characters, i.e., at start of string and just before one of the
477  * delimiter characters (so it doesn't prevent tokens containing spaces and tabs
478  * in the middle).
479  */
480 static char *
strsep_noblanks(char ** const stringp,const char * delim)481 strsep_noblanks(char **const stringp, const char *delim)
482 {
483 	char *p = *stringp;
484 	char *ret, *wsp;
485 	size_t idx;
486 
487 	if (p == NULL)
488 		return (NULL);
489 
490 	idx = strspn(p, " \t");
491 	p += idx;
492 
493 	ret = strsep(&p, delim);
494 
495 	/* Rewind spaces/tabs at the end. */
496 	if (p == NULL)
497 		wsp = ret + strlen(ret);
498 	else
499 		wsp = p - 1;
500 	for (; wsp != ret; --wsp) {
501 		switch (wsp[-1]) {
502 		case ' ':
503 		case '\t':
504 			continue;
505 		}
506 		break;
507 	}
508 	*wsp = '\0';
509 
510 	*stringp = p;
511 	return (ret);
512 }
513 
514 
515 static void
make_parse_error(struct parse_error ** const parse_error,const size_t pos,const char * const fmt,...)516 make_parse_error(struct parse_error **const parse_error, const size_t pos,
517     const char *const fmt, ...)
518 {
519 	struct parse_error *const err = malloc(sizeof(*err), M_MAC_DO,
520 	    M_WAITOK);
521 	va_list ap;
522 
523 	err->pos = pos;
524 	va_start(ap, fmt);
525 	vsnprintf(err->msg, PARSE_ERROR_SIZE, fmt, ap);
526 	va_end(ap);
527 
528 	MPASS(*parse_error == NULL);
529 	*parse_error = err;
530 }
531 
532 static void
free_parse_error(struct parse_error * const parse_error)533 free_parse_error(struct parse_error *const parse_error)
534 {
535 	free(parse_error, M_MAC_DO);
536 }
537 
538 static int
parse_id_type(const char * const string,id_type_t * const type,struct parse_error ** const parse_error)539 parse_id_type(const char *const string, id_type_t *const type,
540     struct parse_error **const parse_error)
541 {
542 	/*
543 	 * Special case for "any", as the canonical form for IT_ANY in
544 	 * id_type_to_str[] is "*".
545 	 */
546 	if (strcmp(string, "any") == 0) {
547 		*type = IT_ANY;
548 		return (0);
549 	}
550 
551 	/* Start at 1 to avoid parsing "invalid". */
552 	for (size_t i = 1; i <= IT_LAST; ++i) {
553 		if (strcmp(string, id_type_to_str[i]) == 0) {
554 			*type = i;
555 			return (0);
556 		}
557 	}
558 
559 	*type = IT_INVALID;
560 	make_parse_error(parse_error, 0, "No valid type found.");
561 	return (EINVAL);
562 }
563 
564 static size_t
parse_gid_flags(const char * const string,flags_t * const flags,flags_t * const gid_flags)565 parse_gid_flags(const char *const string, flags_t *const flags,
566     flags_t *const gid_flags)
567 {
568 	switch (string[0]) {
569 	case '+':
570 		*flags |= MDF_SUPP_ALLOW;
571 		goto has_supp_clause;
572 	case '!':
573 		*flags |= MDF_SUPP_MUST;
574 		*gid_flags |= MDF_MAY_REJ_SUPP;
575 		goto has_supp_clause;
576 	case '-':
577 		*flags |= MDF_SUPP_DONT;
578 		*gid_flags |= MDF_MAY_REJ_SUPP;
579 		goto has_supp_clause;
580 	has_supp_clause:
581 		*gid_flags |= MDF_HAS_SUPP_CLAUSE;
582 		return (1);
583 	}
584 
585 	return (0);
586 }
587 
588 static bool
parse_any(const char * const string)589 parse_any(const char *const string)
590 {
591 	return (strcmp(string, "*") == 0 || strcmp(string, "any") == 0);
592 }
593 
594 static bool
has_clauses(const id_nb_t nb,const flags_t type_flags)595 has_clauses(const id_nb_t nb, const flags_t type_flags)
596 {
597 	return ((type_flags & MDF_TYPE_MASK) != 0 || nb != 0);
598 }
599 
600 static int
parse_target_clause(char * to,struct rule * const rule,struct id_list * const uid_list,struct id_list * const gid_list,struct parse_error ** const parse_error)601 parse_target_clause(char *to, struct rule *const rule,
602     struct id_list *const uid_list, struct id_list *const gid_list,
603     struct parse_error **const parse_error)
604 {
605 	const char *const start = to;
606 	char *to_type, *to_id;
607 	const char *p;
608 	struct id_list *list;
609 	id_nb_t *nb;
610 	flags_t *tflags;
611 	struct id_elem *ie;
612 	struct id_spec is = {.flags = 0};
613 	flags_t gid_flags = 0;
614 	id_type_t type;
615 	int error;
616 
617 	MPASS(*parse_error == NULL);
618 	MPASS(to != NULL);
619 	to_type = strsep_noblanks(&to, "=");
620 	MPASS(to_type != NULL);
621 	to_type += parse_gid_flags(to_type, &is.flags, &gid_flags);
622 	error = parse_id_type(to_type, &type, parse_error);
623 	if (error != 0)
624 		goto einval;
625 	if (type != IT_GID && is.flags != 0) {
626 		make_parse_error(parse_error, to_type - start,
627 		    "Expected type 'gid' after flags, not '%s'.",
628 		    to_type);
629 		goto einval;
630 	}
631 
632 	to_id = strsep_noblanks(&to, "");
633 	switch (type) {
634 	case IT_GID:
635 		if (to_id == NULL) {
636 			make_parse_error(parse_error, to_type - start,
637 			    "No '=' and ID specification after type '%s'.",
638 			    to_type);
639 			goto einval;
640 		}
641 
642 		if (is.flags == 0) {
643 			/* No flags: Dealing with a primary group. */
644 			is.flags |= MDF_PRIMARY;
645 			gid_flags |= MDF_HAS_PRIMARY_CLAUSE;
646 		}
647 
648 		list = gid_list;
649 		nb = &rule->gids_nb;
650 		tflags = &rule->gid_flags;
651 
652 		/* "*" or "any"? */
653 		if (parse_any(to_id)) {
654 			/*
655 			 * We check that we have not seen any other clause of
656 			 * the same category (i.e., concerning primary or
657 			 * supplementary groups).
658 			 */
659 			if ((is.flags & MDF_PRIMARY) != 0) {
660 				if ((*tflags & MDF_HAS_PRIMARY_CLAUSE) != 0) {
661 					make_parse_error(parse_error,
662 					    to_id - start,
663 					    "'any' specified after another "
664 					    "(primary) GID.");
665 					goto einval;
666 				}
667 				*tflags |= gid_flags | MDF_ANY;
668 			} else {
669 				/*
670 				 * If a supplementary group flag was present, it
671 				 * must be MDF_SUPP_ALLOW ("+").
672 				 */
673 				if ((is.flags & MDF_SUPP_MASK) != MDF_SUPP_ALLOW) {
674 					make_parse_error(parse_error,
675 					    to_id - start,
676 					    "'any' specified with another "
677 					    "flag than '+'.");
678 					goto einval;
679 				}
680 				if ((*tflags & MDF_HAS_SUPP_CLAUSE) != 0) {
681 					make_parse_error(parse_error,
682 					    to_id - start,
683 					    "'any' with flag '+' specified after "
684 					    "another (supplementary) GID.");
685 					goto einval;
686 				}
687 				*tflags |= gid_flags | MDF_ANY_SUPP;
688 			}
689 			goto check_type_and_finish;
690 		} else {
691 			/*
692 			 * Check that we haven't already seen "any" for the same
693 			 * category.
694 			 */
695 			if ((is.flags & MDF_PRIMARY) != 0) {
696 				if ((*tflags & MDF_ANY) != 0) {
697 					make_parse_error(parse_error,
698 					    to_id - start,
699 					    "Some (primary) GID specified after "
700 					    "'any'.");
701 					goto einval;
702 				}
703 			} else if ((*tflags & MDF_ANY_SUPP) != 0 &&
704 			    (is.flags & MDF_SUPP_ALLOW) != 0) {
705 				make_parse_error(parse_error,
706 				    to_id - start,
707 				    "Some (supplementary) GID specified after "
708 				    "'any' with flag '+'.");
709 				goto einval;
710 			}
711 			*tflags |= gid_flags;
712 		}
713 		break;
714 
715 	case IT_UID:
716 		if (to_id == NULL) {
717 			make_parse_error(parse_error, to_type - start,
718 			    "No '=' and ID specification after type '%s'.",
719 			    to_type);
720 			goto einval;
721 		}
722 
723 		list = uid_list;
724 		nb = &rule->uids_nb;
725 		tflags = &rule->uid_flags;
726 
727 		/* "*" or "any"? */
728 		if (parse_any(to_id)) {
729 			/* There must not be any other clause. */
730 			if (has_clauses(*nb, *tflags)) {
731 				make_parse_error(parse_error, to_id - start,
732 				    "'any' specified after another UID.");
733 				goto einval;
734 			}
735 			*tflags |= MDF_ANY;
736 			goto check_type_and_finish;
737 		} else {
738 			/*
739 			 * Check that we haven't already seen "any" for the same
740 			 * category.
741 			 */
742 			if ((*tflags & MDF_ANY) != 0) {
743 				make_parse_error(parse_error, to_id - start,
744 				    "Some UID specified after 'any'.");
745 				goto einval;
746 			}
747 		}
748 		break;
749 
750 	case IT_ANY:
751 		/* No ID allowed. */
752 		if (to_id != NULL) {
753 			make_parse_error(parse_error, to_type - start,
754 			    "No '=' and ID allowed after type '%s'.", to_type);
755 			goto einval;
756 		}
757 		/*
758 		 * We can't have IT_ANY after any other IT_*, it must be the
759 		 * only one.
760 		 */
761 		if (has_clauses(rule->uids_nb, rule->uid_flags) ||
762 		    has_clauses(rule->gids_nb, rule->gid_flags)) {
763 			make_parse_error(parse_error, to_type - start,
764 			    "Target clause of type '%s' coming after another "
765 			    "clause (must be alone).", to_type);
766 			goto einval;
767 		}
768 		rule->uid_flags |= MDF_ANY;
769 		rule->gid_flags |= MDF_ANY | MDF_ANY_SUPP |
770 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
771 		goto finish;
772 
773 	default:
774 		/* parse_id_type() returns no other types currently. */
775 		__assert_unreachable();
776 	}
777 
778 	/* Rule out cases that have been treated above. */
779 	MPASS((type == IT_UID || type == IT_GID) && !parse_any(to_id));
780 
781 	/* "."? */
782 	if (strcmp(to_id, ".") == 0) {
783 		if ((*tflags & MDF_CURRENT) != 0) {
784 			/* Duplicate "." <id>.  Try to coalesce. */
785 			error = coalesce_id_flags(is.flags, tflags);
786 			if (error != 0) {
787 				make_parse_error(parse_error, to_id - start,
788 				    "Incompatible flags with prior clause "
789 				    "with same target.");
790 				goto einval;
791 			}
792 		} else
793 			*tflags |= MDF_CURRENT | is.flags;
794 		goto check_type_and_finish;
795 	}
796 
797 	/* Parse an ID. */
798 	error = strtoui_strict(to_id, &p, 10, &is.id);
799 	if (error != 0 || *p != '\0') {
800 		make_parse_error(parse_error, to_id - start,
801 		    "Cannot parse a numerical ID (base 10).");
802 		goto einval;
803 	}
804 
805 	/* Explicit ID flags. */
806 	if (type == IT_GID && (is.flags & MDF_SUPP_MUST) != 0)
807 		*tflags |= MDF_EXPLICIT_SUPP_MUST;
808 
809 	/*
810 	 * We check for duplicate IDs and coalesce their 'struct id_spec' only
811 	 * at end of parse_single_rule() because it is much more performant then
812 	 * (using sorted arrays).
813 	 */
814 	++*nb;
815 	if (*nb == 0) {
816 		make_parse_error(parse_error, 0,
817 		    "Too many target clauses of type '%s'.", to_type);
818 		return (EOVERFLOW);
819 	}
820 	ie = malloc(sizeof(*ie), M_MAC_DO, M_WAITOK);
821 	ie->spec = is;
822 	STAILQ_INSERT_TAIL(list, ie, ie_entries);
823 	check_type_and_id_spec(type, &is);
824 check_type_and_finish:
825 	check_type_and_type_flags(type, *tflags);
826 finish:
827 	MPASS(error == 0 && *parse_error == NULL);
828 	return (0);
829 einval:
830 	/* We must have built a parse error on error. */
831 	MPASS(*parse_error != NULL);
832 	return (EINVAL);
833 }
834 
835 static int
u_int_cmp(const u_int i1,const u_int i2)836 u_int_cmp(const u_int i1, const u_int i2)
837 {
838 	return ((i1 > i2) - (i1 < i2));
839 }
840 
841 static int
id_spec_cmp(const void * const p1,const void * const p2)842 id_spec_cmp(const void *const p1, const void *const p2)
843 {
844 	const struct id_spec *const is1 = p1;
845 	const struct id_spec *const is2 = p2;
846 
847 	return (u_int_cmp(is1->id, is2->id));
848 }
849 
850 /*
851  * Transfer content of 'list' into 'array', freeing and emptying list.
852  *
853  * 'nb' must be 'list''s length and not be greater than 'array''s size.  The
854  * destination array is sorted by ID.  Structures 'struct id_spec' with same IDs
855  * are coalesced if that makes sense (not including duplicate clauses), else
856  * EINVAL is returned.  On success, 'nb' is updated (lowered) to account for
857  * coalesced specifications.  The parameter 'type' is only for testing purposes
858  * (INVARIANTS).
859  */
860 static int
pour_list_into_rule(const id_type_t type,struct id_list * const list,struct id_spec * const array,id_nb_t * const nb,struct parse_error ** const parse_error)861 pour_list_into_rule(const id_type_t type, struct id_list *const list,
862     struct id_spec *const array, id_nb_t *const nb,
863     struct parse_error **const parse_error)
864 {
865 	struct id_elem *ie, *ie_next;
866 	size_t idx = 0;
867 
868 	/* Fill the array. */
869 	STAILQ_FOREACH_SAFE(ie, list, ie_entries, ie_next) {
870 		MPASS(idx < *nb);
871 		array[idx] = ie->spec;
872 		free(ie, M_MAC_DO);
873 		++idx;
874 	}
875 	MPASS(idx == *nb);
876 	STAILQ_INIT(list);
877 
878 	/* Sort it (by ID). */
879 	qsort(array, *nb, sizeof(*array), id_spec_cmp);
880 
881 	/* Coalesce same IDs. */
882 	if (*nb != 0) {
883 		size_t ref_idx = 0;
884 
885 		for (idx = 1; idx < *nb; ++idx) {
886 			const u_int id = array[idx].id;
887 
888 			if (id != array[ref_idx].id) {
889 				++ref_idx;
890 				if (ref_idx != idx)
891 					array[ref_idx] = array[idx];
892 				continue;
893 			}
894 
895 			switch (type) {
896 				int error;
897 
898 			case IT_GID:
899 				error = coalesce_id_flags(array[idx].flags,
900 				    &array[ref_idx].flags);
901 				if (error != 0) {
902 					make_parse_error(parse_error, 0,
903 					    "Incompatible flags or duplicate "
904 					    "GID %u.", id);
905 					goto einval;
906 				}
907 				check_type_and_id_flags(type,
908 				    array[ref_idx].flags);
909 				break;
910 
911 			case IT_UID:
912 				/*
913 				 * No flags in this case.  Multiple appearances
914 				 * of the same UID is an exact redundancy, so
915 				 * error out.
916 				 */
917 				make_parse_error(parse_error, 0,
918 				    "Duplicate UID %u.", id);
919 				goto einval;
920 
921 			default:
922 				__assert_unreachable();
923 			}
924 		}
925 		*nb = ref_idx + 1;
926 	}
927 
928 	MPASS(*parse_error == NULL);
929 	return (0);
930 
931 einval:
932 	MPASS(*parse_error != NULL);
933 	return (EINVAL);
934 }
935 
936 /*
937  * See also the herald comment for parse_rules() below.
938  *
939  * The second part of a rule, called <target> (or <to>), is a comma-separated
940  * (',') list of '<flags><type>=<id>' clauses similar to that of the <from>
941  * part, with the extensions that <id> may also be "*" or "any" or ".", and that
942  * <flags> may contain at most one of the '+', '-' and '!' characters when
943  * <type> is "gid" (no flags are allowed for "uid").  No two clauses in a single
944  * <to> list may list the same <id>.  "*" and "any" both designate any ID for
945  * the <type>, and are aliases to each other.  In front of "any" (or "*"), only
946  * the '+' flag is allowed (in the "gid" case).  "." designates the process'
947  * current IDs for the <type>.  The precise meaning of flags and "." is
948  * explained in functions checking privileges below.
949  */
950 static int
parse_single_rule(char * rule,struct rules * const rules,struct parse_error ** const parse_error)951 parse_single_rule(char *rule, struct rules *const rules,
952     struct parse_error **const parse_error)
953 {
954 	const char *const start = rule;
955 	const char *from_type, *from_id, *p;
956 	char *to_list;
957 	struct id_list uid_list, gid_list;
958 	struct id_elem *ie, *ie_next;
959 	struct rule *new;
960 	int error;
961 
962 	MPASS(*parse_error == NULL);
963 	STAILQ_INIT(&uid_list);
964 	STAILQ_INIT(&gid_list);
965 
966 	/* Freed when the 'struct rules' container is freed. */
967 	new = malloc(sizeof(*new), M_MAC_DO, M_WAITOK | M_ZERO);
968 
969 	from_type = strsep_noblanks(&rule, "=");
970 	MPASS(from_type != NULL); /* Because 'rule' was not NULL. */
971 	error = parse_id_type(from_type, &new->from_type, parse_error);
972 	if (error != 0)
973 		goto einval;
974 	switch (new->from_type) {
975 	case IT_UID:
976 	case IT_GID:
977 		break;
978 	default:
979 		make_parse_error(parse_error, 0, "Type '%s' not allowed in "
980 		    "the \"from\" part of rules.");
981 		goto einval;
982 	}
983 
984 	from_id = strsep_noblanks(&rule, ":>");
985 	if (is_null_or_empty(from_id)) {
986 		make_parse_error(parse_error, 0, "No ID specified.");
987 		goto einval;
988 	}
989 
990 	error = strtoui_strict(from_id, &p, 10, &new->from_id);
991 	if (error != 0 || *p != '\0') {
992 		make_parse_error(parse_error, from_id - start,
993 		    "Cannot parse a numerical ID (base 10).");
994 		goto einval;
995 	}
996 
997 	/*
998 	 * We will now parse the "to" list.
999 	 *
1000 	 * In order to ease parsing, we will begin by building lists of target
1001 	 * UIDs and GIDs in local variables 'uid_list' and 'gid_list'.  The
1002 	 * number of each type of IDs will be filled directly in 'new'.  At end
1003 	 * of parse, we will allocate both arrays of IDs to be placed into the
1004 	 * 'uids' and 'gids' members, sort them, and discard the tail queues
1005 	 * used to build them.  This conversion to sorted arrays at end of parse
1006 	 * allows to minimize memory allocations and enables searching IDs in
1007 	 * O(log(n)) instead of linearly.
1008 	 */
1009 	to_list = strsep_noblanks(&rule, ",");
1010 	if (to_list == NULL) {
1011 		make_parse_error(parse_error, 0, "No target list.");
1012 		goto einval;
1013 	}
1014 	do {
1015 		error = parse_target_clause(to_list, new, &uid_list, &gid_list,
1016 		    parse_error);
1017 		if (error != 0) {
1018 			(*parse_error)->pos += to_list - start;
1019 			goto einval;
1020 		}
1021 
1022 		to_list = strsep_noblanks(&rule, ",");
1023 	} while (to_list != NULL);
1024 
1025 	if (new->uids_nb != 0) {
1026 		new->uids = malloc(sizeof(*new->uids) * new->uids_nb, M_MAC_DO,
1027 		    M_WAITOK);
1028 		error = pour_list_into_rule(IT_UID, &uid_list, new->uids,
1029 		    &new->uids_nb, parse_error);
1030 		if (error != 0)
1031 			goto einval;
1032 	}
1033 	MPASS(STAILQ_EMPTY(&uid_list));
1034 	if (!has_clauses(new->uids_nb, new->uid_flags)) {
1035 		/* No UID specified, default is "uid=.". */
1036 		MPASS(new->uid_flags == 0);
1037 		new->uid_flags = MDF_CURRENT;
1038 		check_type_and_type_flags(IT_UID, new->uid_flags);
1039 	}
1040 
1041 	if (new->gids_nb != 0) {
1042 		new->gids = malloc(sizeof(*new->gids) * new->gids_nb, M_MAC_DO,
1043 		    M_WAITOK);
1044 		error = pour_list_into_rule(IT_GID, &gid_list, new->gids,
1045 		    &new->gids_nb, parse_error);
1046 		if (error != 0)
1047 			goto einval;
1048 	}
1049 	MPASS(STAILQ_EMPTY(&gid_list));
1050 	if (!has_clauses(new->gids_nb, new->gid_flags)) {
1051 		/* No GID specified, default is "gid=.,!gid=.". */
1052 		MPASS(new->gid_flags == 0);
1053 		new->gid_flags = MDF_CURRENT | MDF_PRIMARY | MDF_SUPP_MUST |
1054 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
1055 		check_type_and_type_flags(IT_GID, new->gid_flags);
1056 	}
1057 
1058 	STAILQ_INSERT_TAIL(&rules->head, new, r_entries);
1059 	MPASS(error == 0 && *parse_error == NULL);
1060 	return (0);
1061 
1062 einval:
1063 	free(new->gids, M_MAC_DO);
1064 	free(new->uids, M_MAC_DO);
1065 	free(new, M_MAC_DO);
1066 	STAILQ_FOREACH_SAFE(ie, &gid_list, ie_entries, ie_next)
1067 	    free(ie, M_MAC_DO);
1068 	STAILQ_FOREACH_SAFE(ie, &uid_list, ie_entries, ie_next)
1069 	    free(ie, M_MAC_DO);
1070 	MPASS(*parse_error != NULL);
1071 	return (EINVAL);
1072 }
1073 
1074 /*
1075  * Parse rules specification and produce rule structures out of it.
1076  *
1077  * Must be called with '*parse_error' set to NULL.  Returns 0 on success,
1078  * filling the passed '*rules' with 'struct rule' objects.  On error, the
1079  * returned value is non-zero, and '*rules' may have been changed.  If 'string'
1080  * has length greater or equal to MAX_RULE_STRING_SIZE, ENAMETOOLONG is
1081  * returned.  If it is not in the expected format, EINVAL is returned.  If an
1082  * error is returned, '*parse_error' is set to point to a 'struct parse_error'
1083  * giving an error message for the problem.
1084  *
1085  * Expected format: A >-colon-separated list of rules of the form
1086  * "<from>><target>" (for backwards compatibility, a semi-colon ":" is accepted
1087  * in place of '>').  The <from> part is of the form "<type>=<id>" where <type>
1088  * is "uid" or "gid", <id> an UID or GID (depending on <type>) and <target> is
1089  * "*", "any" or a comma-separated list of '<flags><type>=<id>' clauses (see the
1090  * comment for parse_single_rule() for more details).  For convenience, empty
1091  * rules are allowed (and do nothing), and spaces and tabs are allowed (and
1092  * removed) around each token (tokens are natural ones, except that
1093  * '<flags><type>' as a whole is considered a single token, so no blanks are
1094  * allowed between '<flags>' and '<type>').
1095  *
1096  * Examples:
1097  * - "uid=1001>uid=1010,gid=1010;uid=1002>any"
1098  * - "gid=1010>gid=1011,gid=1012,gid=1013"
1099  */
1100 static int
parse_rules(const char * const string,struct rules * const rules,struct parse_error ** const parse_error)1101 parse_rules(const char *const string, struct rules *const rules,
1102     struct parse_error **const parse_error)
1103 {
1104 	const size_t len = strlen(string);
1105 	char *copy, *p, *rule;
1106 	int error = 0;
1107 
1108 	if (len >= MAX_RULE_STRING_SIZE) {
1109 		make_parse_error(parse_error, 0,
1110 		    "Rule specification string is too long (%zu, max %zu)",
1111 		    len, MAX_RULE_STRING_SIZE - 1);
1112 		return (ENAMETOOLONG);
1113 	}
1114 
1115 	bcopy(string, rules->string, len + 1);
1116 	MPASS(rules->string[len] == '\0'); /* Catch some races. */
1117 
1118 	copy = malloc(len + 1, M_MAC_DO, M_WAITOK);
1119 	bcopy(string, copy, len + 1);
1120 	MPASS(copy[len] == '\0'); /* Catch some races. */
1121 
1122 	p = copy;
1123 	while ((rule = strsep_noblanks(&p, ";")) != NULL) {
1124 		if (rule[0] == '\0')
1125 			continue;
1126 		error = parse_single_rule(rule, rules, parse_error);
1127 		if (error != 0) {
1128 			(*parse_error)->pos += rule - copy;
1129 			goto error;
1130 		}
1131 	}
1132 
1133 	MPASS(error == 0 && *parse_error == NULL);
1134 out:
1135 	free(copy, M_MAC_DO);
1136 	return (error);
1137 error:
1138 	MPASS(error != 0 && *parse_error != NULL);
1139 	goto out;
1140 }
1141 
1142 /*
1143  * Similar constraints as parse_rules() (which see).
1144  */
1145 static int
parse_exec_paths(const char * const string,struct exec_paths * const exec_paths,struct parse_error ** const parse_error)1146 parse_exec_paths(const char *const string, struct exec_paths *const exec_paths,
1147     struct parse_error **const parse_error)
1148 {
1149 	const size_t len = strlen(string);
1150 	char *copy, *p, *path;
1151 	int error = 0;
1152 
1153 	if (len >= MAX_EXEC_PATHS_SIZE) {
1154 		make_parse_error(parse_error, 0,
1155 		    "Exec path specification string is too long (%zu, max %u)",
1156 		    len, MAX_EXEC_PATHS_SIZE - 1);
1157 		return (ENAMETOOLONG);
1158 	}
1159 
1160 	bcopy(string, exec_paths->exec_paths_str, len + 1);
1161 	MPASS(exec_paths->exec_paths_str[len] == '\0');
1162 
1163 	copy = malloc(len + 1, M_MAC_DO, M_WAITOK);
1164 	bcopy(string, copy, len + 1);
1165 	MPASS(copy[len] == '\0');
1166 
1167 	p = copy;
1168 	while ((path = strsep(&p, ":")) != NULL) {
1169 		size_t path_len;
1170 
1171 		if (*path == '\0')
1172 			continue;
1173 
1174 		if (exec_paths->exec_path_count >= MAX_EXEC_PATHS) {
1175 			make_parse_error(parse_error, path - copy,
1176 			    "Too many exec paths specified (max %d)",
1177 			    MAX_EXEC_PATHS);
1178 			error = EINVAL;
1179 			goto error;
1180 		}
1181 
1182 		path_len = strlen(path);
1183 		if (path_len >= PATH_MAX) {
1184 			make_parse_error(parse_error, path - copy,
1185 			    "Exec paths too long (%zu, max %u)",
1186 			    path_len, PATH_MAX - 1);
1187 			error = ENAMETOOLONG;
1188 			goto error;
1189 		}
1190 
1191 		strlcpy(exec_paths->exec_paths[exec_paths->exec_path_count],
1192 		    path, PATH_MAX);
1193 		exec_paths->exec_path_count++;
1194 	}
1195 
1196 	MPASS(error == 0 && *parse_error == NULL);
1197 out:
1198 	free(copy, M_MAC_DO);
1199 	return (error);
1200 error:
1201 	MPASS(error != 0 && *parse_error != NULL);
1202 	goto out;
1203 }
1204 
1205 static void
hold_conf(struct conf * const conf)1206 hold_conf(struct conf *const conf)
1207 {
1208 	int old_count __diagused = refcount_acquire(&conf->use_count);
1209 
1210 	KASSERT(old_count != 0,
1211 	    ("MAC/do: Trying to resurrect a destroyed configuration."));
1212 }
1213 
1214 static void
drop_conf(struct conf * const conf)1215 drop_conf(struct conf *const conf)
1216 {
1217 	if (refcount_release(&conf->use_count)) {
1218 		toast_rules(&conf->rules);
1219 		free(conf, M_MAC_DO);
1220 	}
1221 }
1222 
1223 /*
1224  * Find configuration applicable to the passed prison.
1225  *
1226  * Returns the applicable configuration (which always exists), with an
1227  * additional reference that must be freed by the caller.  'pr' must not be
1228  * locked.
1229  *
1230  * The applicable configuration is that of the closest ancestor prison
1231  * (including itself) of the passed prison that actually has a 'struct conf'
1232  * associated to it.
1233  *
1234  * If 'hpr' is not NULL, it is used to return a pointer to the (unlocked) prison
1235  * holding the applicable configuration.
1236  *
1237  * The find_conf_unlocked() variant needs 'mac_do_rml' to be (read- or write-)
1238  * locked.  The find_conf() variant will take a read lock for the duration of
1239  * the search.
1240  *
1241  * The configuration returned by this function is sequentially consistent with
1242  * other concurrent reads and configuration modifications, even in the presence
1243  * of concurrent changes of configurations higher up in the jail tree (whether
1244  * they "change" the value of some parameters, install a new configuration where
1245  * there wasn't any, breaking inheritance from higher up, or remove an existing
1246  * one, establishing inheritance from higher up).
1247  */
1248 static struct conf *
find_conf_locked(struct prison * const pr,struct prison ** const hpr)1249 find_conf_locked(struct prison *const pr, struct prison **const hpr)
1250 {
1251 	struct prison *cpr, *ppr; /* Current and parent. */
1252 	struct conf *conf;
1253 
1254 	rm_assert(&mac_do_rml, RA_LOCKED);
1255 	/*
1256 	 * We do not need to take any locks here to climb the prison tree as
1257 	 * either the start prison ('pr') is that of the current thread (and our
1258 	 * ancestors are necessarily stable), or it is a prison passed by the jail
1259 	 * machinery to an OSD method, in which case the prison tree lock is
1260 	 * already being held.
1261 	 */
1262 	cpr = pr;
1263 	for (;;) {
1264 		conf = osd_jail_get_unlocked(cpr, osd_jail_slot);
1265 		if (conf != NULL)
1266 			break;
1267 
1268 		ppr = cpr->pr_parent;
1269 		/*
1270 		 * 'prison0' always has a mac_do(4) configuration because we
1271 		 * installed one on module load/activation and nothing can
1272 		 * destroy it as 'prison0' is not a regular jail and the
1273 		 * 'mac.do' parameter cannot be set to 'inherit' on it, which is
1274 		 * the only way to clear an existing configuration.
1275 		 */
1276 		KASSERT(ppr != NULL,
1277 		    ("MAC/do: 'prison0' must always have a configuration."));
1278 		cpr = ppr;
1279 	}
1280 
1281 	hold_conf(conf);
1282 	if (hpr != NULL)
1283 		*hpr = cpr;
1284 	return (conf);
1285 }
1286 
1287 static struct conf *
find_conf(struct prison * const pr,struct prison ** const hpr)1288 find_conf(struct prison *const pr, struct prison **const hpr)
1289 {
1290 	struct conf *conf;
1291 	struct rm_priotracker rmpt;
1292 
1293 	rm_rlock(&mac_do_rml, &rmpt);
1294 	conf = find_conf_locked(pr, hpr);
1295 	rm_runlock(&mac_do_rml, &rmpt);
1296 	return (conf);
1297 }
1298 
1299 #ifdef INVARIANTS
1300 static void
check_conf_use_count(const struct conf * const conf,u_int expected)1301 check_conf_use_count(const struct conf *const conf, u_int expected)
1302 {
1303 	const u_int use_count = refcount_load(&conf->use_count);
1304 
1305 	if (use_count != expected)
1306 		panic("MAC/do: Configuration at %p: Use count is %u, "
1307 		    "expected %u", conf, use_count, expected);
1308 }
1309 #else
1310 #define check_conf_use_count(...)
1311 #endif /* INVARIANTS */
1312 
1313 /*
1314  * OSD destructor for slot 'osd_jail_slot'.
1315  *
1316  * Called with 'value' not NULL.  We have arranged that it is only ever called
1317  * when the corresponding jail goes down or at module unload.
1318  */
1319 static void
dealloc_jail_osd(void * const value)1320 dealloc_jail_osd(void *const value)
1321 {
1322 	struct conf *const conf = value;
1323 
1324 	/*
1325 	 * If called because the "holding" jail goes down, no one should be
1326 	 * using the rules but us at this point because no threads of that jail
1327 	 * (or its sub-jails) should currently be executing (in particular,
1328 	 * currently executing setcred()).  The case of module unload is more
1329 	 * complex.  Although the MAC framework takes care that no hook is
1330 	 * called while a module is unloading, the unload could happen between
1331 	 * two calls to MAC hooks in the course of, e.g., executing setcred(),
1332 	 * where the rules' reference count has been bumped to keep them alive
1333 	 * even if the rules on the "holding" jail has been concurrently
1334 	 * changed.  These other references are held in our thread OSD slot, so
1335 	 * we ensure that all thread's slots are freed first in mac_do_destroy()
1336 	 * to be able to check that only one reference remains.
1337 	 */
1338 	check_conf_use_count(conf, 1);
1339 	drop_conf(conf);
1340 }
1341 
1342 /*
1343  * Sets a mac_do(4) configuration on a jail.
1344  *
1345  * 'conf' is the new conf to set (can be NULL), and an additional reference will
1346  * be taken on it to represent the jail holding it (if not NULL).  'rsv' must
1347  * have been allocated through osd_reserve() (if 'conf' is not NULL; else can
1348  * be NULL).
1349  *
1350  * The previous configuration on the jail (or NULL) is returned (with an
1351  * associated reference if not NULL).
1352  */
1353 static struct conf *
set_conf_locked(struct prison * const pr,struct conf * const conf,void ** const rsv)1354 set_conf_locked(struct prison *const pr, struct conf *const conf,
1355     void **const rsv)
1356 {
1357 	struct conf *old_conf;
1358 	int error __diagused;
1359 
1360 	KASSERT(conf == NULL || rsv != NULL,
1361 	    ("MAC/do: OSD reserve needed to avoid allocating memory"));
1362 	rm_assert(&mac_do_rml, RA_WLOCKED);
1363 
1364 	if (conf != NULL)
1365 		hold_conf(conf);
1366 	old_conf = osd_jail_get_unlocked(pr, osd_jail_slot);
1367 	error = osd_jail_set_reserved(pr, osd_jail_slot, rsv, conf);
1368 	KASSERT(error == 0, ("MAC/do: osd_jail_set_reserved() failed "
1369 	    "with 'conf' = %p and 'rsv' = %p", conf, rsv));
1370 	if (conf == NULL)
1371 		/*
1372 		 * This completely frees the OSD slot, but doesn't call the
1373 		 * destructor since we've just put NULL into the slot.
1374 		 */
1375 		osd_jail_del(pr, osd_jail_slot);
1376 	return (old_conf);
1377 }
1378 
1379 /*
1380  * Immediately replace the jail's configuration.
1381  *
1382  * To be used only if the configuration to set does not depend in any way on the
1383  * currently applicable configuration.
1384  *
1385  * Takes care of write-locking 'mac_do_rml', which should be unlocked on entry
1386  * and will be unlocked on exit.
1387  */
1388 static void
set_conf(struct prison * const pr,struct conf * const conf)1389 set_conf(struct prison *const pr, struct conf *const conf)
1390 {
1391 	void **const rsv = conf != NULL ? osd_reserve(osd_jail_slot) : NULL;
1392 	struct conf *old_conf;
1393 
1394 	rm_wlock(&mac_do_rml);
1395 	old_conf = set_conf_locked(pr, conf, rsv);
1396 	rm_wunlock(&mac_do_rml);
1397 	if (old_conf != NULL)
1398 		drop_conf(old_conf);
1399 }
1400 
1401 /*
1402  * Remove the rules specifically associated to a prison.
1403  *
1404  * In practice, this means that the rules become inherited (from the closest
1405  * ancestor that has some).
1406  *
1407  * Destroys the 'osd_jail_slot' slot of the passed jail.
1408  */
1409 static struct conf *
remove_conf_locked(struct prison * const pr)1410 remove_conf_locked(struct prison *const pr)
1411 {
1412 	return (set_conf_locked(pr, NULL, NULL));
1413 }
1414 
1415 static struct conf *
new_default_conf(void)1416 new_default_conf(void)
1417 {
1418 	const char *const mdo_path = "/usr/bin/mdo";
1419 	struct conf *conf = new_conf();
1420 
1421 	strlcpy(conf->exec_paths.exec_paths_str, mdo_path,
1422 	    MAX_EXEC_PATHS_SIZE);
1423 	strlcpy(conf->exec_paths.exec_paths[0], mdo_path,
1424 	    PATH_MAX);
1425 	conf->exec_paths.exec_path_count = 1;
1426 
1427 	return (conf);
1428 }
1429 
1430 static void
clone_rules(struct rules * const dst,const struct rules * const src)1431 clone_rules(struct rules *const dst, const struct rules *const src)
1432 {
1433 	const struct rule *src_rule;
1434 
1435 	strlcpy(dst->string, src->string, sizeof(dst->string));
1436 
1437 	STAILQ_FOREACH(src_rule, &src->head, r_entries) {
1438 		struct rule *const dst_rule = malloc(sizeof(*dst_rule),
1439 		    M_MAC_DO, M_WAITOK);
1440 		bcopy(src_rule, dst_rule, sizeof(*dst_rule));
1441 
1442 		if (src_rule->uids_nb > 0) {
1443 			const size_t uids_size = sizeof(*dst_rule->uids) *
1444 			    src_rule->uids_nb;
1445 
1446 			dst_rule->uids = malloc(uids_size, M_MAC_DO, M_WAITOK);
1447 			bcopy(src_rule->uids, dst_rule->uids, uids_size);
1448 		}
1449 
1450 		if (src_rule->gids_nb > 0) {
1451 			const size_t gids_size = sizeof(*dst_rule->gids) *
1452 			    src_rule->gids_nb;
1453 
1454 			dst_rule->gids = malloc(gids_size, M_MAC_DO, M_WAITOK);
1455 			bcopy(src_rule->gids, dst_rule->gids, gids_size);
1456 		}
1457 
1458 		STAILQ_INSERT_TAIL(&dst->head, dst_rule, r_entries);
1459 	}
1460 }
1461 
1462 static void
clone_exec_paths(struct exec_paths * const dst,const struct exec_paths * const src)1463 clone_exec_paths(struct exec_paths *const dst,
1464     const struct exec_paths *const src)
1465 {
1466 	MPASS(is_zeroed(dst, sizeof(*dst)));
1467 	dst->exec_path_count = src->exec_path_count;
1468 	for (int i = 0; i < src->exec_path_count; i++)
1469 		strlcpy(dst->exec_paths[i], src->exec_paths[i],
1470 		    sizeof(dst->exec_paths[i]));
1471 
1472 	strlcpy(dst->exec_paths_str, src->exec_paths_str,
1473 	    sizeof(dst->exec_paths_str));
1474 }
1475 
1476 /*
1477  * Sets/modifies the MAC/do configuration for a jail.
1478  *
1479  * Must be called with '*parse_error' set to NULL.
1480  *
1481  * Supports explicitly setting all parameters or only some of them.  An
1482  * unspecified parameter must be passed as NULL.  The values of unspecified
1483  * parameters are copied from those of the passed model configuration (which is
1484  * expected to be the currently applicable configuration, i.e., that of the
1485  * closest ancestor jail that has one).
1486  *
1487  * 'mac_do_rml' needs to be write-locked (and stays so). 'old_conf' serves to
1488  * return, on no error, the old configuration with a reference (which must be
1489  * eventually freed).
1490  */
1491 static int
parse_and_set_conf(struct prison * const pr,const char * const rules_string,const char * const exec_paths_string,const struct conf * const model_conf,struct conf ** const old_conf,struct parse_error ** const parse_error)1492 parse_and_set_conf(struct prison *const pr, const char *const rules_string,
1493     const char *const exec_paths_string, const struct conf *const model_conf,
1494     struct conf **const old_conf, struct parse_error **const parse_error)
1495 {
1496 	struct conf *const conf = new_conf();
1497 	int error = 0;
1498 
1499 	KASSERT(model_conf != NULL ||
1500 	    (rules_string != NULL && exec_paths_string != NULL),
1501 	    ("MAC/do: %s: Model configuration needed!", __func__));
1502 
1503 	if (rules_string != NULL) {
1504 		error = parse_rules(rules_string, &conf->rules, parse_error);
1505 		if (error != 0)
1506 			goto error;
1507 	}
1508 	else
1509 		clone_rules(&conf->rules, &model_conf->rules);
1510 
1511 	if (exec_paths_string != NULL) {
1512 		error = parse_exec_paths(exec_paths_string, &conf->exec_paths,
1513 		    parse_error);
1514 		if (error != 0)
1515 			goto error;
1516 	} else
1517 		clone_exec_paths(&conf->exec_paths,
1518 		    &model_conf->exec_paths);
1519 
1520 	MPASS(error == 0);
1521 	*old_conf = set_conf_locked(pr, conf, osd_reserve(osd_jail_slot));
1522 
1523 	MPASS(error == 0 && *parse_error == NULL);
1524 out:
1525 	drop_conf(conf);
1526 	return (error);
1527 error:
1528 	MPASS(error != 0 && *parse_error != NULL);
1529 	goto out;
1530 }
1531 
1532 /*
1533  * Calls parse_and_set_conf() and closes the current configuration transaction.
1534  *
1535  * Closes the transaction by unlocking 'mac_do_rml' and releasing the old
1536  * configuration returned by parse_and_set_conf().
1537  */
1538 static int
parse_and_commit_conf(struct prison * const pr,const char * const rules_string,const char * const exec_paths_string,const struct conf * const model_conf,struct parse_error ** const parse_error)1539 parse_and_commit_conf(struct prison *const pr, const char *const rules_string,
1540     const char *const exec_paths_string, const struct conf *const model_conf,
1541     struct parse_error **const parse_error)
1542 {
1543 	struct conf *old_conf;
1544 	int error;
1545 
1546 	error = parse_and_set_conf(pr, rules_string, exec_paths_string,
1547 	    model_conf, &old_conf, parse_error);
1548 	rm_wunlock(&mac_do_rml);
1549 
1550 	if (error == 0 && old_conf != NULL)
1551 		drop_conf(old_conf);
1552 	return (error);
1553 }
1554 
1555 
1556 static int
mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS)1557 mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS)
1558 {
1559 	char *const buf = malloc(MAX_RULE_STRING_SIZE, M_MAC_DO, M_WAITOK);
1560 	struct prison *const pr = req->td->td_ucred->cr_prison;
1561 	struct conf *conf;
1562 	struct parse_error *parse_error = NULL;
1563 	int error;
1564 
1565 	if (req->newptr != NULL) {
1566 		rm_wlock(&mac_do_rml);
1567 		conf = find_conf_locked(pr, NULL);
1568 	} else
1569 		conf = find_conf(pr, NULL);
1570 	strlcpy(buf, conf->rules.string, MAX_RULE_STRING_SIZE);
1571 
1572 	error = sysctl_handle_string(oidp, buf, MAX_RULE_STRING_SIZE, req);
1573 	if (req->newptr == NULL)
1574 		goto out;
1575 	if (error != 0) {
1576 		rm_wunlock(&mac_do_rml);
1577 		goto out;
1578 	}
1579 
1580 	/* Unlocks 'mac_do_rml'. */
1581 	error = parse_and_commit_conf(pr, buf, NULL, conf, &parse_error);
1582 	if (error != 0) {
1583 		if (print_parse_error)
1584 			printf("MAC/do: Parse error at index %zu: %s\n",
1585 			    parse_error->pos, parse_error->msg);
1586 		free_parse_error(parse_error);
1587 	}
1588 
1589 out:
1590 	drop_conf(conf);
1591 	free(buf, M_MAC_DO);
1592 	return (error);
1593 }
1594 
1595 SYSCTL_PROC(_security_mac_do, OID_AUTO, rules,
1596     CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON|CTLFLAG_MPSAFE,
1597     0, 0, mac_do_sysctl_rules, "A",
1598     "Rules");
1599 
1600 
1601 SYSCTL_JAIL_PARAM_SYS_SUBNODE(mac, do, CTLFLAG_RW, "Jail MAC/do parameters");
1602 SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAX_RULE_STRING_SIZE,
1603     "Jail MAC/do rules");
1604 
1605 static int
mac_do_sysctl_exec_paths(SYSCTL_HANDLER_ARGS)1606 mac_do_sysctl_exec_paths(SYSCTL_HANDLER_ARGS)
1607 {
1608 	char *const buf = malloc(MAX_EXEC_PATHS_SIZE, M_MAC_DO, M_WAITOK);
1609 	struct prison *const pr = req->td->td_ucred->cr_prison;
1610 	struct conf *conf;
1611 	struct parse_error *parse_error = NULL;
1612 	int error;
1613 
1614 	if (req->newptr != NULL) {
1615 		rm_wlock(&mac_do_rml);
1616 		conf = find_conf_locked(pr, NULL);
1617 	} else
1618 		conf = find_conf(pr, NULL);
1619 	strlcpy(buf, conf->exec_paths.exec_paths_str, MAX_EXEC_PATHS_SIZE);
1620 
1621 	error = sysctl_handle_string(oidp, buf, MAX_EXEC_PATHS_SIZE, req);
1622 	if (req->newptr == NULL)
1623 		goto out;
1624 	if (error != 0) {
1625 		rm_wunlock(&mac_do_rml);
1626 		goto out;
1627 	}
1628 
1629 	/* Unlocks 'mac_do_rml'. */
1630 	error = parse_and_commit_conf(pr, NULL, buf, conf, &parse_error);
1631 	if (error != 0) {
1632 		if (print_parse_error)
1633 			printf("MAC/do: Parse error at index %zu: %s\n",
1634 			    parse_error->pos, parse_error->msg);
1635 		free_parse_error(parse_error);
1636 	}
1637 
1638 out:
1639 	drop_conf(conf);
1640 	free(buf, M_MAC_DO);
1641 	return (error);
1642 }
1643 
1644 SYSCTL_PROC(_security_mac_do, OID_AUTO, exec_paths,
1645     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
1646     0, 0, mac_do_sysctl_exec_paths, "A",
1647     "Colon-separated list of allowed executables");
1648 
1649 SYSCTL_JAIL_PARAM_STRING(_mac_do, exec_paths, CTLFLAG_RW, MAX_EXEC_PATHS_SIZE,
1650     "Jail MAC/do executable paths");
1651 
1652 static int
mac_do_jail_get(void * obj,void * data)1653 mac_do_jail_get(void *obj, void *data)
1654 {
1655 	struct prison *const pr = obj;
1656 	struct vfsoptlist *const opts = data;
1657 	struct prison *hpr_out;
1658 	struct conf *const applicable_conf = find_conf(pr, &hpr_out);
1659 	const struct prison *const hpr = hpr_out;
1660 	const struct rules *const rules = &applicable_conf->rules;
1661 	const struct exec_paths *const exec_paths = &applicable_conf->exec_paths;
1662 	int jsys, error;
1663 
1664 	jsys = hpr == pr ? (has_rules(rules) && has_exec_paths(exec_paths) ?
1665 	    JAIL_SYS_NEW : JAIL_SYS_DISABLE) : JAIL_SYS_INHERIT;
1666 
1667 	error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys));
1668 	if (error != 0 && error != ENOENT)
1669 		goto done;
1670 
1671 	error = vfs_setopts(opts, "mac.do.rules", rules->string);
1672 	if (error != 0 && error != ENOENT)
1673 		goto done;
1674 
1675 	error = vfs_setopts(opts, "mac.do.exec_paths",
1676 	    exec_paths->exec_paths_str);
1677 	if (error != 0 && error != ENOENT)
1678 		goto done;
1679 
1680 	error = 0;
1681 done:
1682 	drop_conf(applicable_conf);
1683 	return (error);
1684 }
1685 
1686 /*
1687  * -1 is used as a sentinel in mac_do_jail_check() and mac_do_jail_set() below.
1688  */
1689 _Static_assert(-1 != JAIL_SYS_DISABLE && -1 != JAIL_SYS_NEW &&
1690     -1 != JAIL_SYS_INHERIT,
1691     "mac_do(4) uses -1 as a sentinel for uninitialized 'jsys'.");
1692 
1693 /*
1694  * We perform only cheap checks here, i.e., we do not really parse the rules
1695  * specification string, if any.
1696  */
1697 static int
mac_do_jail_check(void * obj,void * data)1698 mac_do_jail_check(void *obj, void *data)
1699 {
1700 	struct vfsoptlist *opts = data;
1701 	char *rules_string, *exec_paths_string;
1702 	int error, jsys, rules_size = 0, exec_paths_size = 0;
1703 	bool absent_or_empty_rules, absent_or_empty_exec_paths;
1704 
1705 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1706 	if (error == ENOENT)
1707 		/*
1708 		 * Mark unspecified.  Will fill it up below depending on the
1709 		 * other options.
1710 		 */
1711 		jsys = -1;
1712 	else {
1713 		if (error != 0)
1714 			return (error);
1715 		if (jsys != JAIL_SYS_DISABLE && jsys != JAIL_SYS_NEW &&
1716 		    jsys != JAIL_SYS_INHERIT)
1717 			return (EINVAL);
1718 	}
1719 
1720 	/*
1721 	 * We use vfs_getopt() below instead of vfs_getopts() to get the
1722 	 * string's buffer size.  We perform the additional checks done by the
1723 	 * latter here, even if jail_set() calls vfs_getopts() itself later
1724 	 * (they becoming inconsistent wouldn't cause any security problem).
1725 	 */
1726 
1727 	/* Rules. */
1728 	error = vfs_getopt(opts, "mac.do.rules", (void **)&rules_string,
1729 	    &rules_size);
1730 	if (error == ENOENT)
1731 		rules_string = NULL;
1732 	else {
1733 		if (error != 0)
1734 			return (error);
1735 		if (rules_size == 0 || rules_string[rules_size - 1] != '\0') {
1736 			vfs_opterror(opts,
1737 			    "'mac.do.rules' not a proper string");
1738 			return (EINVAL);
1739 		}
1740 		if (rules_size > MAX_RULE_STRING_SIZE) {
1741 			vfs_opterror(opts, "'mac.do.rules' too long");
1742 			return (ENAMETOOLONG);
1743 		}
1744 	}
1745 
1746 	/* Executable paths. */
1747 	error = vfs_getopt(opts, "mac.do.exec_paths",
1748 	    (void **)&exec_paths_string, &exec_paths_size);
1749 	if (error == ENOENT)
1750 		exec_paths_string = NULL;
1751 	else {
1752 		if (error != 0)
1753 			return (error);
1754 		if (exec_paths_size == 0 ||
1755 		    exec_paths_string[exec_paths_size - 1] != '\0') {
1756 			vfs_opterror(opts,
1757 			    "'mac.do.exec_paths' not a proper string");
1758 			return (EINVAL);
1759 		}
1760 		if (exec_paths_size > MAX_EXEC_PATHS_SIZE) {
1761 			vfs_opterror(opts, "'mac.do.exec_paths' too long");
1762 			return (ENAMETOOLONG);
1763 		}
1764 	}
1765 
1766 	absent_or_empty_rules = is_null_or_empty(rules_string);
1767 	absent_or_empty_exec_paths = is_null_or_empty(exec_paths_string);
1768 
1769 	/* If not specified, infer 'jsys' from passed options. */
1770 	if (jsys == -1) {
1771 		/*
1772 		 * Default in absence of "mac.do.rules" and "mac.do.exec_paths"
1773 		 * is to disable.  We never implicitly inherit, as that changes
1774 		 * reasoning about configurations.
1775 		 */
1776 		if (!absent_or_empty_rules || !absent_or_empty_exec_paths)
1777 			jsys = JAIL_SYS_NEW;
1778 		else
1779 			jsys = JAIL_SYS_DISABLE;
1780 	}
1781 
1782 	/* Final checks based on resolved 'jsys'. */
1783 	switch (jsys) {
1784 	case JAIL_SYS_DISABLE:
1785 		/*
1786 		 * Tolerate specified but empty rules or execution paths
1787 		 * (instead of not being specified).  Also, tolerate that one of
1788 		 * them is not empty (but not both).  Indeed, as soon as one is
1789 		 * empty, mac_do(4) is effectively disabled.  This allows the
1790 		 * administrator to still specify a value for one of them, which
1791 		 * is then used for new sub-jails that do not inherit and for
1792 		 * which no value for the parameter is explicitly specified
1793 		 * (because then the value passed here is copied).
1794 		 */
1795 		if (!absent_or_empty_rules && !absent_or_empty_exec_paths) {
1796 			vfs_opterror(opts,
1797 			    "One of 'mac.do.rules' and 'mac_do.exec_paths' "
1798 			    "should not be specified or should be empty when "
1799 			    "'mac.do' is 'disabled'");
1800 			return (EINVAL);
1801 		}
1802 		break;
1803 
1804 	case JAIL_SYS_INHERIT:
1805 		/*
1806 		 * Canonically, no parameters should be specified in this case.
1807 		 * However, we tolerate empty ones, and also non-empty ones
1808 		 * provided they match the inherited values, so that we can
1809 		 * report the *resolved* value of current parameters via
1810 		 * mac_do_jail_get() and have them re-applicable to this jail in
1811 		 * a similar situation.  Testing that inherited values are the
1812 		 * same as passed ones is more expensive than a single test and
1813 		 * requires some atomicity, which is why we do not perform that
1814 		 * here but only in mac_do_jail_set().
1815 		 */
1816 		break;
1817 	}
1818 
1819 	return (0);
1820 }
1821 
1822 static int
mac_do_jail_set(void * obj,void * data)1823 mac_do_jail_set(void *obj, void *data)
1824 {
1825 	struct prison *const pr = obj;
1826 	struct vfsoptlist *const opts = data;
1827 	char *rules_string, *exec_paths_string;
1828 	struct parse_error *parse_error = NULL;
1829 	struct conf *model_conf;
1830 	int error, jsys;
1831 	bool absent_or_empty_rules, absent_or_empty_exec_paths;
1832 
1833 	/*
1834 	 * The invariants checks used below correspond to what has already been
1835 	 * checked in jail_check() above.
1836 	 */
1837 
1838 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1839 	MPASS(error == 0 || error == ENOENT);
1840 	if (error != 0)
1841 		jsys = -1; /* Mark unfilled. */
1842 
1843 	rules_string = vfs_getopts(opts, "mac.do.rules", &error);
1844 	MPASS(error == 0 || error == ENOENT);
1845 	exec_paths_string = vfs_getopts(opts, "mac.do.exec_paths", &error);
1846 	MPASS(error == 0 || error == ENOENT);
1847 
1848 	absent_or_empty_rules = is_null_or_empty(rules_string);
1849 	absent_or_empty_exec_paths = is_null_or_empty(exec_paths_string);
1850 
1851 	if (jsys == -1) {
1852 		if (!absent_or_empty_rules || !absent_or_empty_exec_paths)
1853 			jsys = JAIL_SYS_NEW;
1854 		else
1855 			jsys = JAIL_SYS_DISABLE;
1856 	}
1857 
1858 	if (jsys == JAIL_SYS_INHERIT) {
1859 		struct conf *old_conf = NULL;
1860 
1861 		error = 0;
1862 		rm_wlock(&mac_do_rml);
1863 
1864 		if (!absent_or_empty_rules || !absent_or_empty_exec_paths) {
1865 			/*
1866 			 * Some values specified.  Check that they match the
1867 			 * ones we are going to inherit.
1868 			 */
1869 			model_conf = find_conf_locked(pr->pr_parent, NULL);
1870 			if (strcmp(model_conf->rules.string, rules_string)
1871 			    != 0) {
1872 				error = EINVAL;
1873 				vfs_opterror(opts,
1874 				    "'mac.do' is 'inherited' but 'mac.do.rules'"
1875 				    " was specified with a different value "
1876 				    "than the one to be inherited (\"%s\")",
1877 				    model_conf->rules.string);
1878 			}
1879 			if (strcmp(model_conf->exec_paths.exec_paths_str,
1880 			    exec_paths_string) != 0) {
1881 				error = EINVAL;
1882 				vfs_opterror(opts,
1883 				    "'mac.do' is 'inherited' but "
1884 				    "'mac.do.exec_paths' was specified with a "
1885 				    "different value than the one to be "
1886 				    "inherited (\"%s\")",
1887 				    model_conf->exec_paths.exec_paths_str);
1888 			}
1889 			drop_conf(model_conf);
1890 		}
1891 
1892 		if (error == 0)
1893 			old_conf = remove_conf_locked(pr);
1894 
1895 		rm_wunlock(&mac_do_rml);
1896 
1897 		if (old_conf != NULL)
1898 			drop_conf(old_conf);
1899 
1900 		return (error);
1901 	}
1902 
1903 	model_conf = NULL;
1904 	/* Freeze configuration accesses. */
1905 	rm_wlock(&mac_do_rml);
1906 
1907 	switch (jsys) {
1908 	case JAIL_SYS_DISABLE:
1909 		/*
1910 		 * mac_do(4) is disabled iff one of the parameter's string is
1911 		 * empty.  The parse_and_commit_conf() call below treats passing
1912 		 * NULL for a parameter as a flag to copy its value from the
1913 		 * relevant ancestor jail's configuration, so we have to watch
1914 		 * for the final result having an empty parameter if no
1915 		 * parameter has been explicitly passed as empty.  Thanks to
1916 		 * mac_do_jail_check(), we know that at least one parameter is
1917 		 * absent or empty (see the comment for the corresponding case
1918 		 * there).
1919 		 */
1920 		MPASS(absent_or_empty_rules || absent_or_empty_exec_paths);
1921 		if (!absent_or_empty_rules)
1922 			exec_paths_string = "";
1923 		else if (!absent_or_empty_exec_paths)
1924 			rules_string = "";
1925 		else {
1926 			/*
1927 			 * Both are either empty or absent.  If at least one is
1928 			 * absent, we retrieve the applicable configuration as
1929 			 * it will serve as a template (provides default
1930 			 * values).
1931 			 */
1932 			if (rules_string == NULL || exec_paths_string == NULL)
1933 				model_conf = find_conf_locked(pr, NULL);
1934 			/* If both are absent, we have to examine if, in the
1935 			 * currently applicable configuration, one of the
1936 			 * parameters, which we are going to copy, is
1937 			 * effectively empty.  If both of those are non-empty,
1938 			 * we keep the executable paths and empty the rules,
1939 			 * since we expect that this is more convenient to
1940 			 * administrators that may want to enable mac_do(4)
1941 			 * later by just setting new rules.
1942 			 */
1943 			if (rules_string == NULL && exec_paths_string == NULL &&
1944 			    has_rules(&model_conf->rules) &&
1945 			    has_exec_paths(&model_conf->exec_paths))
1946 				rules_string = "";
1947 		}
1948 		break;
1949 
1950 	case JAIL_SYS_NEW:
1951 		/* See the comment before the same test above. */
1952 		if (rules_string == NULL || exec_paths_string == NULL)
1953 			model_conf = find_conf_locked(pr, NULL);
1954 		break;
1955 
1956 	default:
1957 		__assert_unreachable();
1958 	}
1959 
1960 	/* Unlocks 'mac_do_rml'. */
1961 	error = parse_and_commit_conf(pr, rules_string, exec_paths_string,
1962 	    model_conf, &parse_error);
1963 	if (model_conf != NULL)
1964 		drop_conf(model_conf);
1965 	if (error != 0) {
1966 		vfs_opterror(opts,
1967 		    "MAC/do: Parse error at index %zu: %s\n",
1968 		    parse_error->pos, parse_error->msg);
1969 		free_parse_error(parse_error);
1970 	}
1971 
1972 	return (error);
1973 }
1974 
1975 /*
1976  * OSD jail methods.
1977  *
1978  * There is no PR_METHOD_REMOVE method, as OSD storage is destroyed by the
1979  * common jail code (see prison_cleanup()), which triggers a run of our
1980  * dealloc_jail_osd() destructor.  There is neither a PR_METHOD_CREATE as
1981  * PR_METHOD_SET is called just after (or the created jail destroyed if some
1982  * PR_METHOD_CREATE fails), and our mac_do_jail_set() will ensure a jail is
1983  * properly configured.
1984  */
1985 static const osd_method_t osd_methods[PR_MAXMETHOD] = {
1986 	[PR_METHOD_GET] = mac_do_jail_get,
1987 	[PR_METHOD_CHECK] = mac_do_jail_check,
1988 	[PR_METHOD_SET] = mac_do_jail_set,
1989 };
1990 
1991 
1992 /*
1993  * Common header structure.
1994  *
1995  * Each structure that is used to pass information between some MAC check
1996  * function and priv_grant() must start with this header.
1997  */
1998 struct mac_do_data_header {
1999 	/* Size of the allocated buffer holding the containing structure. */
2000 	size_t		 allocated_size;
2001 	/* Full size of the containing structure. */
2002 	size_t		 size;
2003 	/*
2004 	 * For convenience, we use privilege numbers as an identifier for the
2005 	 * containing structure's type, since there is one distinct privilege
2006 	 * for each privilege changing function we are supporting.  0 in 'priv'
2007 	 * indicates this header is uninitialized.
2008 	 */
2009 	int		 priv;
2010 	/* The configuration that applies. */
2011 	struct conf	*conf;
2012 };
2013 
2014 /*
2015  * The case of unusable or absent per-thread data can actually happen as nothing
2016  * prevents, e.g., priv_check*() with privilege 'priv' to be called standalone,
2017  * as it is currently by, e.g., the Linux emulator for PRIV_CRED_SETUID.  We
2018  * interpret such calls to priv_check*() as full, unrestricted requests for
2019  * 'priv', contrary to what we're doing here for selected operations, and
2020  * consequently will not grant the requested privilege.
2021  *
2022  * Also, we protect ourselves from a concurrent change of 'do_enabled' while
2023  * a call to setcred() is in progress by storing the rules per-thread
2024  * which is then consulted by each successive hook so that they all have
2025  * a coherent view of the specifications, and we empty the slot (actually, mark
2026  * it as empty) when MAC/do is disabled.
2027  */
2028 static int
check_data_usable(const void * const data,const size_t size,const int priv)2029 check_data_usable(const void *const data, const size_t size, const int priv)
2030 {
2031 	const struct mac_do_data_header *const hdr = data;
2032 
2033 	if (hdr == NULL || hdr->priv == 0)
2034 		return (ENOENT);
2035 	/*
2036 	 * Impacting changes in the protocols we are based on...  Don't crash in
2037 	 * production.
2038 	 */
2039 	if (hdr->priv != priv) {
2040 		MPASS(hdr->priv == priv);
2041 		return (EBUSY);
2042 	}
2043 	MPASS(hdr->size == size);
2044 	MPASS(hdr->size <= hdr->allocated_size);
2045 	return (0);
2046 }
2047 
2048 static void
clear_data(void * const data)2049 clear_data(void *const data)
2050 {
2051 	struct mac_do_data_header *const hdr = data;
2052 
2053 	if (hdr != NULL) {
2054 		drop_conf(hdr->conf);
2055 		/* We don't deallocate so as to save time on next access. */
2056 		hdr->priv = 0;
2057 	}
2058 }
2059 
2060 static void *
fetch_data(void)2061 fetch_data(void)
2062 {
2063 	return (osd_thread_get_unlocked(curthread, osd_thread_slot));
2064 }
2065 
2066 static bool
is_data_reusable(const void * const data,const size_t size)2067 is_data_reusable(const void *const data, const size_t size)
2068 {
2069 	const struct mac_do_data_header *const hdr = data;
2070 
2071 	return (hdr != NULL && size <= hdr->allocated_size);
2072 }
2073 
2074 static void
set_data_header(void * const data,const size_t size,const int priv,struct conf * const conf)2075 set_data_header(void *const data, const size_t size, const int priv,
2076     struct conf *const conf)
2077 {
2078 	struct mac_do_data_header *const hdr = data;
2079 
2080 	MPASS(hdr->priv == 0);
2081 	MPASS(priv != 0);
2082 	MPASS(size <= hdr->allocated_size);
2083 	hdr->size = size;
2084 	hdr->priv = priv;
2085 	hdr->conf = conf;
2086 }
2087 
2088 /* The proc lock (and any other non-sleepable lock) must not be held. */
2089 static void *
alloc_data(void * const data,const size_t size)2090 alloc_data(void *const data, const size_t size)
2091 {
2092 	struct mac_do_data_header *const hdr = realloc(data, size, M_MAC_DO,
2093 	    M_WAITOK);
2094 
2095 	MPASS(size >= sizeof(struct mac_do_data_header));
2096 	hdr->allocated_size = size;
2097 	hdr->priv = 0;
2098 	if (hdr != data) {
2099 		/*
2100 		 * This call either reuses the existing memory allocated for the
2101 		 * slot or tries to allocate some without blocking.
2102 		 */
2103 		int error = osd_thread_set(curthread, osd_thread_slot, hdr);
2104 
2105 		if (error != 0) {
2106 			/* Going to make a M_WAITOK allocation. */
2107 			void **const rsv = osd_reserve(osd_thread_slot);
2108 
2109 			error = osd_thread_set_reserved(curthread,
2110 			    osd_thread_slot, rsv, hdr);
2111 			MPASS(error == 0);
2112 		}
2113 	}
2114 	return (hdr);
2115 }
2116 
2117 /* Destructor for 'osd_thread_slot'. */
2118 static void
dealloc_thread_osd(void * const value)2119 dealloc_thread_osd(void *const value)
2120 {
2121 	free(value, M_MAC_DO);
2122 }
2123 
2124 /*
2125  * Whether to grant access to some primary group according to flags.
2126  *
2127  * The passed 'flags' must be those of a rule's matching GID, or the IT_GID type
2128  * flags when MDF_CURRENT has been matched.
2129  *
2130  * Return values:
2131  * - 0:			Access granted.
2132  * - EJUSTRETURN:	Flags are agnostic.
2133  */
2134 static int
grant_primary_group_from_flags(const flags_t flags)2135 grant_primary_group_from_flags(const flags_t flags)
2136 {
2137 	return ((flags & MDF_PRIMARY) != 0 ? 0 : EJUSTRETURN);
2138 }
2139 
2140 /*
2141  * Same as grant_primary_group_from_flags(), but for supplementary groups.
2142  *
2143  * Return values:
2144  * - 0:			Access granted.
2145  * - EJUSTRETURN:	Flags are agnostic.
2146  * - EPERM:		Access denied.
2147  */
2148 static int __unused
grant_supplementary_group_from_flags(const flags_t flags)2149 grant_supplementary_group_from_flags(const flags_t flags)
2150 {
2151 	if ((flags & MDF_SUPP_MASK) != 0)
2152 		return ((flags & MDF_SUPP_DONT) != 0 ? EPERM : 0);
2153 
2154 	return (EJUSTRETURN);
2155 }
2156 
2157 static int
rule_grant_supplementary_groups(const struct rule * const rule,const struct ucred * const old_cred,const struct ucred * const new_cred)2158 rule_grant_supplementary_groups(const struct rule *const rule,
2159     const struct ucred *const old_cred, const struct ucred *const new_cred)
2160 {
2161 	const gid_t *const old_groups = old_cred->cr_groups;
2162 	const gid_t *const new_groups = new_cred->cr_groups;
2163 	const int old_ngroups = old_cred->cr_ngroups;
2164 	const int new_ngroups = new_cred->cr_ngroups;
2165 	const flags_t gid_flags = rule->gid_flags;
2166 	const bool current_has_supp = (gid_flags & MDF_CURRENT) != 0 &&
2167 	    (gid_flags & MDF_SUPP_MASK) != 0;
2168 	id_nb_t rule_idx = 0;
2169 	int old_idx = 0, new_idx = 0;
2170 
2171 	if ((gid_flags & MDF_ANY_SUPP) != 0 &&
2172 	    (gid_flags & MDF_MAY_REJ_SUPP) == 0)
2173 		/*
2174 		 * Any set of supplementary groups is accepted, no need to loop
2175 		 * over them.
2176 		 */
2177 		return (0);
2178 
2179 	for (; new_idx < new_ngroups; ++new_idx) {
2180 		const gid_t gid = new_groups[new_idx];
2181 		bool may_accept = false;
2182 
2183 		if ((gid_flags & MDF_ANY_SUPP) != 0)
2184 			may_accept = true;
2185 
2186 		/* Do we have to check for the current supplementary groups? */
2187 		if (current_has_supp) {
2188 			/*
2189 			 * Linear search, as both supplementary groups arrays
2190 			 * are sorted.  Advancing 'old_idx' with a binary search
2191 			 * on absence of MDF_SUPP_MUST doesn't seem worth it in
2192 			 * practice.
2193 			 */
2194 			for (; old_idx < old_ngroups; ++old_idx) {
2195 				const gid_t old_gid = old_groups[old_idx];
2196 
2197 				if (old_gid < gid) {
2198 					/* Mandatory but absent. */
2199 					if ((gid_flags & MDF_SUPP_MUST) != 0)
2200 						return (EPERM);
2201 				} else if (old_gid == gid) {
2202 					switch (gid_flags & MDF_SUPP_MASK) {
2203 					case MDF_SUPP_DONT:
2204 						/* Present but forbidden. */
2205 						return (EPERM);
2206 					case MDF_SUPP_ALLOW:
2207 					case MDF_SUPP_MUST:
2208 						may_accept = true;
2209 						break;
2210 					default:
2211 #ifdef INVARIANTS
2212 						__assert_unreachable();
2213 #else
2214 						/* Better be safe than sorry. */
2215 						return (EPERM);
2216 #endif
2217 					}
2218 					++old_idx;
2219 					break;
2220 				}
2221 				else
2222 					break;
2223 			}
2224 		}
2225 
2226 		/*
2227 		 * Search by GID for a corresponding 'struct id_spec'.
2228 		 *
2229 		 * Again, linear search, with same note on not using binary
2230 		 * search optimization as above (the trigger would be absence of
2231 		 * MDF_EXPLICIT_SUPP_MUST this time).
2232 		 */
2233 		for (; rule_idx < rule->gids_nb; ++rule_idx) {
2234 			const struct id_spec is = rule->gids[rule_idx];
2235 
2236 			if (is.id < gid) {
2237 				/* Mandatory but absent. */
2238 				if ((is.flags & MDF_SUPP_MUST) != 0)
2239 					return (EPERM);
2240 			} else if (is.id == gid) {
2241 				switch (is.flags & MDF_SUPP_MASK) {
2242 				case MDF_SUPP_DONT:
2243 					/* Present but forbidden. */
2244 					return (EPERM);
2245 				case MDF_SUPP_ALLOW:
2246 				case MDF_SUPP_MUST:
2247 					may_accept = true;
2248 					break;
2249 				case 0:
2250 					/* Primary group only. */
2251 					break;
2252 				default:
2253 #ifdef INVARIANTS
2254 					__assert_unreachable();
2255 #else
2256 					/* Better be safe than sorry. */
2257 					return (EPERM);
2258 #endif
2259 				}
2260 				++rule_idx;
2261 				break;
2262 			}
2263 			else
2264 				break;
2265 		}
2266 
2267 		/* 'gid' wasn't explicitly accepted. */
2268 		if (!may_accept)
2269 			return (EPERM);
2270 	}
2271 
2272 	/*
2273 	 * If we must have all current groups and we didn't browse all
2274 	 * of them at this point (because the remaining ones have GIDs
2275 	 * greater than the last requested group), we are simply missing
2276 	 * them.
2277 	 */
2278 	if ((gid_flags & MDF_CURRENT) != 0 &&
2279 	    (gid_flags & MDF_SUPP_MUST) != 0 &&
2280 	    old_idx < old_ngroups)
2281 		return (EPERM);
2282 	/*
2283 	 * Similarly, we have to finish browsing all GIDs from the rule
2284 	 * in case some are marked mandatory.
2285 	 */
2286 	if ((gid_flags & MDF_EXPLICIT_SUPP_MUST) != 0) {
2287 		for (; rule_idx < rule->gids_nb; ++rule_idx) {
2288 			const struct id_spec is = rule->gids[rule_idx];
2289 
2290 			if ((is.flags & MDF_SUPP_MUST) != 0)
2291 				return (EPERM);
2292 		}
2293 	}
2294 
2295 	return (0);
2296 }
2297 
2298 static int
rule_grant_primary_group(const struct rule * const rule,const struct ucred * const old_cred,const gid_t gid)2299 rule_grant_primary_group(const struct rule *const rule,
2300     const struct ucred *const old_cred, const gid_t gid)
2301 {
2302 	struct id_spec gid_is = {.flags = 0};
2303 	const struct id_spec *found_is;
2304 	int error;
2305 
2306 	if ((rule->gid_flags & MDF_ANY) != 0)
2307 		return (0);
2308 
2309 	/* Was MDF_CURRENT specified, and is 'gid' a current GID? */
2310 	if ((rule->gid_flags & MDF_CURRENT) != 0 &&
2311 	    group_is_primary(gid, old_cred)) {
2312 		error = grant_primary_group_from_flags(rule->gid_flags);
2313 		if (error == 0)
2314 			return (0);
2315 	}
2316 
2317 	/* Search by GID for a corresponding 'struct id_spec'. */
2318 	gid_is.id = gid;
2319 	found_is = bsearch(&gid_is, rule->gids, rule->gids_nb,
2320 	    sizeof(*rule->gids), id_spec_cmp);
2321 
2322 	if (found_is != NULL) {
2323 		error = grant_primary_group_from_flags(found_is->flags);
2324 		if (error == 0)
2325 			return (0);
2326 	}
2327 
2328 	return (EPERM);
2329 }
2330 
2331 static int
rule_grant_primary_groups(const struct rule * const rule,const struct ucred * const old_cred,const struct ucred * const new_cred)2332 rule_grant_primary_groups(const struct rule *const rule,
2333     const struct ucred *const old_cred, const struct ucred *const new_cred)
2334 {
2335 	int error;
2336 
2337 	/* Shortcut. */
2338 	if ((rule->gid_flags & MDF_ANY) != 0)
2339 		return (0);
2340 
2341 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_gid);
2342 	if (error != 0)
2343 		return (error);
2344 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_rgid);
2345 	if (error != 0)
2346 		return (error);
2347 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_svgid);
2348 	if (error != 0)
2349 		return (error);
2350 	return (0);
2351 }
2352 
2353 static bool
user_is_current(const uid_t uid,const struct ucred * const old_cred)2354 user_is_current(const uid_t uid, const struct ucred *const old_cred)
2355 {
2356 	return (uid == old_cred->cr_uid || uid == old_cred->cr_ruid ||
2357 	    uid == old_cred->cr_svuid);
2358 }
2359 
2360 static int
rule_grant_user(const struct rule * const rule,const struct ucred * const old_cred,const uid_t uid)2361 rule_grant_user(const struct rule *const rule,
2362     const struct ucred *const old_cred, const uid_t uid)
2363 {
2364 	struct id_spec uid_is = {.flags = 0};
2365 	const struct id_spec *found_is;
2366 
2367 	if ((rule->uid_flags & MDF_ANY) != 0)
2368 		return (0);
2369 
2370 	/* Was MDF_CURRENT specified, and is 'uid' a current UID? */
2371 	if ((rule->uid_flags & MDF_CURRENT) != 0 &&
2372 	    user_is_current(uid, old_cred))
2373 		return (0);
2374 
2375 	/* Search by UID for a corresponding 'struct id_spec'. */
2376 	uid_is.id = uid;
2377 	found_is = bsearch(&uid_is, rule->uids, rule->uids_nb,
2378 	    sizeof(*rule->uids), id_spec_cmp);
2379 
2380 	if (found_is != NULL)
2381 		return (0);
2382 
2383 	return (EPERM);
2384 }
2385 
2386 static int
rule_grant_users(const struct rule * const rule,const struct ucred * const old_cred,const struct ucred * const new_cred)2387 rule_grant_users(const struct rule *const rule,
2388     const struct ucred *const old_cred, const struct ucred *const new_cred)
2389 {
2390 	int error;
2391 
2392 	/* Shortcut. */
2393 	if ((rule->uid_flags & MDF_ANY) != 0)
2394 		return (0);
2395 
2396 	error = rule_grant_user(rule, old_cred, new_cred->cr_uid);
2397 	if (error != 0)
2398 		return (error);
2399 	error = rule_grant_user(rule, old_cred, new_cred->cr_ruid);
2400 	if (error != 0)
2401 		return (error);
2402 	error = rule_grant_user(rule, old_cred, new_cred->cr_svuid);
2403 	if (error != 0)
2404 		return (error);
2405 
2406 	return (0);
2407 }
2408 
2409 static int
rule_grant_setcred(const struct rule * const rule,const struct ucred * const old_cred,const struct ucred * const new_cred)2410 rule_grant_setcred(const struct rule *const rule,
2411     const struct ucred *const old_cred, const struct ucred *const new_cred)
2412 {
2413 	int error;
2414 
2415 	error = rule_grant_users(rule, old_cred, new_cred);
2416 	if (error != 0)
2417 		return (error);
2418 	error = rule_grant_primary_groups(rule, old_cred, new_cred);
2419 	if (error != 0)
2420 		return (error);
2421 	error = rule_grant_supplementary_groups(rule, old_cred, new_cred);
2422 	if (error != 0)
2423 		return (error);
2424 
2425 	return (0);
2426 }
2427 
2428 static bool
rule_applies(const struct rule * const rule,const struct ucred * const cred)2429 rule_applies(const struct rule *const rule, const struct ucred *const cred)
2430 {
2431 	if (rule->from_type == IT_UID && rule->from_id == cred->cr_ruid)
2432 		return (true);
2433 	if (rule->from_type == IT_GID && realgroupmember(rule->from_id, cred))
2434 		return (true);
2435 	return (false);
2436 }
2437 
2438 /*
2439  * To pass data between check_setcred() and priv_grant() (on PRIV_CRED_SETCRED).
2440  */
2441 struct mac_do_setcred_data {
2442 	struct mac_do_data_header hdr;
2443 	const struct ucred *new_cred;
2444 	u_int setcred_flags;
2445 };
2446 
2447 static int
mac_do_priv_grant(struct ucred * cred,int priv)2448 mac_do_priv_grant(struct ucred *cred, int priv)
2449 {
2450 	struct mac_do_setcred_data *const data = fetch_data();
2451 	struct rules *rules;
2452 	const struct ucred *new_cred;
2453 	const struct rule *rule;
2454 	u_int setcred_flags;
2455 	int error;
2456 
2457 	/* Bail out fast if we aren't concerned. */
2458 	if (priv != PRIV_CRED_SETCRED)
2459 		return (EPERM);
2460 
2461 	/*
2462 	 * Do we have to do something?
2463 	 */
2464 	if (check_data_usable(data, sizeof(*data), priv) != 0)
2465 		/* No. */
2466 		return (EPERM);
2467 
2468 	rules = &data->hdr.conf->rules;
2469 	new_cred = data->new_cred;
2470 	KASSERT(new_cred != NULL,
2471 	    ("priv_check*() called before mac_cred_check_setcred()"));
2472 	setcred_flags = data->setcred_flags;
2473 
2474 	/*
2475 	 * Explicitly check that only the flags we currently support are present
2476 	 * in order to avoid accepting transitions with other changes than those
2477 	 * we are actually going to check.  Currently, this rules out the
2478 	 * SETCREDF_MAC_LABEL flag.  This may be improved by adding code
2479 	 * actually checking whether the requested label and the current one
2480 	 * would differ.
2481 	 */
2482 	if ((setcred_flags & ~(SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID |
2483 	    SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID |
2484 	    SETCREDF_SUPP_GROUPS)) != 0)
2485 		return (EPERM);
2486 
2487 	/*
2488 	 * Browse rules, and for those that match the requestor, call specific
2489 	 * privilege granting functions interpreting the "to"/"target" part.
2490 	 */
2491 	error = EPERM;
2492 	STAILQ_FOREACH(rule, &rules->head, r_entries)
2493 	    if (rule_applies(rule, cred)) {
2494 		    error = rule_grant_setcred(rule, cred, new_cred);
2495 		    if (error != EPERM)
2496 			    break;
2497 	    }
2498 
2499 	return (error);
2500 }
2501 
2502 static int
check_proc(void)2503 check_proc(void)
2504 {
2505 	struct prison *const pr = curproc->p_ucred->cr_prison;
2506 	char *path, *to_free;
2507 	struct conf *conf;
2508 	struct exec_paths *exec_paths;
2509 	int error;
2510 
2511 	/*
2512 	 * Only grant privileges if requested by the right executable.
2513 	 *
2514 	 * As MAC/do configuration is per-jail, in order to avoid confused
2515 	 * deputy situations in chroots (privileged or unprivileged), make sure
2516 	 * to check the path from the current jail's root.
2517 	 *
2518 	 * XXXOC: We may want to base this check on a tunable path and/or
2519 	 * a specific MAC label.  Going even further, e.g., envisioning to
2520 	 * completely replace the path check with the latter, we would need to
2521 	 * install FreeBSD on a FS with multilabel enabled by default, which in
2522 	 * practice entails adding an option to ZFS to set MNT_MULTILABEL
2523 	 * automatically on mounts, ensuring that root (and more if using
2524 	 * different partitions) ZFS or UFS filesystems are created with
2525 	 * multilabel turned on, and having the installation procedure support
2526 	 * setting a MAC label per file (perhaps via additions to mtree(1)).  So
2527 	 * this probably isn't going to happen overnight, if ever.
2528 	 */
2529 	if (vn_fullpath_jail(curproc->p_textvp, &path, &to_free) != 0)
2530 		return (EPERM);
2531 
2532 	error = EPERM;
2533 	conf = find_conf(pr, NULL);
2534 	exec_paths = &conf->exec_paths;
2535 
2536 	for (int i = 0; i < exec_paths->exec_path_count; i++)
2537 		if (strcmp(exec_paths->exec_paths[i], path) == 0) {
2538 			error = 0;
2539 			break;
2540 		}
2541 
2542 	drop_conf(conf);
2543 	free(to_free, M_TEMP);
2544 	return (error);
2545 }
2546 
2547 static void
mac_do_setcred_enter(void)2548 mac_do_setcred_enter(void)
2549 {
2550 	struct prison *const pr = curproc->p_ucred->cr_prison;
2551 	struct mac_do_setcred_data * data;
2552 	struct conf *conf;
2553 	int error;
2554 
2555 	/*
2556 	 * If not enabled, don't prepare data.  Other hooks will check for that
2557 	 * to know if they have to do something.
2558 	 */
2559 	if (do_enabled == 0)
2560 		return;
2561 
2562 	/*
2563 	 * MAC/do only applies to a process launched from a given executable.
2564 	 * For other processes, we just won't intervene (we don't deny requests,
2565 	 * nor do we grant privileges to them).
2566 	 */
2567 	error = check_proc();
2568 	if (error != 0)
2569 		return;
2570 
2571 	/*
2572 	 * Find the currently applicable rules.
2573 	 */
2574 	conf = find_conf(pr, NULL);
2575 
2576 	/*
2577 	 * Setup thread data to be used by other hooks.
2578 	 */
2579 	data = fetch_data();
2580 	if (!is_data_reusable(data, sizeof(*data)))
2581 		data = alloc_data(data, sizeof(*data));
2582 	set_data_header(data, sizeof(*data), PRIV_CRED_SETCRED, conf);
2583 	/* Not really necessary, but helps to catch programming errors. */
2584 	data->new_cred = NULL;
2585 	data->setcred_flags = 0;
2586 }
2587 
2588 static int
mac_do_check_setcred(u_int flags,const struct ucred * const old_cred,struct ucred * const new_cred)2589 mac_do_check_setcred(u_int flags, const struct ucred *const old_cred,
2590     struct ucred *const new_cred)
2591 {
2592 	struct mac_do_setcred_data *const data = fetch_data();
2593 
2594 	/*
2595 	 * Do we have to do something?
2596 	 */
2597 	if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) != 0)
2598 		/* No. */
2599 		return (0);
2600 
2601 	/*
2602 	 * Keep track of the setcred() flags and the new credentials for
2603 	 * priv_check*().
2604 	 */
2605 	data->new_cred = new_cred;
2606 	data->setcred_flags = flags;
2607 
2608 	return (0);
2609 }
2610 
2611 static void
mac_do_setcred_exit(void)2612 mac_do_setcred_exit(void)
2613 {
2614 	struct mac_do_setcred_data *const data = fetch_data();
2615 
2616 	if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) == 0)
2617 		/*
2618 		 * This doesn't deallocate the small per-thread data storage,
2619 		 * which can be reused on subsequent calls.  (That data is of
2620 		 * course deallocated as the current thread dies or this module
2621 		 * is unloaded.)
2622 		 */
2623 		clear_data(data);
2624 }
2625 
2626 static void
mac_do_init(struct mac_policy_conf * mpc)2627 mac_do_init(struct mac_policy_conf *mpc)
2628 {
2629 	struct conf *const default_conf = new_default_conf();
2630 	struct prison *pr;
2631 
2632 	rm_init_flags(&mac_do_rml, "mac_do(4)", RM_SLEEPABLE);
2633 
2634 	osd_jail_slot = osd_jail_register(dealloc_jail_osd, osd_methods);
2635 	set_conf(&prison0, default_conf);
2636 	sx_slock(&allprison_lock);
2637 	TAILQ_FOREACH(pr, &allprison, pr_list)
2638 	    set_conf(pr, default_conf);
2639 	sx_sunlock(&allprison_lock);
2640 	drop_conf(default_conf);
2641 
2642 	osd_thread_slot = osd_thread_register(dealloc_thread_osd);
2643 }
2644 
2645 static void
mac_do_destroy(struct mac_policy_conf * mpc)2646 mac_do_destroy(struct mac_policy_conf *mpc)
2647 {
2648 	/*
2649 	 * osd_thread_deregister() must be called before osd_jail_deregister(),
2650 	 * for the reason explained in dealloc_jail_osd().
2651 	 */
2652 	osd_thread_deregister(osd_thread_slot);
2653 	osd_jail_deregister(osd_jail_slot);
2654 	rm_destroy(&mac_do_rml);
2655 }
2656 
2657 static struct mac_policy_ops do_ops = {
2658 	.mpo_init = mac_do_init,
2659 	.mpo_destroy = mac_do_destroy,
2660 	.mpo_cred_setcred_enter = mac_do_setcred_enter,
2661 	.mpo_cred_check_setcred = mac_do_check_setcred,
2662 	.mpo_cred_setcred_exit = mac_do_setcred_exit,
2663 	.mpo_priv_grant = mac_do_priv_grant,
2664 };
2665 
2666 MAC_POLICY_SET(&do_ops, mac_do, "MAC/do", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
2667 MODULE_VERSION(mac_do, 1);
2668