xref: /freebsd/sys/security/mac_do/mac_do.c (revision c7fc71c6af0761f81ecafdb281dd43a081b3b22f)
1 /*-
2  * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <sys/param.h>
8 #include <sys/systm.h>
9 #include <sys/ctype.h>
10 #include <sys/jail.h>
11 #include <sys/kernel.h>
12 #include <sys/limits.h>
13 #include <sys/lock.h>
14 #include <sys/malloc.h>
15 #include <sys/module.h>
16 #include <sys/mount.h>
17 #include <sys/mutex.h>
18 #include <sys/priv.h>
19 #include <sys/proc.h>
20 #include <sys/refcount.h>
21 #include <sys/socket.h>
22 #include <sys/sx.h>
23 #include <sys/sysctl.h>
24 #include <sys/ucred.h>
25 #include <sys/vnode.h>
26 
27 #include <machine/stdarg.h>
28 
29 #include <security/mac/mac_policy.h>
30 
31 static SYSCTL_NODE(_security_mac, OID_AUTO, do,
32     CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "mac_do policy controls");
33 
34 static int	do_enabled = 1;
35 SYSCTL_INT(_security_mac_do, OID_AUTO, enabled, CTLFLAG_RWTUN,
36     &do_enabled, 0, "Enforce do policy");
37 
38 static int	print_parse_error = 1;
39 SYSCTL_INT(_security_mac_do, OID_AUTO, print_parse_error, CTLFLAG_RWTUN,
40     &print_parse_error, 0, "Print parse errors on setting rules "
41     "(via sysctl(8)).");
42 
43 static MALLOC_DEFINE(M_DO, "do_rule", "Rules for mac_do");
44 
45 #define MAC_RULE_STRING_LEN	1024
46 
47 static unsigned		osd_jail_slot;
48 static unsigned		osd_thread_slot;
49 
50 #define IT_INVALID	0 /* Must stay 0. */
51 #define IT_UID		1
52 #define IT_GID		2
53 #define IT_ANY		3
54 #define IT_LAST		IT_ANY
55 
56 static const char *id_type_to_str[] = {
57 	[IT_INVALID]	= "invalid",
58 	[IT_UID]	= "uid",
59 	[IT_GID]	= "gid",
60 	/* See also parse_id_type(). */
61 	[IT_ANY]	= "*",
62 };
63 
64 #define PARSE_ERROR_SIZE	256
65 
66 struct parse_error {
67 	size_t	pos;
68 	char	msg[PARSE_ERROR_SIZE];
69 };
70 
71 /*
72  * We assume that 'uid_t' and 'gid_t' are aliases to 'u_int' in conversions
73  * required for parsing rules specification strings.
74  */
75 _Static_assert(sizeof(uid_t) == sizeof(u_int) && (uid_t)-1 >= 0 &&
76     sizeof(gid_t) == sizeof(u_int) && (gid_t)-1 >= 0,
77     "mac_do(4) assumes that 'uid_t' and 'gid_t' are aliases to 'u_int'");
78 
79 /*
80  * Internal flags.
81  *
82  * They either apply as per-type (t) or per-ID (i) but are conflated because all
83  * per-ID flags are also valid as per-type ones to qualify the "current" (".")
84  * per-type flag.  Also, some of them are in fact exclusive, but we use one-hot
85  * encoding for simplicity.
86  *
87  * There is currently room for "only" 16 bits.  As these flags are purely
88  * internal, they can be renumbered and/or their type changed as needed.
89  *
90  * See also the check_*() functions below.
91  */
92 typedef uint16_t	flags_t;
93 
94 /* (i,gid) Specification concerns primary groups. */
95 #define MDF_PRIMARY	(1u << 0)
96 /* (i,gid) Specification concerns supplementary groups. */
97 #define MDF_SUPP_ALLOW	(1u << 1)
98 /* (i,gid) Group must appear as a supplementary group. */
99 #define MDF_SUPP_MUST	(1u << 2)
100 /* (i,gid) Group must not appear as a supplementary group. */
101 #define MDF_SUPP_DONT	(1u << 3)
102 #define MDF_SUPP_MASK	(MDF_SUPP_ALLOW | MDF_SUPP_MUST | MDF_SUPP_DONT)
103 #define MDF_ID_MASK	(MDF_PRIMARY | MDF_SUPP_MASK)
104 
105 /*
106  * (t) All IDs allowed.
107  *
108  * For GIDs, MDF_ANY only concerns primary groups.  The MDF_PRIMARY and
109  * MDF_SUPP_* flags never apply to MDF_ANY, but can be present if MDF_CURRENT is
110  * present also, as usual.
111  */
112 #define MDF_ANY			(1u << 8)
113 /* (t) Current IDs allowed. */
114 #define MDF_CURRENT		(1u << 9)
115 #define MDF_TYPE_COMMON_MASK	(MDF_ANY | MDF_CURRENT)
116 /* (t,gid) All IDs allowed as supplementary groups. */
117 #define MDF_ANY_SUPP		(1u << 10)
118 /* (t,gid) Some ID or MDF_CURRENT has MDF_SUPP_MUST or MDF_SUPP_DONT. */
119 #define MDF_MAY_REJ_SUPP	(1u << 11)
120 /* (t,gid) Some explicit ID (not MDF_CURRENT) has MDF_SUPP_MUST. */
121 #define MDF_EXPLICIT_SUPP_MUST	(1u << 12)
122 /* (t,gid) Whether any target clause is about primary groups.  Used during
123  * parsing only. */
124 #define MDF_HAS_PRIMARY_CLAUSE	(1u << 13)
125 /* (t,gid) Whether any target clause is about supplementary groups.  Used during
126  * parsing only. */
127 #define MDF_HAS_SUPP_CLAUSE	(1u << 14)
128 #define MDF_TYPE_GID_MASK	(MDF_ANY_SUPP | MDF_MAY_REJ_SUPP |	\
129     MDF_EXPLICIT_SUPP_MUST | MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE)
130 #define MDF_TYPE_MASK		(MDF_TYPE_COMMON_MASK | MDF_TYPE_GID_MASK)
131 
132 /*
133  * Persistent structures.
134  */
135 
136 struct id_spec {
137 	u_int		 id;
138 	flags_t		 flags; /* See MDF_* above. */
139 };
140 
141 /*
142  * This limits the number of target clauses per type to 65535.  With the current
143  * value of MAC_RULE_STRING_LEN (1024), this is way more than enough anyway.
144  */
145 typedef uint16_t	 id_nb_t;
146 /* We only have a few IT_* types. */
147 typedef uint16_t	 id_type_t;
148 
149 struct rule {
150 	STAILQ_ENTRY(rule) r_entries;
151 	id_type_t	 from_type;
152 	u_int		 from_id;
153 	flags_t		 uid_flags; /* See MDF_* above. */
154 	id_nb_t		 uids_nb;
155 	flags_t		 gid_flags; /* See MDF_* above. */
156 	id_nb_t		 gids_nb;
157 	struct id_spec	*uids;
158 	struct id_spec	*gids;
159 };
160 
161 STAILQ_HEAD(rulehead, rule);
162 
163 struct rules {
164 	char		string[MAC_RULE_STRING_LEN];
165 	struct rulehead	head;
166 	volatile u_int	use_count __aligned(CACHE_LINE_SIZE);
167 };
168 
169 /*
170  * Temporary structures used to build a 'struct rule' above.
171  */
172 
173 struct id_elem {
174 	STAILQ_ENTRY(id_elem) ie_entries;
175 	struct id_spec spec;
176 };
177 
178 STAILQ_HEAD(id_list, id_elem);
179 
180 #ifdef INVARIANTS
181 static void
182 check_type(const id_type_t type)
183 {
184 	if (type > IT_LAST)
185 		panic("Invalid type number %u", type);
186 }
187 
188 static void
189 panic_for_unexpected_flags(const id_type_t type, const flags_t flags,
190     const char *const str)
191 {
192 	panic("ID type %s: Unexpected flags %u (%s), ", id_type_to_str[type],
193 	    flags, str);
194 }
195 
196 static void
197 check_type_and_id_flags(const id_type_t type, const flags_t flags)
198 {
199 	const char *str;
200 
201 	check_type(type);
202 	switch (type) {
203 	case IT_UID:
204 		if (flags != 0) {
205 			str = "only 0 allowed";
206 			goto unexpected_flags;
207 		}
208 		break;
209 	case IT_GID:
210 		if ((flags & ~MDF_ID_MASK) != 0) {
211 			str = "only bits in MDF_ID_MASK allowed";
212 			goto unexpected_flags;
213 		}
214 		if (!powerof2(flags & MDF_SUPP_MASK)) {
215 			str = "only a single flag in MDF_SUPP_MASK allowed";
216 			goto unexpected_flags;
217 		}
218 		break;
219 	default:
220 	    __assert_unreachable();
221 	}
222 	return;
223 
224 unexpected_flags:
225 	panic_for_unexpected_flags(type, flags, str);
226 }
227 
228 static void
229 check_type_and_id_spec(const id_type_t type, const struct id_spec *const is)
230 {
231 	check_type_and_id_flags(type, is->flags);
232 }
233 
234 static void
235 check_type_and_type_flags(const id_type_t type, const flags_t flags)
236 {
237 	const char *str;
238 
239 	check_type_and_id_flags(type, flags & MDF_ID_MASK);
240 	if ((flags & ~MDF_ID_MASK & ~MDF_TYPE_MASK) != 0) {
241 		str = "only MDF_ID_MASK | MDF_TYPE_MASK bits allowed";
242 		goto unexpected_flags;
243 	}
244 	if ((flags & MDF_ANY) != 0 && (flags & MDF_CURRENT) != 0 &&
245 	    (type == IT_UID || (flags & MDF_PRIMARY) != 0)) {
246 		str = "MDF_ANY and MDF_CURRENT are exclusive for UIDs "
247 		    "or primary group GIDs";
248 		goto unexpected_flags;
249 	}
250 	if ((flags & MDF_ANY_SUPP) != 0 && (flags & MDF_CURRENT) != 0 &&
251 	    (flags & MDF_SUPP_MASK) != 0) {
252 		str = "MDF_SUPP_ANY and MDF_CURRENT with supplementary "
253 		    "groups specification are exclusive";
254 		goto unexpected_flags;
255 	}
256 	if (((flags & MDF_PRIMARY) != 0 || (flags & MDF_ANY) != 0) &&
257 	    (flags & MDF_HAS_PRIMARY_CLAUSE) == 0) {
258 		str = "Presence of folded primary clause not reflected "
259 		    "by presence of MDF_HAS_PRIMARY_CLAUSE";
260 		goto unexpected_flags;
261 	}
262 	if (((flags & MDF_SUPP_MASK) != 0 || (flags & MDF_ANY_SUPP) != 0) &&
263 	    (flags & MDF_HAS_SUPP_CLAUSE) == 0) {
264 		str = "Presence of folded supplementary clause not reflected "
265 		    "by presence of MDF_HAS_SUPP_CLAUSE";
266 		goto unexpected_flags;
267 	}
268 	return;
269 
270 unexpected_flags:
271 	panic_for_unexpected_flags(type, flags, str);
272 }
273 #else /* !INVARIANTS */
274 #define check_type_and_id_flags(...)
275 #define check_type_and_id_spec(...)
276 #define check_type_and_type_flags(...)
277 #endif /* INVARIANTS */
278 
279 /*
280  * Returns EALREADY if both flags have some overlap, or EINVAL if flags are
281  * incompatible, else 0 with flags successfully merged into 'dest'.
282  */
283 static int
284 coalesce_id_flags(const flags_t src, flags_t *const dest)
285 {
286 	flags_t res;
287 
288 	if ((src & *dest) != 0)
289 		return (EALREADY);
290 
291 	res = src | *dest;
292 
293 	/* Check for compatibility of supplementary flags, and coalesce. */
294 	if ((res & MDF_SUPP_MASK) != 0) {
295 		/* MDF_SUPP_DONT incompatible with the rest. */
296 		if ((res & MDF_SUPP_DONT) != 0 && (res & MDF_SUPP_MASK &
297 		    ~MDF_SUPP_DONT) != 0)
298 			return (EINVAL);
299 		/*
300 		 * Coalesce MDF_SUPP_ALLOW and MDF_SUPP_MUST into MDF_SUPP_MUST.
301 		 */
302 		if ((res & MDF_SUPP_ALLOW) != 0 && (res & MDF_SUPP_MUST) != 0)
303 			res &= ~MDF_SUPP_ALLOW;
304 	}
305 
306 	*dest = res;
307 	return (0);
308 }
309 
310 static void
311 toast_rules(struct rules *const rules)
312 {
313 	struct rulehead *const head = &rules->head;
314 	struct rule *rule, *rule_next;
315 
316 	STAILQ_FOREACH_SAFE(rule, head, r_entries, rule_next) {
317 		free(rule->uids, M_DO);
318 		free(rule->gids, M_DO);
319 		free(rule, M_DO);
320 	}
321 	free(rules, M_DO);
322 }
323 
324 static struct rules *
325 alloc_rules(void)
326 {
327 	struct rules *const rules = malloc(sizeof(*rules), M_DO, M_WAITOK);
328 
329 	_Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!");
330 	rules->string[0] = 0;
331 	STAILQ_INIT(&rules->head);
332 	rules->use_count = 0;
333 	return (rules);
334 }
335 
336 static bool
337 is_null_or_empty(const char *s)
338 {
339 	return (s == NULL || s[0] == '\0');
340 }
341 
342 /*
343  * String to unsigned int.
344  *
345  * Contrary to the "standard" strtou*() family of functions, do not tolerate
346  * spaces at start nor an empty string, and returns a status code, the 'u_int'
347  * result being returned through a passed pointer (if no error).
348  *
349  * We detour through 'quad_t' because in-kernel strto*() functions cannot set
350  * 'errno' and thus can't distinguish a true maximum value from one returned
351  * because of overflow.  We use 'quad_t' instead of 'u_quad_t' to support
352  * negative specifications (e.g., such as "-1" for UINT_MAX).
353  */
354 static int
355 strtoui_strict(const char *const restrict s, const char **const restrict endptr,
356     int base, u_int *result)
357 {
358 	char *ep;
359 	quad_t q;
360 
361 	/* Rule out spaces and empty specifications. */
362 	if (s[0] == '\0' || isspace(s[0])) {
363 		if (endptr != NULL)
364 			*endptr = s;
365 		return (EINVAL);
366 	}
367 
368 	q = strtoq(s, &ep, base);
369 	if (endptr != NULL)
370 		*endptr = ep;
371 	if (q < 0) {
372 		/* We allow specifying a negative number. */
373 		if (q < -(quad_t)UINT_MAX - 1 || q == QUAD_MIN)
374 			return (EOVERFLOW);
375 	} else {
376 		if (q > UINT_MAX || q == UQUAD_MAX)
377 			return (EOVERFLOW);
378 	}
379 
380 	*result = (u_int)q;
381 	return (0);
382 }
383 
384 /*
385  * strsep() variant skipping spaces and tabs.
386  *
387  * Skips spaces and tabs at beginning and end of the token before one of the
388  * 'delim' characters, i.e., at start of string and just before one of the
389  * delimiter characters (so it doesn't prevent tokens containing spaces and tabs
390  * in the middle).
391  */
392 static char *
393 strsep_noblanks(char **const stringp, const char *delim)
394 {
395 	char *p = *stringp;
396 	char *ret, *wsp;
397 	size_t idx;
398 
399 	if (p == NULL)
400 		return (NULL);
401 
402 	idx = strspn(p, " \t");
403 	p += idx;
404 
405 	ret = strsep(&p, delim);
406 
407 	/* Rewind spaces/tabs at the end. */
408 	if (p == NULL)
409 		wsp = ret + strlen(ret);
410 	else
411 		wsp = p - 1;
412 	for (; wsp != ret; --wsp) {
413 		switch (wsp[-1]) {
414 		case ' ':
415 		case '\t':
416 			continue;
417 		}
418 		break;
419 	}
420 	*wsp = '\0';
421 
422 	*stringp = p;
423 	return (ret);
424 }
425 
426 
427 static void
428 make_parse_error(struct parse_error **const parse_error, const size_t pos,
429     const char *const fmt, ...)
430 {
431 	struct parse_error *const err = malloc(sizeof(*err), M_DO, M_WAITOK);
432 	va_list ap;
433 
434 	err->pos = pos;
435 	va_start(ap, fmt);
436 	vsnprintf(err->msg, PARSE_ERROR_SIZE, fmt, ap);
437 	va_end(ap);
438 
439 	MPASS(*parse_error == NULL);
440 	*parse_error = err;
441 }
442 
443 static void
444 free_parse_error(struct parse_error *const parse_error)
445 {
446 	free(parse_error, M_DO);
447 }
448 
449 static int
450 parse_id_type(const char *const string, id_type_t *const type,
451     struct parse_error **const parse_error)
452 {
453 	/*
454 	 * Special case for "any", as the canonical form for IT_ANY in
455 	 * id_type_to_str[] is "*".
456 	 */
457 	if (strcmp(string, "any") == 0) {
458 		*type = IT_ANY;
459 		return (0);
460 	}
461 
462 	/* Start at 1 to avoid parsing "invalid". */
463 	for (size_t i = 1; i <= IT_LAST; ++i) {
464 		if (strcmp(string, id_type_to_str[i]) == 0) {
465 			*type = i;
466 			return (0);
467 		}
468 	}
469 
470 	*type = IT_INVALID;
471 	make_parse_error(parse_error, 0, "No valid type found.");
472 	return (EINVAL);
473 }
474 
475 static size_t
476 parse_gid_flags(const char *const string, flags_t *const flags,
477     flags_t *const gid_flags)
478 {
479 	switch (string[0]) {
480 	case '+':
481 		*flags |= MDF_SUPP_ALLOW;
482 		goto has_supp_clause;
483 	case '!':
484 		*flags |= MDF_SUPP_MUST;
485 		*gid_flags |= MDF_MAY_REJ_SUPP;
486 		goto has_supp_clause;
487 	case '-':
488 		*flags |= MDF_SUPP_DONT;
489 		*gid_flags |= MDF_MAY_REJ_SUPP;
490 		goto has_supp_clause;
491 	has_supp_clause:
492 		*gid_flags |= MDF_HAS_SUPP_CLAUSE;
493 		return (1);
494 	}
495 
496 	return (0);
497 }
498 
499 static bool
500 parse_any(const char *const string)
501 {
502 	return (strcmp(string, "*") == 0 || strcmp(string, "any") == 0);
503 }
504 
505 static bool
506 has_clauses(const id_nb_t nb, const flags_t type_flags)
507 {
508 	return ((type_flags & MDF_TYPE_MASK) != 0 || nb != 0);
509 }
510 
511 static int
512 parse_target_clause(char *to, struct rule *const rule,
513     struct id_list *const uid_list, struct id_list *const gid_list,
514     struct parse_error **const parse_error)
515 {
516 	const char *const start = to;
517 	char *to_type, *to_id;
518 	const char *p;
519 	struct id_list *list;
520 	id_nb_t *nb;
521 	flags_t *tflags;
522 	struct id_elem *ie;
523 	struct id_spec is = {.flags = 0};
524 	flags_t gid_flags = 0;
525 	id_type_t type;
526 	int error;
527 
528 	MPASS(*parse_error == NULL);
529 	MPASS(to != NULL);
530 	to_type = strsep_noblanks(&to, "=");
531 	MPASS(to_type != NULL);
532 	to_type += parse_gid_flags(to_type, &is.flags, &gid_flags);
533 	error = parse_id_type(to_type, &type, parse_error);
534 	if (error != 0)
535 		goto einval;
536 	if (type != IT_GID && is.flags != 0) {
537 		make_parse_error(parse_error, to_type - start,
538 		    "Expected type 'gid' after flags, not '%s'.",
539 		    to_type);
540 		goto einval;
541 	}
542 
543 	to_id = strsep_noblanks(&to, "");
544 	switch (type) {
545 	case IT_GID:
546 		if (to_id == NULL) {
547 			make_parse_error(parse_error, to_type - start,
548 			    "No '=' and ID specification after type '%s'.",
549 			    to_type);
550 			goto einval;
551 		}
552 
553 		if (is.flags == 0) {
554 			/* No flags: Dealing with a primary group. */
555 			is.flags |= MDF_PRIMARY;
556 			gid_flags |= MDF_HAS_PRIMARY_CLAUSE;
557 		}
558 
559 		list = gid_list;
560 		nb = &rule->gids_nb;
561 		tflags = &rule->gid_flags;
562 
563 		/* "*" or "any"? */
564 		if (parse_any(to_id)) {
565 			/*
566 			 * We check that we have not seen any other clause of
567 			 * the same category (i.e., concerning primary or
568 			 * supplementary groups).
569 			 */
570 			if ((is.flags & MDF_PRIMARY) != 0) {
571 				if ((*tflags & MDF_HAS_PRIMARY_CLAUSE) != 0) {
572 					make_parse_error(parse_error,
573 					    to_id - start,
574 					    "'any' specified after another "
575 					    "(primary) GID.");
576 					goto einval;
577 				}
578 				*tflags |= gid_flags | MDF_ANY;
579 			} else {
580 				/*
581 				 * If a supplementary group flag was present, it
582 				 * must be MDF_SUPP_ALLOW ("+").
583 				 */
584 				if ((is.flags & MDF_SUPP_MASK) != MDF_SUPP_ALLOW) {
585 					make_parse_error(parse_error,
586 					    to_id - start,
587 					    "'any' specified with another "
588 					    "flag than '+'.");
589 					goto einval;
590 				}
591 				if ((*tflags & MDF_HAS_SUPP_CLAUSE) != 0) {
592 					make_parse_error(parse_error,
593 					    to_id - start,
594 					    "'any' with flag '+' specified after "
595 					    "another (supplementary) GID.");
596 					goto einval;
597 				}
598 				*tflags |= gid_flags | MDF_ANY_SUPP;
599 			}
600 			goto check_type_and_finish;
601 		} else {
602 			/*
603 			 * Check that we haven't already seen "any" for the same
604 			 * category.
605 			 */
606 			if ((is.flags & MDF_PRIMARY) != 0) {
607 				if ((*tflags & MDF_ANY) != 0) {
608 					make_parse_error(parse_error,
609 					    to_id - start,
610 					    "Some (primary) GID specified after "
611 					    "'any'.");
612 					goto einval;
613 				}
614 			} else if ((*tflags & MDF_ANY_SUPP) != 0 &&
615 			    (is.flags & MDF_SUPP_ALLOW) != 0) {
616 				make_parse_error(parse_error,
617 				    to_id - start,
618 				    "Some (supplementary) GID specified after "
619 				    "'any' with flag '+'.");
620 				goto einval;
621 			}
622 			*tflags |= gid_flags;
623 		}
624 		break;
625 
626 	case IT_UID:
627 		if (to_id == NULL) {
628 			make_parse_error(parse_error, to_type - start,
629 			    "No '=' and ID specification after type '%s'.",
630 			    to_type);
631 			goto einval;
632 		}
633 
634 		list = uid_list;
635 		nb = &rule->uids_nb;
636 		tflags = &rule->uid_flags;
637 
638 		/* "*" or "any"? */
639 		if (parse_any(to_id)) {
640 			/* There must not be any other clause. */
641 			if (has_clauses(*nb, *tflags)) {
642 				make_parse_error(parse_error, to_id - start,
643 				    "'any' specified after another UID.");
644 				goto einval;
645 			}
646 			*tflags |= MDF_ANY;
647 			goto check_type_and_finish;
648 		} else {
649 			/*
650 			 * Check that we haven't already seen "any" for the same
651 			 * category.
652 			 */
653 			if ((*tflags & MDF_ANY) != 0) {
654 				make_parse_error(parse_error, to_id - start,
655 				    "Some UID specified after 'any'.");
656 				goto einval;
657 			}
658 		}
659 		break;
660 
661 	case IT_ANY:
662 		/* No ID allowed. */
663 		if (to_id != NULL) {
664 			make_parse_error(parse_error, to_type - start,
665 			    "No '=' and ID allowed after type '%s'.", to_type);
666 			goto einval;
667 		}
668 		/*
669 		 * We can't have IT_ANY after any other IT_*, it must be the
670 		 * only one.
671 		 */
672 		if (has_clauses(rule->uids_nb, rule->uid_flags) ||
673 		    has_clauses(rule->gids_nb, rule->gid_flags)) {
674 			make_parse_error(parse_error, to_type - start,
675 			    "Target clause of type '%s' coming after another "
676 			    "clause (must be alone).", to_type);
677 			goto einval;
678 		}
679 		rule->uid_flags |= MDF_ANY;
680 		rule->gid_flags |= MDF_ANY | MDF_ANY_SUPP |
681 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
682 		goto finish;
683 
684 	default:
685 		/* parse_id_type() returns no other types currently. */
686 		__assert_unreachable();
687 	}
688 
689 	/* Rule out cases that have been treated above. */
690 	MPASS((type == IT_UID || type == IT_GID) && !parse_any(to_id));
691 
692 	/* "."? */
693 	if (strcmp(to_id, ".") == 0) {
694 		if ((*tflags & MDF_CURRENT) != 0) {
695 			/* Duplicate "." <id>.  Try to coalesce. */
696 			error = coalesce_id_flags(is.flags, tflags);
697 			if (error != 0) {
698 				make_parse_error(parse_error, to_id - start,
699 				    "Incompatible flags with prior clause "
700 				    "with same target.");
701 				goto einval;
702 			}
703 		} else
704 			*tflags |= MDF_CURRENT | is.flags;
705 		goto check_type_and_finish;
706 	}
707 
708 	/* Parse an ID. */
709 	error = strtoui_strict(to_id, &p, 10, &is.id);
710 	if (error != 0 || *p != '\0') {
711 		make_parse_error(parse_error, to_id - start,
712 		    "Cannot parse a numerical ID (base 10).");
713 		goto einval;
714 	}
715 
716 	/* Explicit ID flags. */
717 	if (type == IT_GID && (is.flags & MDF_SUPP_MUST) != 0)
718 		*tflags |= MDF_EXPLICIT_SUPP_MUST;
719 
720 	/*
721 	 * We check for duplicate IDs and coalesce their 'struct id_spec' only
722 	 * at end of parse_single_rule() because it is much more performant then
723 	 * (using sorted arrays).
724 	 */
725 	++*nb;
726 	if (*nb == 0) {
727 		make_parse_error(parse_error, 0,
728 		    "Too many target clauses of type '%s'.", to_type);
729 		return (EOVERFLOW);
730 	}
731 	ie = malloc(sizeof(*ie), M_DO, M_WAITOK);
732 	ie->spec = is;
733 	STAILQ_INSERT_TAIL(list, ie, ie_entries);
734 	check_type_and_id_spec(type, &is);
735 check_type_and_finish:
736 	check_type_and_type_flags(type, *tflags);
737 finish:
738 	return (0);
739 einval:
740 	/* We must have built a parse error on error. */
741 	MPASS(*parse_error != NULL);
742 	return (EINVAL);
743 }
744 
745 static int
746 u_int_cmp(const u_int i1, const u_int i2)
747 {
748 	return ((i1 > i2) - (i1 < i2));
749 }
750 
751 static int
752 id_spec_cmp(const void *const p1, const void *const p2)
753 {
754 	const struct id_spec *const is1 = p1;
755 	const struct id_spec *const is2 = p2;
756 
757 	return (u_int_cmp(is1->id, is2->id));
758 }
759 
760 /*
761  * Transfer content of 'list' into 'array', freeing and emptying list.
762  *
763  * 'nb' must be 'list''s length and not be greater than 'array''s size.  The
764  * destination array is sorted by ID.  Structures 'struct id_spec' with same IDs
765  * are coalesced if that makes sense (not including duplicate clauses), else
766  * EINVAL is returned.  On success, 'nb' is updated (lowered) to account for
767  * coalesced specifications.  The parameter 'type' is only for testing purposes
768  * (INVARIANTS).
769  */
770 static int
771 pour_list_into_rule(const id_type_t type, struct id_list *const list,
772     struct id_spec *const array, id_nb_t *const nb,
773     struct parse_error **const parse_error)
774 {
775 	struct id_elem *ie, *ie_next;
776 	size_t idx = 0;
777 
778 	/* Fill the array. */
779 	STAILQ_FOREACH_SAFE(ie, list, ie_entries, ie_next) {
780 		MPASS(idx < *nb);
781 		array[idx] = ie->spec;
782 		free(ie, M_DO);
783 		++idx;
784 	}
785 	MPASS(idx == *nb);
786 	STAILQ_INIT(list);
787 
788 	/* Sort it (by ID). */
789 	qsort(array, *nb, sizeof(*array), id_spec_cmp);
790 
791 	/* Coalesce same IDs. */
792 	if (*nb != 0) {
793 		size_t ref_idx = 0;
794 
795 		for (idx = 1; idx < *nb; ++idx) {
796 			const u_int id = array[idx].id;
797 
798 			if (id != array[ref_idx].id) {
799 				++ref_idx;
800 				if (ref_idx != idx)
801 					array[ref_idx] = array[idx];
802 				continue;
803 			}
804 
805 			switch (type) {
806 				int error;
807 
808 			case IT_GID:
809 				error = coalesce_id_flags(array[idx].flags,
810 				    &array[ref_idx].flags);
811 				if (error != 0) {
812 					make_parse_error(parse_error, 0,
813 					    "Incompatible flags or duplicate "
814 					    "GID %u.", id);
815 					return (EINVAL);
816 				}
817 				check_type_and_id_flags(type,
818 				    array[ref_idx].flags);
819 				break;
820 
821 			case IT_UID:
822 				/*
823 				 * No flags in this case.  Multiple appearances
824 				 * of the same UID is an exact redundancy, so
825 				 * error out.
826 				 */
827 				make_parse_error(parse_error, 0,
828 				    "Duplicate UID %u.", id);
829 				return (EINVAL);
830 
831 			default:
832 				__assert_unreachable();
833 			}
834 		}
835 		*nb = ref_idx + 1;
836 	}
837 
838 	return (0);
839 }
840 
841 /*
842  * See also first comments for parse_rule() below.
843  *
844  * The second part of a rule, called <target> (or <to>), is a comma-separated
845  * (',') list of '<flags><type>=<id>' clauses similar to that of the <from>
846  * part, with the extensions that <id> may also be "*" or "any" or ".", and that
847  * <flags> may contain at most one of the '+', '-' and '!' characters when
848  * <type> is "gid" (no flags are allowed for "uid").  No two clauses in a single
849  * <to> list may list the same <id>.  "*" and "any" both designate any ID for
850  * the <type>, and are aliases to each other.  In front of "any" (or "*"), only
851  * the '+' flag is allowed (in the "gid" case).  "." designates the process'
852  * current IDs for the <type>.  The precise meaning of flags and "." is
853  * explained in functions checking privileges below.
854  */
855 static int
856 parse_single_rule(char *rule, struct rules *const rules,
857     struct parse_error **const parse_error)
858 {
859 	const char *const start = rule;
860 	const char *from_type, *from_id, *p;
861 	char *to_list;
862 	struct id_list uid_list, gid_list;
863 	struct id_elem *ie, *ie_next;
864 	struct rule *new;
865 	int error;
866 
867 	MPASS(*parse_error == NULL);
868 	STAILQ_INIT(&uid_list);
869 	STAILQ_INIT(&gid_list);
870 
871 	/* Freed when the 'struct rules' container is freed. */
872 	new = malloc(sizeof(*new), M_DO, M_WAITOK | M_ZERO);
873 
874 	from_type = strsep_noblanks(&rule, "=");
875 	MPASS(from_type != NULL); /* Because 'rule' was not NULL. */
876 	error = parse_id_type(from_type, &new->from_type, parse_error);
877 	if (error != 0)
878 		goto einval;
879 	switch (new->from_type) {
880 	case IT_UID:
881 	case IT_GID:
882 		break;
883 	default:
884 		make_parse_error(parse_error, 0, "Type '%s' not allowed in "
885 		    "the \"from\" part of rules.");
886 		goto einval;
887 	}
888 
889 	from_id = strsep_noblanks(&rule, ":");
890 	if (is_null_or_empty(from_id)) {
891 		make_parse_error(parse_error, 0, "No ID specified.");
892 		goto einval;
893 	}
894 
895 	error = strtoui_strict(from_id, &p, 10, &new->from_id);
896 	if (error != 0 || *p != '\0') {
897 		make_parse_error(parse_error, from_id - start,
898 		    "Cannot parse a numerical ID (base 10).");
899 		goto einval;
900 	}
901 
902 	/*
903 	 * We will now parse the "to" list.
904 	 *
905 	 * In order to ease parsing, we will begin by building lists of target
906 	 * UIDs and GIDs in local variables 'uid_list' and 'gid_list'.  The
907 	 * number of each type of IDs will be filled directly in 'new'.  At end
908 	 * of parse, we will allocate both arrays of IDs to be placed into the
909 	 * 'uids' and 'gids' members, sort them, and discard the tail queues
910 	 * used to build them.  This conversion to sorted arrays at end of parse
911 	 * allows to minimize memory allocations and enables searching IDs in
912 	 * O(log(n)) instead of linearly.
913 	 */
914 	to_list = strsep_noblanks(&rule, ",");
915 	if (to_list == NULL) {
916 		make_parse_error(parse_error, 0, "No target list.");
917 		goto einval;
918 	}
919 	do {
920 		error = parse_target_clause(to_list, new, &uid_list, &gid_list,
921 		    parse_error);
922 		if (error != 0) {
923 			(*parse_error)->pos += to_list - start;
924 			goto einval;
925 		}
926 
927 		to_list = strsep_noblanks(&rule, ",");
928 	} while (to_list != NULL);
929 
930 	if (new->uids_nb != 0) {
931 		new->uids = malloc(sizeof(*new->uids) * new->uids_nb, M_DO,
932 		    M_WAITOK);
933 		error = pour_list_into_rule(IT_UID, &uid_list, new->uids,
934 		    &new->uids_nb, parse_error);
935 		if (error != 0)
936 			goto einval;
937 	}
938 	MPASS(STAILQ_EMPTY(&uid_list));
939 	if (!has_clauses(new->uids_nb, new->uid_flags)) {
940 		/* No UID specified, default is "uid=.". */
941 		MPASS(new->uid_flags == 0);
942 		new->uid_flags = MDF_CURRENT;
943 		check_type_and_type_flags(IT_UID, new->uid_flags);
944 	}
945 
946 	if (new->gids_nb != 0) {
947 		new->gids = malloc(sizeof(*new->gids) * new->gids_nb, M_DO,
948 		    M_WAITOK);
949 		error = pour_list_into_rule(IT_GID, &gid_list, new->gids,
950 		    &new->gids_nb, parse_error);
951 		if (error != 0)
952 			goto einval;
953 	}
954 	MPASS(STAILQ_EMPTY(&gid_list));
955 	if (!has_clauses(new->gids_nb, new->gid_flags)) {
956 		/* No GID specified, default is "gid=.,!gid=.". */
957 		MPASS(new->gid_flags == 0);
958 		new->gid_flags = MDF_CURRENT | MDF_PRIMARY | MDF_SUPP_MUST |
959 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
960 		check_type_and_type_flags(IT_GID, new->gid_flags);
961 	}
962 
963 	STAILQ_INSERT_TAIL(&rules->head, new, r_entries);
964 	return (0);
965 
966 einval:
967 	free(new->gids, M_DO);
968 	free(new->uids, M_DO);
969 	free(new, M_DO);
970 	STAILQ_FOREACH_SAFE(ie, &gid_list, ie_entries, ie_next)
971 	    free(ie, M_DO);
972 	STAILQ_FOREACH_SAFE(ie, &uid_list, ie_entries, ie_next)
973 	    free(ie, M_DO);
974 	MPASS(*parse_error != NULL);
975 	return (EINVAL);
976 }
977 
978 /*
979  * Parse rules specification and produce rule structures out of it.
980  *
981  * Returns 0 on success, with '*rulesp' made to point to a 'struct rule'
982  * representing the rules.  On error, the returned value is non-zero and
983  * '*rulesp' is unchanged.  If 'string' has length greater or equal to
984  * MAC_RULE_STRING_LEN, ENAMETOOLONG is returned.  If it is not in the expected
985  * format, EINVAL is returned.  If an error is returned, '*parse_error' is set
986  * to point to a 'struct parse_error' giving an error message for the problem,
987  * else '*parse_error' is set to NULL.
988  *
989  * Expected format: A semi-colon-separated list of rules of the form
990  * "<from>:<target>".  The <from> part is of the form "<type>=<id>" where <type>
991  * is "uid" or "gid", <id> an UID or GID (depending on <type>) and <target> is
992  * "*", "any" or a comma-separated list of '<flags><type>=<id>' clauses (see the
993  * comment for parse_single_rule() for more details).  For convenience, empty
994  * rules are allowed (and do nothing), and spaces and tabs are allowed (and
995  * removed) around each token (tokens are natural ones, except that
996  * '<flags><type>' as a whole is considered a single token, so no blanks are
997  * allowed between '<flags>' and '<type>').
998  *
999  * Examples:
1000  * - "uid=1001:uid=1010,gid=1010;uid=1002:any"
1001  * - "gid=1010:gid=1011,gid=1012,gid=1013"
1002  */
1003 static int
1004 parse_rules(const char *const string, struct rules **const rulesp,
1005     struct parse_error **const parse_error)
1006 {
1007 	const size_t len = strlen(string);
1008 	char *copy, *p, *rule;
1009 	struct rules *rules;
1010 	int error = 0;
1011 
1012 	*parse_error = NULL;
1013 
1014 	if (len >= MAC_RULE_STRING_LEN) {
1015 		make_parse_error(parse_error, 0,
1016 		    "Rule specification string is too long (%zu, max %zu)",
1017 		    len, MAC_RULE_STRING_LEN - 1);
1018 		return (ENAMETOOLONG);
1019 	}
1020 
1021 	rules = alloc_rules();
1022 	bcopy(string, rules->string, len + 1);
1023 	MPASS(rules->string[len] == '\0'); /* Catch some races. */
1024 
1025 	copy = malloc(len + 1, M_DO, M_WAITOK);
1026 	bcopy(string, copy, len + 1);
1027 	MPASS(copy[len] == '\0'); /* Catch some races. */
1028 
1029 	p = copy;
1030 	while ((rule = strsep_noblanks(&p, ";")) != NULL) {
1031 		if (rule[0] == '\0')
1032 			continue;
1033 		error = parse_single_rule(rule, rules, parse_error);
1034 		if (error != 0) {
1035 			(*parse_error)->pos += rule - copy;
1036 			toast_rules(rules);
1037 			goto out;
1038 		}
1039 	}
1040 
1041 	*rulesp = rules;
1042 out:
1043 	free(copy, M_DO);
1044 	return (error);
1045 }
1046 
1047 /*
1048  * Find rules applicable to the passed prison.
1049  *
1050  * Returns the applicable rules (and never NULL).  'pr' must be unlocked.
1051  * 'aprp' is set to the (ancestor) prison holding these, and it must be unlocked
1052  * once the caller is done accessing the rules.  '*aprp' is equal to 'pr' if and
1053  * only if the current jail has its own set of rules.
1054  */
1055 static struct rules *
1056 find_rules(struct prison *const pr, struct prison **const aprp)
1057 {
1058 	struct prison *cpr, *ppr;
1059 	struct rules *rules;
1060 
1061 	cpr = pr;
1062 	for (;;) {
1063 		prison_lock(cpr);
1064 		rules = osd_jail_get(cpr, osd_jail_slot);
1065 		if (rules != NULL)
1066 			break;
1067 		prison_unlock(cpr);
1068 
1069 		ppr = cpr->pr_parent;
1070 		MPASS(ppr != NULL); /* prison0 always has rules. */
1071 		cpr = ppr;
1072 	}
1073 
1074 	*aprp = cpr;
1075 	return (rules);
1076 }
1077 
1078 static void
1079 hold_rules(struct rules *const rules)
1080 {
1081 	refcount_acquire(&rules->use_count);
1082 }
1083 
1084 static void
1085 drop_rules(struct rules *const rules)
1086 {
1087 	if (refcount_release(&rules->use_count))
1088 		toast_rules(rules);
1089 }
1090 
1091 #ifdef INVARIANTS
1092 static void
1093 check_rules_use_count(const struct rules *const rules, u_int expected)
1094 {
1095 	const u_int use_count = refcount_load(&rules->use_count);
1096 
1097 	if (use_count != expected)
1098 		panic("MAC/do: Rules at %p: Use count is %u, expected %u",
1099 		    rules, use_count, expected);
1100 }
1101 #else
1102 #define check_rules_use_count(...)
1103 #endif /* INVARIANTS */
1104 
1105 /*
1106  * OSD destructor for slot 'osd_jail_slot'.
1107  *
1108  * Called with 'value' not NULL.  We have arranged that it is only ever called
1109  * when the corresponding jail goes down or at module unload.
1110  */
1111 static void
1112 dealloc_jail_osd(void *const value)
1113 {
1114 	struct rules *const rules = value;
1115 
1116 	/*
1117 	 * If called because the "holding" jail goes down, no one should be
1118 	 * using the rules but us at this point because no threads of that jail
1119 	 * (or its sub-jails) should currently be executing (in particular,
1120 	 * currently executing setcred()).  The case of module unload is more
1121 	 * complex.  Although the MAC framework takes care that no hook is
1122 	 * called while a module is unloading, the unload could happen between
1123 	 * two calls to MAC hooks in the course of, e.g., executing setcred(),
1124 	 * where the rules' reference count has been bumped to keep them alive
1125 	 * even if the rules on the "holding" jail has been concurrently
1126 	 * changed.  These other references are held in our thread OSD slot, so
1127 	 * we ensure that all thread's slots are freed first in mac_do_destroy()
1128 	 * to be able to check that only one reference remains.
1129 	 */
1130 	check_rules_use_count(rules, 1);
1131 	toast_rules(rules);
1132 }
1133 
1134 /*
1135  * Remove the rules specifically associated to a prison.
1136  *
1137  * In practice, this means that the rules become inherited (from the closest
1138  * ascendant that has some).
1139  *
1140  * Destroys the 'osd_jail_slot' slot of the passed jail.
1141  */
1142 static void
1143 remove_rules(struct prison *const pr)
1144 {
1145 	struct rules *old_rules;
1146 	int error __unused;
1147 
1148 	prison_lock(pr);
1149 	/*
1150 	 * We go to the burden of extracting rules first instead of just letting
1151 	 * osd_jail_del() calling dealloc_jail_osd() as we want to decrement
1152 	 * their use count, and possibly free them, outside of the prison lock.
1153 	 */
1154 	old_rules = osd_jail_get(pr, osd_jail_slot);
1155 	error = osd_jail_set(pr, osd_jail_slot, NULL);
1156 	/* osd_set() never fails nor allocate memory when 'value' is NULL. */
1157 	MPASS(error == 0);
1158 	/*
1159 	 * This completely frees the OSD slot, but doesn't call the destructor
1160 	 * since we've just put NULL in the slot.
1161 	 */
1162 	osd_jail_del(pr, osd_jail_slot);
1163 	prison_unlock(pr);
1164 
1165 	if (old_rules != NULL)
1166 		drop_rules(old_rules);
1167 }
1168 
1169 /*
1170  * Assign already built rules to a jail.
1171  */
1172 static void
1173 set_rules(struct prison *const pr, struct rules *const rules)
1174 {
1175 	struct rules *old_rules;
1176 	void **rsv;
1177 
1178 	check_rules_use_count(rules, 0);
1179 	hold_rules(rules);
1180 	rsv = osd_reserve(osd_jail_slot);
1181 
1182 	prison_lock(pr);
1183 	old_rules = osd_jail_get(pr, osd_jail_slot);
1184 	osd_jail_set_reserved(pr, osd_jail_slot, rsv, rules);
1185 	prison_unlock(pr);
1186 	if (old_rules != NULL)
1187 		drop_rules(old_rules);
1188 }
1189 
1190 /*
1191  * Assigns empty rules to a jail.
1192  */
1193 static void
1194 set_empty_rules(struct prison *const pr)
1195 {
1196 	struct rules *const rules = alloc_rules();
1197 
1198 	set_rules(pr, rules);
1199 }
1200 
1201 /*
1202  * Parse a rules specification and assign them to a jail.
1203  *
1204  * Returns the same error code as parse_rules() (which see).
1205  */
1206 static int
1207 parse_and_set_rules(struct prison *const pr, const char *rules_string,
1208     struct parse_error **const parse_error)
1209 {
1210 	struct rules *rules;
1211 	int error;
1212 
1213 	error = parse_rules(rules_string, &rules, parse_error);
1214 	if (error != 0)
1215 		return (error);
1216 	set_rules(pr, rules);
1217 	return (0);
1218 }
1219 
1220 static int
1221 mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS)
1222 {
1223 	char *const buf = malloc(MAC_RULE_STRING_LEN, M_DO, M_WAITOK);
1224 	struct prison *const td_pr = req->td->td_ucred->cr_prison;
1225 	struct prison *pr;
1226 	struct rules *rules;
1227 	struct parse_error *parse_error;
1228 	int error;
1229 
1230 	rules = find_rules(td_pr, &pr);
1231 	strlcpy(buf, rules->string, MAC_RULE_STRING_LEN);
1232 	prison_unlock(pr);
1233 
1234 	error = sysctl_handle_string(oidp, buf, MAC_RULE_STRING_LEN, req);
1235 	if (error != 0 || req->newptr == NULL)
1236 		goto out;
1237 
1238 	/* Set our prison's rules, not that of the jail we inherited from. */
1239 	error = parse_and_set_rules(td_pr, buf, &parse_error);
1240 	if (error != 0) {
1241 		if (print_parse_error)
1242 			printf("MAC/do: Parse error at index %zu: %s\n",
1243 			    parse_error->pos, parse_error->msg);
1244 		free_parse_error(parse_error);
1245 	}
1246 out:
1247 	free(buf, M_DO);
1248 	return (error);
1249 }
1250 
1251 SYSCTL_PROC(_security_mac_do, OID_AUTO, rules,
1252     CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON|CTLFLAG_MPSAFE,
1253     0, 0, mac_do_sysctl_rules, "A",
1254     "Rules");
1255 
1256 
1257 SYSCTL_JAIL_PARAM_SYS_SUBNODE(mac, do, CTLFLAG_RW, "Jail MAC/do parameters");
1258 SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAC_RULE_STRING_LEN,
1259     "Jail MAC/do rules");
1260 
1261 
1262 static int
1263 mac_do_jail_create(void *obj, void *data __unused)
1264 {
1265 	struct prison *const pr = obj;
1266 
1267 	set_empty_rules(pr);
1268 	return (0);
1269 }
1270 
1271 static int
1272 mac_do_jail_get(void *obj, void *data)
1273 {
1274 	struct prison *ppr, *const pr = obj;
1275 	struct vfsoptlist *const opts = data;
1276 	struct rules *rules;
1277 	int jsys, error;
1278 
1279 	rules = find_rules(pr, &ppr);
1280 
1281 	jsys = pr == ppr ?
1282 	    (STAILQ_EMPTY(&rules->head) ? JAIL_SYS_DISABLE : JAIL_SYS_NEW) :
1283 	    JAIL_SYS_INHERIT;
1284 	error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys));
1285 	if (error != 0 && error != ENOENT)
1286 		goto done;
1287 
1288 	error = vfs_setopts(opts, "mac.do.rules", rules->string);
1289 	if (error != 0 && error != ENOENT)
1290 		goto done;
1291 
1292 	error = 0;
1293 done:
1294 	prison_unlock(ppr);
1295 	return (error);
1296 }
1297 
1298 /*
1299  * -1 is used as a sentinel in mac_do_jail_check() and mac_do_jail_set() below.
1300  */
1301 _Static_assert(-1 != JAIL_SYS_DISABLE && -1 != JAIL_SYS_NEW &&
1302     -1 != JAIL_SYS_INHERIT,
1303     "mac_do(4) uses -1 as a sentinel for uninitialized 'jsys'.");
1304 
1305 /*
1306  * We perform only cheap checks here, i.e., we do not really parse the rules
1307  * specification string, if any.
1308  */
1309 static int
1310 mac_do_jail_check(void *obj, void *data)
1311 {
1312 	struct vfsoptlist *opts = data;
1313 	char *rules_string;
1314 	int error, jsys, size;
1315 
1316 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1317 	if (error == ENOENT)
1318 		jsys = -1;
1319 	else {
1320 		if (error != 0)
1321 			return (error);
1322 		if (jsys != JAIL_SYS_DISABLE && jsys != JAIL_SYS_NEW &&
1323 		    jsys != JAIL_SYS_INHERIT)
1324 			return (EINVAL);
1325 	}
1326 
1327 	/*
1328 	 * We use vfs_getopt() here instead of vfs_getopts() to get the length.
1329 	 * We perform the additional checks done by the latter here, even if
1330 	 * jail_set() calls vfs_getopts() itself later (they becoming
1331 	 * inconsistent wouldn't cause any security problem).
1332 	 */
1333 	error = vfs_getopt(opts, "mac.do.rules", (void**)&rules_string, &size);
1334 	if (error == ENOENT) {
1335 		/*
1336 		 * Default (in absence of "mac.do.rules") is to disable (and, in
1337 		 * particular, not inherit).
1338 		 */
1339 		if (jsys == -1)
1340 			jsys = JAIL_SYS_DISABLE;
1341 
1342 		if (jsys == JAIL_SYS_NEW) {
1343 			vfs_opterror(opts, "'mac.do.rules' must be specified "
1344 			    "given 'mac.do''s value");
1345 			return (EINVAL);
1346 		}
1347 
1348 		/* Absence of "mac.do.rules" at this point is OK. */
1349 		error = 0;
1350 	} else {
1351 		if (error != 0)
1352 			return (error);
1353 
1354 		/* Not a proper string. */
1355 		if (size == 0 || rules_string[size - 1] != '\0') {
1356 			vfs_opterror(opts, "'mac.do.rules' not a proper string");
1357 			return (EINVAL);
1358 		}
1359 
1360 		if (size > MAC_RULE_STRING_LEN) {
1361 			vfs_opterror(opts, "'mdo.rules' too long");
1362 			return (ENAMETOOLONG);
1363 		}
1364 
1365 		if (jsys == -1)
1366 			/* Default (if "mac.do.rules" is present). */
1367 			jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE :
1368 			    JAIL_SYS_NEW;
1369 
1370 		/*
1371 		 * Be liberal and accept JAIL_SYS_DISABLE and JAIL_SYS_INHERIT
1372 		 * with an explicit empty rules specification.
1373 		 */
1374 		switch (jsys) {
1375 		case JAIL_SYS_DISABLE:
1376 		case JAIL_SYS_INHERIT:
1377 			if (rules_string[0] != '\0') {
1378 				vfs_opterror(opts, "'mac.do.rules' specified "
1379 				    "but should not given 'mac.do''s value");
1380 				return (EINVAL);
1381 			}
1382 			break;
1383 		}
1384 	}
1385 
1386 	return (error);
1387 }
1388 
1389 static int
1390 mac_do_jail_set(void *obj, void *data)
1391 {
1392 	struct prison *pr = obj;
1393 	struct vfsoptlist *opts = data;
1394 	char *rules_string;
1395 	struct parse_error *parse_error;
1396 	int error, jsys;
1397 
1398 	/*
1399 	 * The invariants checks used below correspond to what has already been
1400 	 * checked in jail_check() above.
1401 	 */
1402 
1403 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1404 	MPASS(error == 0 || error == ENOENT);
1405 	if (error != 0)
1406 		jsys = -1; /* Mark unfilled. */
1407 
1408 	rules_string = vfs_getopts(opts, "mac.do.rules", &error);
1409 	MPASS(error == 0 || error == ENOENT);
1410 	if (error == 0) {
1411 		MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN);
1412 		if (jsys == -1)
1413 			/* Default (if "mac.do.rules" is present). */
1414 			jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE :
1415 			    JAIL_SYS_NEW;
1416 		else
1417 			MPASS(jsys == JAIL_SYS_NEW ||
1418 			    ((jsys == JAIL_SYS_DISABLE ||
1419 			    jsys == JAIL_SYS_INHERIT) &&
1420 			    rules_string[0] == '\0'));
1421 	} else {
1422 		MPASS(jsys != JAIL_SYS_NEW);
1423 		if (jsys == -1)
1424 			/*
1425 			 * Default (in absence of "mac.do.rules") is to disable
1426 			 * (and, in particular, not inherit).
1427 			 */
1428 			jsys = JAIL_SYS_DISABLE;
1429 		/* If disabled, we'll store an empty rule specification. */
1430 		if (jsys == JAIL_SYS_DISABLE)
1431 			rules_string = "";
1432 	}
1433 
1434 	switch (jsys) {
1435 	case JAIL_SYS_INHERIT:
1436 		remove_rules(pr);
1437 		error = 0;
1438 		break;
1439 	case JAIL_SYS_DISABLE:
1440 	case JAIL_SYS_NEW:
1441 		error = parse_and_set_rules(pr, rules_string, &parse_error);
1442 		if (error != 0) {
1443 			vfs_opterror(opts,
1444 			    "MAC/do: Parse error at index %zu: %s\n",
1445 			    parse_error->pos, parse_error->msg);
1446 			free_parse_error(parse_error);
1447 		}
1448 		break;
1449 	default:
1450 		__assert_unreachable();
1451 	}
1452 	return (error);
1453 }
1454 
1455 /*
1456  * OSD jail methods.
1457  *
1458  * There is no PR_METHOD_REMOVE, as OSD storage is destroyed by the common jail
1459  * code (see prison_cleanup()), which triggers a run of our dealloc_jail_osd()
1460  * destructor.
1461  */
1462 static const osd_method_t osd_methods[PR_MAXMETHOD] = {
1463 	[PR_METHOD_CREATE] = mac_do_jail_create,
1464 	[PR_METHOD_GET] = mac_do_jail_get,
1465 	[PR_METHOD_CHECK] = mac_do_jail_check,
1466 	[PR_METHOD_SET] = mac_do_jail_set,
1467 };
1468 
1469 
1470 /*
1471  * Common header structure.
1472  *
1473  * Each structure that is used to pass information between some MAC check
1474  * function and priv_grant() must start with this header.
1475  */
1476 struct mac_do_data_header {
1477 	/* Size of the allocated buffer holding the containing structure. */
1478 	size_t		 allocated_size;
1479 	/* Full size of the containing structure. */
1480 	size_t		 size;
1481 	/*
1482 	 * For convenience, we use privilege numbers as an identifier for the
1483 	 * containing structure's type, since there is one distinct privilege
1484 	 * for each privilege changing function we are supporting.  0 in 'priv'
1485 	 * indicates this header is uninitialized.
1486 	 */
1487 	int		 priv;
1488 	/* Rules to apply. */
1489 	struct rules	*rules;
1490 };
1491 
1492 /*
1493  * The case of unusable or absent per-thread data can actually happen as nothing
1494  * prevents, e.g., priv_check*() with privilege 'priv' to be called standalone,
1495  * as it is currently by, e.g., the Linux emulator for PRIV_CRED_SETUID.  We
1496  * interpret such calls to priv_check*() as full, unrestricted requests for
1497  * 'priv', contrary to what we're doing here for selected operations, and
1498  * consequently will not grant the requested privilege.
1499  *
1500  * Also, we protect ourselves from a concurrent change of 'do_enabled' while
1501  * a call to setcred() is in progress by storing the rules per-thread
1502  * which is then consulted by each successive hook so that they all have
1503  * a coherent view of the specifications, and we empty the slot (actually, mark
1504  * it as empty) when MAC/do is disabled.
1505  */
1506 static int
1507 check_data_usable(const void *const data, const size_t size, const int priv)
1508 {
1509 	const struct mac_do_data_header *const hdr = data;
1510 
1511 	if (hdr == NULL || hdr->priv == 0)
1512 		return (ENOENT);
1513 	/*
1514 	 * Impacting changes in the protocols we are based on...  Don't crash in
1515 	 * production.
1516 	 */
1517 	if (hdr->priv != priv) {
1518 		MPASS(hdr->priv == priv);
1519 		return (EBUSY);
1520 	}
1521 	MPASS(hdr->size == size);
1522 	MPASS(hdr->size <= hdr->allocated_size);
1523 	return (0);
1524 }
1525 
1526 static void
1527 clear_data(void *const data)
1528 {
1529 	struct mac_do_data_header *const hdr = data;
1530 
1531 	if (hdr != NULL) {
1532 		drop_rules(hdr->rules);
1533 		/* We don't deallocate so as to save time on next access. */
1534 		hdr->priv = 0;
1535 	}
1536 }
1537 
1538 static void *
1539 fetch_data(void)
1540 {
1541 	return (osd_thread_get_unlocked(curthread, osd_thread_slot));
1542 }
1543 
1544 static bool
1545 is_data_reusable(const void *const data, const size_t size)
1546 {
1547 	const struct mac_do_data_header *const hdr = data;
1548 
1549 	return (hdr != NULL && size <= hdr->allocated_size);
1550 }
1551 
1552 static void
1553 set_data_header(void *const data, const size_t size, const int priv,
1554     struct rules *const rules)
1555 {
1556 	struct mac_do_data_header *const hdr = data;
1557 
1558 	MPASS(hdr->priv == 0);
1559 	MPASS(priv != 0);
1560 	MPASS(size <= hdr->allocated_size);
1561 	hdr->size = size;
1562 	hdr->priv = priv;
1563 	hdr->rules = rules;
1564 }
1565 
1566 /* The proc lock (and any other non-sleepable lock) must not be held. */
1567 static void *
1568 alloc_data(void *const data, const size_t size)
1569 {
1570 	struct mac_do_data_header *const hdr = realloc(data, size, M_DO,
1571 	    M_WAITOK);
1572 
1573 	MPASS(size >= sizeof(struct mac_do_data_header));
1574 	hdr->allocated_size = size;
1575 	hdr->priv = 0;
1576 	if (hdr != data) {
1577 		/*
1578 		 * This call either reuses the existing memory allocated for the
1579 		 * slot or tries to allocate some without blocking.
1580 		 */
1581 		int error = osd_thread_set(curthread, osd_thread_slot, hdr);
1582 
1583 		if (error != 0) {
1584 			/* Going to make a M_WAITOK allocation. */
1585 			void **const rsv = osd_reserve(osd_thread_slot);
1586 
1587 			error = osd_thread_set_reserved(curthread,
1588 			    osd_thread_slot, rsv, hdr);
1589 			MPASS(error == 0);
1590 		}
1591 	}
1592 	return (hdr);
1593 }
1594 
1595 /* Destructor for 'osd_thread_slot'. */
1596 static void
1597 dealloc_thread_osd(void *const value)
1598 {
1599 	free(value, M_DO);
1600 }
1601 
1602 /*
1603  * Whether to grant access to some primary group according to flags.
1604  *
1605  * The passed 'flags' must be those of a rule's matching GID, or the IT_GID type
1606  * flags when MDF_CURRENT has been matched.
1607  *
1608  * Return values:
1609  * - 0:			Access granted.
1610  * - EJUSTRETURN:	Flags are agnostic.
1611  */
1612 static int
1613 grant_primary_group_from_flags(const flags_t flags)
1614 {
1615 	return ((flags & MDF_PRIMARY) != 0 ? 0 : EJUSTRETURN);
1616 }
1617 
1618 /*
1619  * Same as grant_primary_group_from_flags(), but for supplementary groups.
1620  *
1621  * Return values:
1622  * - 0:			Access granted.
1623  * - EJUSTRETURN:	Flags are agnostic.
1624  * - EPERM:		Access denied.
1625  */
1626 static int
1627 grant_supplementary_group_from_flags(const flags_t flags)
1628 {
1629 	if ((flags & MDF_SUPP_MASK) != 0)
1630 		return ((flags & MDF_SUPP_DONT) != 0 ? EPERM : 0);
1631 
1632 	return (EJUSTRETURN);
1633 }
1634 
1635 static int
1636 rule_grant_supplementary_groups(const struct rule *const rule,
1637     const struct ucred *const old_cred, const struct ucred *const new_cred)
1638 {
1639 	const gid_t *const old_groups = old_cred->cr_groups;
1640 	const gid_t *const new_groups = new_cred->cr_groups;
1641 	const int old_ngroups = old_cred->cr_ngroups;
1642 	const int new_ngroups = new_cred->cr_ngroups;
1643 	const flags_t gid_flags = rule->gid_flags;
1644 	const bool current_has_supp = (gid_flags & MDF_CURRENT) != 0 &&
1645 	    (gid_flags & MDF_SUPP_MASK) != 0;
1646 	id_nb_t rule_idx = 0;
1647 	int old_idx = 1, new_idx = 1;
1648 
1649 	if ((gid_flags & MDF_ANY_SUPP) != 0 &&
1650 	    (gid_flags & MDF_MAY_REJ_SUPP) == 0)
1651 		/*
1652 		 * Any set of supplementary groups is accepted, no need to loop
1653 		 * over them.
1654 		 */
1655 		return (0);
1656 
1657 	for (; new_idx < new_ngroups; ++new_idx) {
1658 		const gid_t gid = new_groups[new_idx];
1659 		bool may_accept = false;
1660 
1661 		if ((gid_flags & MDF_ANY_SUPP) != 0)
1662 			may_accept = true;
1663 
1664 		/* Do we have to check for the current supplementary groups? */
1665 		if (current_has_supp) {
1666 			/*
1667 			 * Linear search, as both supplementary groups arrays
1668 			 * are sorted.  Advancing 'old_idx' with a binary search
1669 			 * on absence of MDF_SUPP_MUST doesn't seem worth it in
1670 			 * practice.
1671 			 */
1672 			for (; old_idx < old_ngroups; ++old_idx) {
1673 				const gid_t old_gid = old_groups[old_idx];
1674 
1675 				if (old_gid < gid) {
1676 					/* Mandatory but absent. */
1677 					if ((gid_flags & MDF_SUPP_MUST) != 0)
1678 						return (EPERM);
1679 				} else if (old_gid == gid) {
1680 					switch (gid_flags & MDF_SUPP_MASK) {
1681 					case MDF_SUPP_DONT:
1682 						/* Present but forbidden. */
1683 						return (EPERM);
1684 					case MDF_SUPP_ALLOW:
1685 					case MDF_SUPP_MUST:
1686 						may_accept = true;
1687 						break;
1688 					default:
1689 #ifdef INVARIANTS
1690 						__assert_unreachable();
1691 #else
1692 						/* Better be safe than sorry. */
1693 						return (EPERM);
1694 #endif
1695 					}
1696 					++old_idx;
1697 					break;
1698 				}
1699 				else
1700 					break;
1701 			}
1702 		}
1703 
1704 		/*
1705 		 * Search by GID for a corresponding 'struct id_spec'.
1706 		 *
1707 		 * Again, linear search, with same note on not using binary
1708 		 * search optimization as above (the trigger would be absence of
1709 		 * MDF_EXPLICIT_SUPP_MUST this time).
1710 		 */
1711 		for (; rule_idx < rule->gids_nb; ++rule_idx) {
1712 			const struct id_spec is = rule->gids[rule_idx];
1713 
1714 			if (is.id < gid) {
1715 				/* Mandatory but absent. */
1716 				if ((is.flags & MDF_SUPP_MUST) != 0)
1717 					return (EPERM);
1718 			} else if (is.id == gid) {
1719 				switch (is.flags & MDF_SUPP_MASK) {
1720 				case MDF_SUPP_DONT:
1721 					/* Present but forbidden. */
1722 					return (EPERM);
1723 				case MDF_SUPP_ALLOW:
1724 				case MDF_SUPP_MUST:
1725 					may_accept = true;
1726 					break;
1727 				case 0:
1728 					/* Primary group only. */
1729 					break;
1730 				default:
1731 #ifdef INVARIANTS
1732 					__assert_unreachable();
1733 #else
1734 					/* Better be safe than sorry. */
1735 					return (EPERM);
1736 #endif
1737 				}
1738 				++rule_idx;
1739 				break;
1740 			}
1741 			else
1742 				break;
1743 		}
1744 
1745 		/* 'gid' wasn't explicitly accepted. */
1746 		if (!may_accept)
1747 			return (EPERM);
1748 	}
1749 
1750 	/*
1751 	 * If we must have all current groups and we didn't browse all
1752 	 * of them at this point (because the remaining ones have GIDs
1753 	 * greater than the last requested group), we are simply missing
1754 	 * them.
1755 	 */
1756 	if ((gid_flags & MDF_CURRENT) != 0 &&
1757 	    (gid_flags & MDF_SUPP_MUST) != 0 &&
1758 	    old_idx < old_ngroups)
1759 		return (EPERM);
1760 	/*
1761 	 * Similarly, we have to finish browsing all GIDs from the rule
1762 	 * in case some are marked mandatory.
1763 	 */
1764 	if ((gid_flags & MDF_EXPLICIT_SUPP_MUST) != 0) {
1765 		for (; rule_idx < rule->gids_nb; ++rule_idx) {
1766 			const struct id_spec is = rule->gids[rule_idx];
1767 
1768 			if ((is.flags & MDF_SUPP_MUST) != 0)
1769 				return (EPERM);
1770 		}
1771 	}
1772 
1773 	return (0);
1774 }
1775 
1776 static int
1777 rule_grant_primary_group(const struct rule *const rule,
1778     const struct ucred *const old_cred, const gid_t gid)
1779 {
1780 	struct id_spec gid_is = {.flags = 0};
1781 	const struct id_spec *found_is;
1782 	int error;
1783 
1784 	if ((rule->gid_flags & MDF_ANY) != 0)
1785 		return (0);
1786 
1787 	/* Was MDF_CURRENT specified, and is 'gid' a current GID? */
1788 	if ((rule->gid_flags & MDF_CURRENT) != 0 &&
1789 	    group_is_primary(gid, old_cred)) {
1790 		error = grant_primary_group_from_flags(rule->gid_flags);
1791 		if (error == 0)
1792 			return (0);
1793 	}
1794 
1795 	/* Search by GID for a corresponding 'struct id_spec'. */
1796 	gid_is.id = gid;
1797 	found_is = bsearch(&gid_is, rule->gids, rule->gids_nb,
1798 	    sizeof(*rule->gids), id_spec_cmp);
1799 
1800 	if (found_is != NULL) {
1801 		error = grant_primary_group_from_flags(found_is->flags);
1802 		if (error == 0)
1803 			return (0);
1804 	}
1805 
1806 	return (EPERM);
1807 }
1808 
1809 static int
1810 rule_grant_primary_groups(const struct rule *const rule,
1811     const struct ucred *const old_cred, const struct ucred *const new_cred)
1812 {
1813 	int error;
1814 
1815 	/* Shortcut. */
1816 	if ((rule->gid_flags & MDF_ANY) != 0)
1817 		return (0);
1818 
1819 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_gid);
1820 	if (error != 0)
1821 		return (error);
1822 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_rgid);
1823 	if (error != 0)
1824 		return (error);
1825 	error = rule_grant_primary_group(rule, old_cred, new_cred->cr_svgid);
1826 	if (error != 0)
1827 		return (error);
1828 	return (0);
1829 }
1830 
1831 static bool
1832 user_is_current(const uid_t uid, const struct ucred *const old_cred)
1833 {
1834 	return (uid == old_cred->cr_uid || uid == old_cred->cr_ruid ||
1835 	    uid == old_cred->cr_svuid);
1836 }
1837 
1838 static int
1839 rule_grant_user(const struct rule *const rule,
1840     const struct ucred *const old_cred, const uid_t uid)
1841 {
1842 	struct id_spec uid_is = {.flags = 0};
1843 	const struct id_spec *found_is;
1844 
1845 	if ((rule->uid_flags & MDF_ANY) != 0)
1846 		return (0);
1847 
1848 	/* Was MDF_CURRENT specified, and is 'uid' a current UID? */
1849 	if ((rule->uid_flags & MDF_CURRENT) != 0 &&
1850 	    user_is_current(uid, old_cred))
1851 		return (0);
1852 
1853 	/* Search by UID for a corresponding 'struct id_spec'. */
1854 	uid_is.id = uid;
1855 	found_is = bsearch(&uid_is, rule->uids, rule->uids_nb,
1856 	    sizeof(*rule->uids), id_spec_cmp);
1857 
1858 	if (found_is != NULL)
1859 		return (0);
1860 
1861 	return (EPERM);
1862 }
1863 
1864 static int
1865 rule_grant_users(const struct rule *const rule,
1866     const struct ucred *const old_cred, const struct ucred *const new_cred)
1867 {
1868 	int error;
1869 
1870 	/* Shortcut. */
1871 	if ((rule->uid_flags & MDF_ANY) != 0)
1872 		return (0);
1873 
1874 	error = rule_grant_user(rule, old_cred, new_cred->cr_uid);
1875 	if (error != 0)
1876 		return (error);
1877 	error = rule_grant_user(rule, old_cred, new_cred->cr_ruid);
1878 	if (error != 0)
1879 		return (error);
1880 	error = rule_grant_user(rule, old_cred, new_cred->cr_svuid);
1881 	if (error != 0)
1882 		return (error);
1883 
1884 	return (0);
1885 }
1886 
1887 static int
1888 rule_grant_setcred(const struct rule *const rule,
1889     const struct ucred *const old_cred, const struct ucred *const new_cred)
1890 {
1891 	int error;
1892 
1893 	error = rule_grant_users(rule, old_cred, new_cred);
1894 	if (error != 0)
1895 		return (error);
1896 	error = rule_grant_primary_groups(rule, old_cred, new_cred);
1897 	if (error != 0)
1898 		return (error);
1899 	error = rule_grant_supplementary_groups(rule, old_cred, new_cred);
1900 	if (error != 0)
1901 		return (error);
1902 
1903 	return (0);
1904 }
1905 
1906 static bool
1907 rule_applies(const struct rule *const rule, const struct ucred *const cred)
1908 {
1909 	if (rule->from_type == IT_UID && rule->from_id == cred->cr_uid)
1910 		return (true);
1911 	if (rule->from_type == IT_GID && groupmember(rule->from_id, cred))
1912 		return (true);
1913 	return (false);
1914 }
1915 
1916 /*
1917  * To pass data between check_setcred() and priv_grant() (on PRIV_CRED_SETCRED).
1918  */
1919 struct mac_do_setcred_data {
1920 	struct mac_do_data_header hdr;
1921 	const struct ucred *new_cred;
1922 	u_int setcred_flags;
1923 };
1924 
1925 static int
1926 mac_do_priv_grant(struct ucred *cred, int priv)
1927 {
1928 	struct mac_do_setcred_data *const data = fetch_data();
1929 	const struct rules *rules;
1930 	const struct ucred *new_cred;
1931 	const struct rule *rule;
1932 	u_int setcred_flags;
1933 	int error;
1934 
1935 	/* Bail out fast if we aren't concerned. */
1936 	if (priv != PRIV_CRED_SETCRED)
1937 		return (EPERM);
1938 
1939 	/*
1940 	 * Do we have to do something?
1941 	 */
1942 	if (check_data_usable(data, sizeof(*data), priv) != 0)
1943 		/* No. */
1944 		return (EPERM);
1945 
1946 	rules = data->hdr.rules;
1947 	new_cred = data->new_cred;
1948 	KASSERT(new_cred != NULL,
1949 	    ("priv_check*() called before mac_cred_check_setcred()"));
1950 	setcred_flags = data->setcred_flags;
1951 
1952 	/*
1953 	 * Explicitly check that only the flags we currently support are present
1954 	 * in order to avoid accepting transitions with other changes than those
1955 	 * we are actually going to check.  Currently, this rules out the
1956 	 * SETCREDF_MAC_LABEL flag.  This may be improved by adding code
1957 	 * actually checking whether the requested label and the current one
1958 	 * would differ.
1959 	 */
1960 	if ((setcred_flags & ~(SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID |
1961 	    SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID |
1962 	    SETCREDF_SUPP_GROUPS)) != 0)
1963 		return (EPERM);
1964 
1965 	/*
1966 	 * Browse rules, and for those that match the requestor, call specific
1967 	 * privilege granting functions interpreting the "to"/"target" part.
1968 	 */
1969 	error = EPERM;
1970 	STAILQ_FOREACH(rule, &rules->head, r_entries)
1971 	    if (rule_applies(rule, cred)) {
1972 		    error = rule_grant_setcred(rule, cred, new_cred);
1973 		    if (error != EPERM)
1974 			    break;
1975 	    }
1976 
1977 	return (error);
1978 }
1979 
1980 static int
1981 check_proc(void)
1982 {
1983 	char *path, *to_free;
1984 	int error;
1985 
1986 	/*
1987 	 * Only grant privileges if requested by the right executable.
1988 	 *
1989 	 * XXXOC: We may want to base this check on a tunable path and/or
1990 	 * a specific MAC label.  Going even further, e.g., envisioning to
1991 	 * completely replace the path check with the latter, we would need to
1992 	 * install FreeBSD on a FS with multilabel enabled by default, which in
1993 	 * practice entails adding an option to ZFS to set MNT_MULTILABEL
1994 	 * automatically on mounts, ensuring that root (and more if using
1995 	 * different partitions) ZFS or UFS filesystems are created with
1996 	 * multilabel turned on, and having the installation procedure support
1997 	 * setting a MAC label per file (perhaps via additions to mtree(1)).  So
1998 	 * this probably isn't going to happen overnight, if ever.
1999 	 */
2000 	if (vn_fullpath(curproc->p_textvp, &path, &to_free) != 0)
2001 		return (EPERM);
2002 	error = strcmp(path, "/usr/bin/mdo") == 0 ? 0 : EPERM;
2003 	free(to_free, M_TEMP);
2004 	return (error);
2005 }
2006 
2007 static void
2008 mac_do_setcred_enter(void)
2009 {
2010 	struct rules *rules;
2011 	struct prison *pr;
2012 	struct mac_do_setcred_data * data;
2013 	int error;
2014 
2015 	/*
2016 	 * If not enabled, don't prepare data.  Other hooks will check for that
2017 	 * to know if they have to do something.
2018 	 */
2019 	if (do_enabled == 0)
2020 		return;
2021 
2022 	/*
2023 	 * MAC/do only applies to a process launched from a given executable.
2024 	 * For other processes, we just won't intervene (we don't deny requests,
2025 	 * nor do we grant privileges to them).
2026 	 */
2027 	error = check_proc();
2028 	if (error != 0)
2029 		return;
2030 
2031 	/*
2032 	 * Find the currently applicable rules.
2033 	 */
2034 	rules = find_rules(curproc->p_ucred->cr_prison, &pr);
2035 	hold_rules(rules);
2036 	prison_unlock(pr);
2037 
2038 	/*
2039 	 * Setup thread data to be used by other hooks.
2040 	 */
2041 	data = fetch_data();
2042 	if (!is_data_reusable(data, sizeof(*data)))
2043 		data = alloc_data(data, sizeof(*data));
2044 	set_data_header(data, sizeof(*data), PRIV_CRED_SETCRED, rules);
2045 	/* Not really necessary, but helps to catch programming errors. */
2046 	data->new_cred = NULL;
2047 	data->setcred_flags = 0;
2048 }
2049 
2050 static int
2051 mac_do_check_setcred(u_int flags, const struct ucred *const old_cred,
2052     struct ucred *const new_cred)
2053 {
2054 	struct mac_do_setcred_data *const data = fetch_data();
2055 
2056 	/*
2057 	 * Do we have to do something?
2058 	 */
2059 	if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) != 0)
2060 		/* No. */
2061 		return (0);
2062 
2063 	/*
2064 	 * Keep track of the setcred() flags and the new credentials for
2065 	 * priv_check*().
2066 	 */
2067 	data->new_cred = new_cred;
2068 	data->setcred_flags = flags;
2069 
2070 	return (0);
2071 }
2072 
2073 static void
2074 mac_do_setcred_exit(void)
2075 {
2076 	struct mac_do_setcred_data *const data = fetch_data();
2077 
2078 	if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) == 0)
2079 		/*
2080 		 * This doesn't deallocate the small per-thread data storage,
2081 		 * which can be reused on subsequent calls.  (That data is of
2082 		 * course deallocated as the current thread dies or this module
2083 		 * is unloaded.)
2084 		 */
2085 		clear_data(data);
2086 }
2087 
2088 static void
2089 mac_do_init(struct mac_policy_conf *mpc)
2090 {
2091 	struct prison *pr;
2092 
2093 	osd_jail_slot = osd_jail_register(dealloc_jail_osd, osd_methods);
2094 	set_empty_rules(&prison0);
2095 	sx_slock(&allprison_lock);
2096 	TAILQ_FOREACH(pr, &allprison, pr_list)
2097 	    set_empty_rules(pr);
2098 	sx_sunlock(&allprison_lock);
2099 
2100 	osd_thread_slot = osd_thread_register(dealloc_thread_osd);
2101 }
2102 
2103 static void
2104 mac_do_destroy(struct mac_policy_conf *mpc)
2105 {
2106 	/*
2107 	 * osd_thread_deregister() must be called before osd_jail_deregister(),
2108 	 * for the reason explained in dealloc_jail_osd().
2109 	 */
2110 	osd_thread_deregister(osd_thread_slot);
2111 	osd_jail_deregister(osd_jail_slot);
2112 }
2113 
2114 static struct mac_policy_ops do_ops = {
2115 	.mpo_init = mac_do_init,
2116 	.mpo_destroy = mac_do_destroy,
2117 	.mpo_cred_setcred_enter = mac_do_setcred_enter,
2118 	.mpo_cred_check_setcred = mac_do_check_setcred,
2119 	.mpo_cred_setcred_exit = mac_do_setcred_exit,
2120 	.mpo_priv_grant = mac_do_priv_grant,
2121 };
2122 
2123 MAC_POLICY_SET(&do_ops, mac_do, "MAC/do", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
2124 MODULE_VERSION(mac_do, 1);
2125