xref: /freebsd/sys/security/mac_do/mac_do.c (revision 3d8d91a5b32c219c7ee47840dcacbaf8c7480267)
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 
49 #define IT_INVALID	0 /* Must stay 0. */
50 #define IT_UID		1
51 #define IT_GID		2
52 #define IT_ANY		3
53 #define IT_LAST		IT_ANY
54 
55 static const char *id_type_to_str[] = {
56 	[IT_INVALID]	= "invalid",
57 	[IT_UID]	= "uid",
58 	[IT_GID]	= "gid",
59 	/* See also parse_id_type(). */
60 	[IT_ANY]	= "*",
61 };
62 
63 #define PARSE_ERROR_SIZE	256
64 
65 struct parse_error {
66 	size_t	pos;
67 	char	msg[PARSE_ERROR_SIZE];
68 };
69 
70 /*
71  * We assume that 'uid_t' and 'gid_t' are aliases to 'u_int' in conversions
72  * required for parsing rules specification strings.
73  */
74 _Static_assert(sizeof(uid_t) == sizeof(u_int) && (uid_t)-1 >= 0 &&
75     sizeof(gid_t) == sizeof(u_int) && (gid_t)-1 >= 0,
76     "mac_do(4) assumes that 'uid_t' and 'gid_t' are aliases to 'u_int'");
77 
78 /*
79  * Internal flags.
80  *
81  * They either apply as per-type (t) or per-ID (i) but are conflated because all
82  * per-ID flags are also valid as per-type ones to qualify the "current" (".")
83  * per-type flag.  Also, some of them are in fact exclusive, but we use one-hot
84  * encoding for simplicity.
85  *
86  * There is currently room for "only" 16 bits.  As these flags are purely
87  * internal, they can be renumbered and/or their type changed as needed.
88  *
89  * See also the check_*() functions below.
90  */
91 typedef uint16_t	flags_t;
92 
93 /* (i,gid) Specification concerns primary groups. */
94 #define MDF_PRIMARY	(1u << 0)
95 /* (i,gid) Specification concerns supplementary groups. */
96 #define MDF_SUPP_ALLOW	(1u << 1)
97 /* (i,gid) Group must appear as a supplementary group. */
98 #define MDF_SUPP_MUST	(1u << 2)
99 /* (i,gid) Group must not appear as a supplementary group. */
100 #define MDF_SUPP_DONT	(1u << 3)
101 #define MDF_SUPP_MASK	(MDF_SUPP_ALLOW | MDF_SUPP_MUST | MDF_SUPP_DONT)
102 #define MDF_ID_MASK	(MDF_PRIMARY | MDF_SUPP_MASK)
103 
104 /*
105  * (t) All IDs allowed.
106  *
107  * For GIDs, MDF_ANY only concerns primary groups.  The MDF_PRIMARY and
108  * MDF_SUPP_* flags never apply to MDF_ANY, but can be present if MDF_CURRENT is
109  * present also, as usual.
110  */
111 #define MDF_ANY			(1u << 8)
112 /* (t) Current IDs allowed. */
113 #define MDF_CURRENT		(1u << 9)
114 #define MDF_TYPE_COMMON_MASK	(MDF_ANY | MDF_CURRENT)
115 /* (t,gid) All IDs allowed as supplementary groups. */
116 #define MDF_ANY_SUPP		(1u << 10)
117 /* (t,gid) Some ID or MDF_CURRENT has MDF_SUPP_MUST or MDF_SUPP_DONT. */
118 #define MDF_MAY_REJ_SUPP	(1u << 11)
119 /* (t,gid) Some explicit ID (not MDF_CURRENT) has MDF_SUPP_MUST. */
120 #define MDF_EXPLICIT_SUPP_MUST	(1u << 12)
121 /* (t,gid) Whether any target clause is about primary groups.  Used during
122  * parsing only. */
123 #define MDF_HAS_PRIMARY_CLAUSE	(1u << 13)
124 /* (t,gid) Whether any target clause is about supplementary groups.  Used during
125  * parsing only. */
126 #define MDF_HAS_SUPP_CLAUSE	(1u << 14)
127 #define MDF_TYPE_GID_MASK	(MDF_ANY_SUPP | MDF_MAY_REJ_SUPP |	\
128     MDF_EXPLICIT_SUPP_MUST | MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE)
129 #define MDF_TYPE_MASK		(MDF_TYPE_COMMON_MASK | MDF_TYPE_GID_MASK)
130 
131 /*
132  * Persistent structures.
133  */
134 
135 struct id_spec {
136 	u_int		 id;
137 	flags_t		 flags; /* See MDF_* above. */
138 };
139 
140 /*
141  * This limits the number of target clauses per type to 65535.  With the current
142  * value of MAC_RULE_STRING_LEN (1024), this is way more than enough anyway.
143  */
144 typedef uint16_t	 id_nb_t;
145 /* We only have a few IT_* types. */
146 typedef uint16_t	 id_type_t;
147 
148 struct rule {
149 	TAILQ_ENTRY(rule) r_entries;
150 	id_type_t	 from_type;
151 	u_int		 from_id;
152 	flags_t		 uid_flags; /* See MDF_* above. */
153 	id_nb_t		 uids_nb;
154 	flags_t		 gid_flags; /* See MDF_* above. */
155 	id_nb_t		 gids_nb;
156 	struct id_spec	*uids;
157 	struct id_spec	*gids;
158 };
159 
160 TAILQ_HEAD(rulehead, rule);
161 
162 struct rules {
163 	char		string[MAC_RULE_STRING_LEN];
164 	struct rulehead	head;
165 	volatile u_int	use_count __aligned(CACHE_LINE_SIZE);
166 };
167 
168 /*
169  * Temporary structures used to build a 'struct rule' above.
170  */
171 
172 struct id_elem {
173 	TAILQ_ENTRY(id_elem) ie_entries;
174 	struct id_spec spec;
175 };
176 
177 TAILQ_HEAD(id_list, id_elem);
178 
179 #ifdef INVARIANTS
180 static void
181 check_type(const id_type_t type)
182 {
183 	if (type > IT_LAST)
184 		panic("Invalid type number %u", type);
185 }
186 
187 static void
188 panic_for_unexpected_flags(const id_type_t type, const flags_t flags,
189     const char *const str)
190 {
191 	panic("ID type %s: Unexpected flags %u (%s), ", id_type_to_str[type],
192 	    flags, str);
193 }
194 
195 static void
196 check_type_and_id_flags(const id_type_t type, const flags_t flags)
197 {
198 	const char *str;
199 
200 	check_type(type);
201 	switch (type) {
202 	case IT_UID:
203 		if (flags != 0) {
204 			str = "only 0 allowed";
205 			goto unexpected_flags;
206 		}
207 		break;
208 	case IT_GID:
209 		if ((flags & ~MDF_ID_MASK) != 0) {
210 			str = "only bits in MDF_ID_MASK allowed";
211 			goto unexpected_flags;
212 		}
213 		if (!powerof2(flags & MDF_SUPP_MASK)) {
214 			str = "only a single flag in MDF_SUPP_MASK allowed";
215 			goto unexpected_flags;
216 		}
217 		break;
218 	default:
219 	    __assert_unreachable();
220 	}
221 	return;
222 
223 unexpected_flags:
224 	panic_for_unexpected_flags(type, flags, str);
225 }
226 
227 static void
228 check_type_and_id_spec(const id_type_t type, const struct id_spec *const is)
229 {
230 	check_type_and_id_flags(type, is->flags);
231 }
232 
233 static void
234 check_type_and_type_flags(const id_type_t type, const flags_t flags)
235 {
236 	const char *str;
237 
238 	check_type_and_id_flags(type, flags & MDF_ID_MASK);
239 	if ((flags & ~MDF_ID_MASK & ~MDF_TYPE_MASK) != 0) {
240 		str = "only MDF_ID_MASK | MDF_TYPE_MASK bits allowed";
241 		goto unexpected_flags;
242 	}
243 	if ((flags & MDF_ANY) != 0 && (flags & MDF_CURRENT) != 0 &&
244 	    (type == IT_UID || (flags & MDF_PRIMARY) != 0)) {
245 		str = "MDF_ANY and MDF_CURRENT are exclusive for UIDs "
246 		    "or primary group GIDs";
247 		goto unexpected_flags;
248 	}
249 	if ((flags & MDF_ANY_SUPP) != 0 && (flags & MDF_CURRENT) != 0 &&
250 	    (flags & MDF_SUPP_MASK) != 0) {
251 		str = "MDF_SUPP_ANY and MDF_CURRENT with supplementary "
252 		    "groups specification are exclusive";
253 		goto unexpected_flags;
254 	}
255 	if (((flags & MDF_PRIMARY) != 0 || (flags & MDF_ANY) != 0) &&
256 	    (flags & MDF_HAS_PRIMARY_CLAUSE) == 0) {
257 		str = "Presence of folded primary clause not reflected "
258 		    "by presence of MDF_HAS_PRIMARY_CLAUSE";
259 		goto unexpected_flags;
260 	}
261 	if (((flags & MDF_SUPP_MASK) != 0 || (flags & MDF_ANY_SUPP) != 0) &&
262 	    (flags & MDF_HAS_SUPP_CLAUSE) == 0) {
263 		str = "Presence of folded supplementary clause not reflected "
264 		    "by presence of MDF_HAS_SUPP_CLAUSE";
265 		goto unexpected_flags;
266 	}
267 	return;
268 
269 unexpected_flags:
270 	panic_for_unexpected_flags(type, flags, str);
271 }
272 #else /* !INVARIANTS */
273 #define check_type_and_id_flags(...)
274 #define check_type_and_id_spec(...)
275 #define check_type_and_type_flags(...)
276 #endif /* INVARIANTS */
277 
278 /*
279  * Returns EALREADY if both flags have some overlap, or EINVAL if flags are
280  * incompatible, else 0 with flags successfully merged into 'dest'.
281  */
282 static int
283 coalesce_id_flags(const flags_t src, flags_t *const dest)
284 {
285 	flags_t res;
286 
287 	if ((src & *dest) != 0)
288 		return (EALREADY);
289 
290 	res = src | *dest;
291 
292 	/* Check for compatibility of supplementary flags, and coalesce. */
293 	if ((res & MDF_SUPP_MASK) != 0) {
294 		/* MDF_SUPP_DONT incompatible with the rest. */
295 		if ((res & MDF_SUPP_DONT) != 0 && (res & MDF_SUPP_MASK &
296 		    ~MDF_SUPP_DONT) != 0)
297 			return (EINVAL);
298 		/*
299 		 * Coalesce MDF_SUPP_ALLOW and MDF_SUPP_MUST into MDF_SUPP_MUST.
300 		 */
301 		if ((res & MDF_SUPP_ALLOW) != 0 && (res & MDF_SUPP_MUST) != 0)
302 			res &= ~MDF_SUPP_ALLOW;
303 	}
304 
305 	*dest = res;
306 	return (0);
307 }
308 
309 static void
310 toast_rules(struct rules *const rules)
311 {
312 	struct rulehead *const head = &rules->head;
313 	struct rule *rule;
314 
315 	while ((rule = TAILQ_FIRST(head)) != NULL) {
316 		TAILQ_REMOVE(head, rule, r_entries);
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 	TAILQ_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 static void
386 make_parse_error(struct parse_error **const parse_error, const size_t pos,
387     const char *const fmt, ...)
388 {
389 	struct parse_error *const err = malloc(sizeof(*err), M_DO, M_WAITOK);
390 	va_list ap;
391 
392 	err->pos = pos;
393 	va_start(ap, fmt);
394 	vsnprintf(err->msg, PARSE_ERROR_SIZE, fmt, ap);
395 	va_end(ap);
396 
397 	MPASS(*parse_error == NULL);
398 	*parse_error = err;
399 }
400 
401 static void
402 free_parse_error(struct parse_error *const parse_error)
403 {
404 	free(parse_error, M_DO);
405 }
406 
407 static int
408 parse_id_type(const char *const string, id_type_t *const type,
409     struct parse_error **const parse_error)
410 {
411 	/*
412 	 * Special case for "any", as the canonical form for IT_ANY in
413 	 * id_type_to_str[] is "*".
414 	 */
415 	if (strcmp(string, "any") == 0) {
416 		*type = IT_ANY;
417 		return (0);
418 	}
419 
420 	/* Start at 1 to avoid parsing "invalid". */
421 	for (size_t i = 1; i <= IT_LAST; ++i) {
422 		if (strcmp(string, id_type_to_str[i]) == 0) {
423 			*type = i;
424 			return (0);
425 		}
426 	}
427 
428 	*type = IT_INVALID;
429 	make_parse_error(parse_error, 0, "No valid type found.");
430 	return (EINVAL);
431 }
432 
433 static size_t
434 parse_gid_flags(const char *const string, flags_t *const flags,
435     flags_t *const gid_flags)
436 {
437 	switch (string[0]) {
438 	case '+':
439 		*flags |= MDF_SUPP_ALLOW;
440 		goto has_supp_clause;
441 	case '!':
442 		*flags |= MDF_SUPP_MUST;
443 		*gid_flags |= MDF_MAY_REJ_SUPP;
444 		goto has_supp_clause;
445 	case '-':
446 		*flags |= MDF_SUPP_DONT;
447 		*gid_flags |= MDF_MAY_REJ_SUPP;
448 		goto has_supp_clause;
449 	has_supp_clause:
450 		*gid_flags |= MDF_HAS_SUPP_CLAUSE;
451 		return (1);
452 	}
453 
454 	return (0);
455 }
456 
457 static bool
458 parse_any(const char *const string)
459 {
460 	return (strcmp(string, "*") == 0 || strcmp(string, "any") == 0);
461 }
462 
463 static bool
464 has_clauses(const id_nb_t nb, const flags_t type_flags)
465 {
466 	return ((type_flags & MDF_TYPE_MASK) != 0 || nb != 0);
467 }
468 
469 static int
470 parse_target_clause(char *to, struct rule *const rule,
471     struct id_list *const uid_list, struct id_list *const gid_list,
472     struct parse_error **const parse_error)
473 {
474 	const char *const start = to;
475 	char *to_type, *to_id;
476 	const char *p;
477 	struct id_list *list;
478 	id_nb_t *nb;
479 	flags_t *tflags;
480 	struct id_elem *ie;
481 	struct id_spec is = {.flags = 0};
482 	flags_t gid_flags = 0;
483 	id_type_t type;
484 	int error;
485 
486 	MPASS(*parse_error == NULL);
487 	MPASS(to != NULL);
488 	to_type = strsep(&to, "=");
489 	MPASS(to_type != NULL);
490 	to_type += parse_gid_flags(to_type, &is.flags, &gid_flags);
491 	error = parse_id_type(to_type, &type, parse_error);
492 	if (error != 0)
493 		goto einval;
494 	if (type != IT_GID && is.flags != 0) {
495 		make_parse_error(parse_error, to_type - start,
496 		    "Expected type 'gid' after flags, not '%s'.",
497 		    to_type);
498 		goto einval;
499 	}
500 
501 	to_id = strsep(&to, "");
502 	switch (type) {
503 	case IT_GID:
504 		if (to_id == NULL) {
505 			make_parse_error(parse_error, to_type - start,
506 			    "No '=' and ID specification after type '%s'.",
507 			    to_type);
508 			goto einval;
509 		}
510 
511 		if (is.flags == 0) {
512 			/* No flags: Dealing with a primary group. */
513 			is.flags |= MDF_PRIMARY;
514 			gid_flags |= MDF_HAS_PRIMARY_CLAUSE;
515 		}
516 
517 		list = gid_list;
518 		nb = &rule->gids_nb;
519 		tflags = &rule->gid_flags;
520 
521 		/* "*" or "any"? */
522 		if (parse_any(to_id)) {
523 			/*
524 			 * We check that we have not seen any other clause of
525 			 * the same category (i.e., concerning primary or
526 			 * supplementary groups).
527 			 */
528 			if ((is.flags & MDF_PRIMARY) != 0) {
529 				if ((*tflags & MDF_HAS_PRIMARY_CLAUSE) != 0) {
530 					make_parse_error(parse_error,
531 					    to_id - start,
532 					    "'any' specified after another "
533 					    "(primary) GID.");
534 					goto einval;
535 				}
536 				*tflags |= gid_flags | MDF_ANY;
537 			} else {
538 				/*
539 				 * If a supplementary group flag was present, it
540 				 * must be MDF_SUPP_ALLOW ("+").
541 				 */
542 				if ((is.flags & MDF_SUPP_MASK) != MDF_SUPP_ALLOW) {
543 					make_parse_error(parse_error,
544 					    to_id - start,
545 					    "'any' specified with another "
546 					    "flag than '+'.");
547 					goto einval;
548 				}
549 				if ((*tflags & MDF_HAS_SUPP_CLAUSE) != 0) {
550 					make_parse_error(parse_error,
551 					    to_id - start,
552 					    "'any' with flag '+' specified after "
553 					    "another (supplementary) GID.");
554 					goto einval;
555 				}
556 				*tflags |= gid_flags | MDF_ANY_SUPP;
557 			}
558 			goto check_type_and_finish;
559 		} else {
560 			/*
561 			 * Check that we haven't already seen "any" for the same
562 			 * category.
563 			 */
564 			if ((is.flags & MDF_PRIMARY) != 0) {
565 				if ((*tflags & MDF_ANY) != 0) {
566 					make_parse_error(parse_error,
567 					    to_id - start,
568 					    "Some (primary) GID specified after "
569 					    "'any'.");
570 					goto einval;
571 				}
572 			} else if ((*tflags & MDF_ANY_SUPP) != 0 &&
573 			    (is.flags & MDF_SUPP_ALLOW) != 0) {
574 				make_parse_error(parse_error,
575 				    to_id - start,
576 				    "Some (supplementary) GID specified after "
577 				    "'any' with flag '+'.");
578 				goto einval;
579 			}
580 			*tflags |= gid_flags;
581 		}
582 		break;
583 
584 	case IT_UID:
585 		if (to_id == NULL) {
586 			make_parse_error(parse_error, to_type - start,
587 			    "No '=' and ID specification after type '%s'.",
588 			    to_type);
589 			goto einval;
590 		}
591 
592 		list = uid_list;
593 		nb = &rule->uids_nb;
594 		tflags = &rule->uid_flags;
595 
596 		/* "*" or "any"? */
597 		if (parse_any(to_id)) {
598 			/* There must not be any other clause. */
599 			if (has_clauses(*nb, *tflags)) {
600 				make_parse_error(parse_error, to_id - start,
601 				    "'any' specified after another UID.");
602 				goto einval;
603 			}
604 			*tflags |= MDF_ANY;
605 			goto check_type_and_finish;
606 		} else {
607 			/*
608 			 * Check that we haven't already seen "any" for the same
609 			 * category.
610 			 */
611 			if ((*tflags & MDF_ANY) != 0) {
612 				make_parse_error(parse_error, to_id - start,
613 				    "Some UID specified after 'any'.");
614 				goto einval;
615 			}
616 		}
617 		break;
618 
619 	case IT_ANY:
620 		/* No ID allowed. */
621 		if (to_id != NULL) {
622 			make_parse_error(parse_error, to_type - start,
623 			    "No '=' and ID allowed after type '%s'.", to_type);
624 			goto einval;
625 		}
626 		/*
627 		 * We can't have IT_ANY after any other IT_*, it must be the
628 		 * only one.
629 		 */
630 		if (has_clauses(rule->uids_nb, rule->uid_flags) ||
631 		    has_clauses(rule->gids_nb, rule->gid_flags)) {
632 			make_parse_error(parse_error, to_type - start,
633 			    "Target clause of type '%s' coming after another "
634 			    "clause (must be alone).", to_type);
635 			goto einval;
636 		}
637 		rule->uid_flags |= MDF_ANY;
638 		rule->gid_flags |= MDF_ANY | MDF_ANY_SUPP |
639 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
640 		goto finish;
641 
642 	default:
643 		/* parse_id_type() returns no other types currently. */
644 		__assert_unreachable();
645 	}
646 
647 	/* Rule out cases that have been treated above. */
648 	MPASS((type == IT_UID || type == IT_GID) && !parse_any(to_id));
649 
650 	/* "."? */
651 	if (strcmp(to_id, ".") == 0) {
652 		if ((*tflags & MDF_CURRENT) != 0) {
653 			/* Duplicate "." <id>.  Try to coalesce. */
654 			error = coalesce_id_flags(is.flags, tflags);
655 			if (error != 0) {
656 				make_parse_error(parse_error, to_id - start,
657 				    "Incompatible flags with prior clause "
658 				    "with same target.");
659 				goto einval;
660 			}
661 		} else
662 			*tflags |= MDF_CURRENT | is.flags;
663 		goto check_type_and_finish;
664 	}
665 
666 	/* Parse an ID. */
667 	error = strtoui_strict(to_id, &p, 10, &is.id);
668 	if (error != 0 || *p != '\0') {
669 		make_parse_error(parse_error, to_id - start,
670 		    "Cannot parse a numerical ID (base 10).");
671 		goto einval;
672 	}
673 
674 	/* Explicit ID flags. */
675 	if (type == IT_GID && (is.flags & MDF_SUPP_MUST) != 0)
676 		*tflags |= MDF_EXPLICIT_SUPP_MUST;
677 
678 	/*
679 	 * We check for duplicate IDs and coalesce their 'struct id_spec' only
680 	 * at end of parse_single_rule() because it is much more performant then
681 	 * (using sorted arrays).
682 	 */
683 	++*nb;
684 	if (*nb == 0) {
685 		make_parse_error(parse_error, 0,
686 		    "Too many target clauses of type '%s'.", to_type);
687 		return (EOVERFLOW);
688 	}
689 	ie = malloc(sizeof(*ie), M_DO, M_WAITOK);
690 	ie->spec = is;
691 	TAILQ_INSERT_TAIL(list, ie, ie_entries);
692 	check_type_and_id_spec(type, &is);
693 check_type_and_finish:
694 	check_type_and_type_flags(type, *tflags);
695 finish:
696 	return (0);
697 einval:
698 	/* We must have built a parse error on error. */
699 	MPASS(*parse_error != NULL);
700 	return (EINVAL);
701 }
702 
703 static int
704 u_int_cmp(const u_int i1, const u_int i2)
705 {
706 	return ((i1 > i2) - (i1 < i2));
707 }
708 
709 static int
710 id_spec_cmp(const void *const p1, const void *const p2)
711 {
712 	const struct id_spec *const is1 = p1;
713 	const struct id_spec *const is2 = p2;
714 
715 	return (u_int_cmp(is1->id, is2->id));
716 }
717 
718 /*
719  * Transfer content of 'list' into 'array', freeing and emptying list.
720  *
721  * 'nb' must be 'list''s length and not be greater than 'array''s size.  The
722  * destination array is sorted by ID.  Structures 'struct id_spec' with same IDs
723  * are coalesced if that makes sense (not including duplicate clauses), else
724  * EINVAL is returned.  On success, 'nb' is updated (lowered) to account for
725  * coalesced specifications.  The parameter 'type' is only for testing purposes
726  * (INVARIANTS).
727  */
728 static int
729 pour_list_into_rule(const id_type_t type, struct id_list *const list,
730     struct id_spec *const array, id_nb_t *const nb,
731     struct parse_error **const parse_error)
732 {
733 	struct id_elem *ie, *ie_next;
734 	size_t idx = 0;
735 
736 	/* Fill the array. */
737 	TAILQ_FOREACH_SAFE(ie, list, ie_entries, ie_next) {
738 		MPASS(idx < *nb);
739 		array[idx] = ie->spec;
740 		free(ie, M_DO);
741 		++idx;
742 	}
743 	MPASS(idx == *nb);
744 	TAILQ_INIT(list);
745 
746 	/* Sort it (by ID). */
747 	qsort(array, *nb, sizeof(*array), id_spec_cmp);
748 
749 	/* Coalesce same IDs. */
750 	if (*nb != 0) {
751 		size_t ref_idx = 0;
752 
753 		for (idx = 1; idx < *nb; ++idx) {
754 			const u_int id = array[idx].id;
755 
756 			if (id != array[ref_idx].id) {
757 				++ref_idx;
758 				if (ref_idx != idx)
759 					array[ref_idx] = array[idx];
760 				continue;
761 			}
762 
763 			switch (type) {
764 				int error;
765 
766 			case IT_GID:
767 				error = coalesce_id_flags(array[idx].flags,
768 				    &array[ref_idx].flags);
769 				if (error != 0) {
770 					make_parse_error(parse_error, 0,
771 					    "Incompatible flags or duplicate "
772 					    "GID %u.", id);
773 					return (EINVAL);
774 				}
775 				check_type_and_id_flags(type,
776 				    array[ref_idx].flags);
777 				break;
778 
779 			case IT_UID:
780 				/*
781 				 * No flags in this case.  Multiple appearances
782 				 * of the same UID is an exact redundancy, so
783 				 * error out.
784 				 */
785 				make_parse_error(parse_error, 0,
786 				    "Duplicate UID %u.", id);
787 				return (EINVAL);
788 
789 			default:
790 				__assert_unreachable();
791 			}
792 		}
793 		*nb = ref_idx + 1;
794 	}
795 
796 	return (0);
797 }
798 
799 /*
800  * See also first comments for parse_rule() below.
801  *
802  * The second part of a rule, called <target> (or <to>), is a comma-separated
803  * (',') list of '<flags><type>=<id>' clauses similar to that of the <from>
804  * part, with the extensions that <id> may also be "*" or "any" or ".", and that
805  * <flags> may contain at most one of the '+', '-' and '!' characters when
806  * <type> is "gid" (no flags are allowed for "uid").  No two clauses in a single
807  * <to> list may list the same <id>.  "*" and "any" both designate any ID for
808  * the <type>, and are aliases to each other.  In front of "any" (or "*"), only
809  * the '+' flag is allowed (in the "gid" case).  "." designates the process'
810  * current IDs for the <type>.  The precise meaning of flags and "." is
811  * explained in functions checking privileges below.
812  */
813 static int
814 parse_single_rule(char *rule, struct rules *const rules,
815     struct parse_error **const parse_error)
816 {
817 	const char *const start = rule;
818 	const char *from_type, *from_id, *p;
819 	char *to_list;
820 	struct id_list uid_list, gid_list;
821 	struct id_elem *ie, *ie_next;
822 	struct rule *new;
823 	int error;
824 
825 	MPASS(*parse_error == NULL);
826 	TAILQ_INIT(&uid_list);
827 	TAILQ_INIT(&gid_list);
828 
829 	/* Freed when the 'struct rules' container is freed. */
830 	new = malloc(sizeof(*new), M_DO, M_WAITOK | M_ZERO);
831 
832 	from_type = strsep(&rule, "=");
833 	MPASS(from_type != NULL); /* Because 'rule' was not NULL. */
834 	error = parse_id_type(from_type, &new->from_type, parse_error);
835 	if (error != 0)
836 		goto einval;
837 	switch (new->from_type) {
838 	case IT_UID:
839 	case IT_GID:
840 		break;
841 	default:
842 		make_parse_error(parse_error, 0, "Type '%s' not allowed in "
843 		    "the \"from\" part of rules.");
844 		goto einval;
845 	}
846 
847 	from_id = strsep(&rule, ":");
848 	if (is_null_or_empty(from_id)) {
849 		make_parse_error(parse_error, 0, "No ID specified.");
850 		goto einval;
851 	}
852 
853 	error = strtoui_strict(from_id, &p, 10, &new->from_id);
854 	if (error != 0 || *p != '\0') {
855 		make_parse_error(parse_error, from_id - start,
856 		    "Cannot parse a numerical ID (base 10).");
857 		goto einval;
858 	}
859 
860 	/*
861 	 * We will now parse the "to" list.
862 	 *
863 	 * In order to ease parsing, we will begin by building lists of target
864 	 * UIDs and GIDs in local variables 'uid_list' and 'gid_list'.  The
865 	 * number of each type of IDs will be filled directly in 'new'.  At end
866 	 * of parse, we will allocate both arrays of IDs to be placed into the
867 	 * 'uids' and 'gids' members, sort them, and discard the tail queues
868 	 * used to build them.  This conversion to sorted arrays at end of parse
869 	 * allows to minimize memory allocations and enables searching IDs in
870 	 * O(log(n)) instead of linearly.
871 	 */
872 	to_list = strsep(&rule, ",");
873 	if (to_list == NULL) {
874 		make_parse_error(parse_error, 0, "No target list.");
875 		goto einval;
876 	}
877 	do {
878 		error = parse_target_clause(to_list, new, &uid_list, &gid_list,
879 		    parse_error);
880 		if (error != 0) {
881 			(*parse_error)->pos += to_list - start;
882 			goto einval;
883 		}
884 
885 		to_list = strsep(&rule, ",");
886 	} while (to_list != NULL);
887 
888 	if (new->uids_nb != 0) {
889 		new->uids = malloc(sizeof(*new->uids) * new->uids_nb, M_DO,
890 		    M_WAITOK);
891 		error = pour_list_into_rule(IT_UID, &uid_list, new->uids,
892 		    &new->uids_nb, parse_error);
893 		if (error != 0)
894 			goto einval;
895 	}
896 	MPASS(TAILQ_EMPTY(&uid_list));
897 	if (!has_clauses(new->uids_nb, new->uid_flags)) {
898 		/* No UID specified, default is "uid=.". */
899 		MPASS(new->uid_flags == 0);
900 		new->uid_flags = MDF_CURRENT;
901 		check_type_and_type_flags(IT_UID, new->uid_flags);
902 	}
903 
904 	if (new->gids_nb != 0) {
905 		new->gids = malloc(sizeof(*new->gids) * new->gids_nb, M_DO,
906 		    M_WAITOK);
907 		error = pour_list_into_rule(IT_GID, &gid_list, new->gids,
908 		    &new->gids_nb, parse_error);
909 		if (error != 0)
910 			goto einval;
911 	}
912 	MPASS(TAILQ_EMPTY(&gid_list));
913 	if (!has_clauses(new->gids_nb, new->gid_flags)) {
914 		/* No GID specified, default is "gid=.,!gid=.". */
915 		MPASS(new->gid_flags == 0);
916 		new->gid_flags = MDF_CURRENT | MDF_PRIMARY | MDF_SUPP_MUST |
917 		    MDF_HAS_PRIMARY_CLAUSE | MDF_HAS_SUPP_CLAUSE;
918 		check_type_and_type_flags(IT_GID, new->gid_flags);
919 	}
920 
921 	TAILQ_INSERT_TAIL(&rules->head, new, r_entries);
922 	return (0);
923 
924 einval:
925 	free(new->gids, M_DO);
926 	free(new->uids, M_DO);
927 	free(new, M_DO);
928 	TAILQ_FOREACH_SAFE(ie, &gid_list, ie_entries, ie_next)
929 	    free(ie, M_DO);
930 	TAILQ_FOREACH_SAFE(ie, &uid_list, ie_entries, ie_next)
931 	    free(ie, M_DO);
932 	MPASS(*parse_error != NULL);
933 	return (EINVAL);
934 }
935 
936 /*
937  * Parse rules specification and produce rule structures out of it.
938  *
939  * Returns 0 on success, with '*rulesp' made to point to a 'struct rule'
940  * representing the rules.  On error, the returned value is non-zero and
941  * '*rulesp' is unchanged.  If 'string' has length greater or equal to
942  * MAC_RULE_STRING_LEN, ENAMETOOLONG is returned.  If it is not in the expected
943  * format, EINVAL is returned.  If an error is returned, '*parse_error' is set
944  * to point to a 'struct parse_error' giving an error message for the problem,
945  * else '*parse_error' is set to NULL.
946  *
947  * Expected format: A semi-colon-separated list of rules of the form
948  * "<from>:<target>".  The <from> part is of the form "<type>=<id>" where <type>
949  * is "uid" or "gid", <id> an UID or GID (depending on <type>) and <target> is
950  * "*", "any" or a comma-separated list of '<flags><type>=<id>' clauses (see the
951  * comment for parse_single_rule() for more details).  For convenience, empty
952  * rules are allowed (and do nothing).
953  *
954  * Examples:
955  * - "uid=1001:uid=1010,gid=1010;uid=1002:any"
956  * - "gid=1010:gid=1011,gid=1012,gid=1013"
957  */
958 static int
959 parse_rules(const char *const string, struct rules **const rulesp,
960     struct parse_error **const parse_error)
961 {
962 	const size_t len = strlen(string);
963 	char *copy, *p, *rule;
964 	struct rules *rules;
965 	int error = 0;
966 
967 	*parse_error = NULL;
968 
969 	if (len >= MAC_RULE_STRING_LEN) {
970 		make_parse_error(parse_error, 0,
971 		    "Rule specification string is too long (%zu, max %zu)",
972 		    len, MAC_RULE_STRING_LEN - 1);
973 		return (ENAMETOOLONG);
974 	}
975 
976 	rules = alloc_rules();
977 	bcopy(string, rules->string, len + 1);
978 	MPASS(rules->string[len] == '\0'); /* Catch some races. */
979 
980 	copy = malloc(len + 1, M_DO, M_WAITOK);
981 	bcopy(string, copy, len + 1);
982 	MPASS(copy[len] == '\0'); /* Catch some races. */
983 
984 	p = copy;
985 	while ((rule = strsep(&p, ";")) != NULL) {
986 		if (rule[0] == '\0')
987 			continue;
988 		error = parse_single_rule(rule, rules, parse_error);
989 		if (error != 0) {
990 			(*parse_error)->pos += rule - copy;
991 			toast_rules(rules);
992 			goto out;
993 		}
994 	}
995 
996 	*rulesp = rules;
997 out:
998 	free(copy, M_DO);
999 	return (error);
1000 }
1001 
1002 /*
1003  * Find rules applicable to the passed prison.
1004  *
1005  * Returns the applicable rules (and never NULL).  'pr' must be unlocked.
1006  * 'aprp' is set to the (ancestor) prison holding these, and it must be unlocked
1007  * once the caller is done accessing the rules.  '*aprp' is equal to 'pr' if and
1008  * only if the current jail has its own set of rules.
1009  */
1010 static struct rules *
1011 find_rules(struct prison *const pr, struct prison **const aprp)
1012 {
1013 	struct prison *cpr, *ppr;
1014 	struct rules *rules;
1015 
1016 	cpr = pr;
1017 	for (;;) {
1018 		prison_lock(cpr);
1019 		rules = osd_jail_get(cpr, osd_jail_slot);
1020 		if (rules != NULL)
1021 			break;
1022 		prison_unlock(cpr);
1023 
1024 		ppr = cpr->pr_parent;
1025 		MPASS(ppr != NULL); /* prison0 always has rules. */
1026 		cpr = ppr;
1027 	}
1028 
1029 	*aprp = cpr;
1030 	return (rules);
1031 }
1032 
1033 static void
1034 hold_rules(struct rules *const rules)
1035 {
1036 	refcount_acquire(&rules->use_count);
1037 }
1038 
1039 static void
1040 drop_rules(struct rules *const rules)
1041 {
1042 	if (refcount_release(&rules->use_count))
1043 		toast_rules(rules);
1044 }
1045 
1046 #ifdef INVARIANTS
1047 static void
1048 check_rules_use_count(const struct rules *const rules, u_int expected)
1049 {
1050 	const u_int use_count = refcount_load(&rules->use_count);
1051 
1052 	if (use_count != expected)
1053 		panic("MAC/do: Rules at %p: Use count is %u, expected %u",
1054 		    rules, use_count, expected);
1055 }
1056 #else
1057 #define check_rules_use_count(...)
1058 #endif /* INVARIANTS */
1059 
1060 /*
1061  * OSD destructor for slot 'osd_jail_slot'.
1062  *
1063  * Called with 'value' not NULL.  We have arranged that it is only ever called
1064  * when the corresponding jail goes down or at module unload.
1065  */
1066 static void
1067 dealloc_osd(void *const value)
1068 {
1069 	struct rules *const rules = value;
1070 
1071 	/* No one should be using the rules but us at this point. */
1072 	check_rules_use_count(rules, 1);
1073 	toast_rules(rules);
1074 }
1075 
1076 /*
1077  * Remove the rules specifically associated to a prison.
1078  *
1079  * In practice, this means that the rules become inherited (from the closest
1080  * ascendant that has some).
1081  *
1082  * Destroys the 'osd_jail_slot' slot of the passed jail.
1083  */
1084 static void
1085 remove_rules(struct prison *const pr)
1086 {
1087 	struct rules *old_rules;
1088 	int error __unused;
1089 
1090 	prison_lock(pr);
1091 	/*
1092 	 * We go to the burden of extracting rules first instead of just letting
1093 	 * osd_jail_del() calling dealloc_osd() as we want to decrement their
1094 	 * use count, and possibly free them, outside of the prison lock.
1095 	 */
1096 	old_rules = osd_jail_get(pr, osd_jail_slot);
1097 	error = osd_jail_set(pr, osd_jail_slot, NULL);
1098 	/* osd_set() never fails nor allocate memory when 'value' is NULL. */
1099 	MPASS(error == 0);
1100 	/*
1101 	 * This completely frees the OSD slot, but doesn't call the destructor
1102 	 * since we've just put NULL in the slot.
1103 	 */
1104 	osd_jail_del(pr, osd_jail_slot);
1105 	prison_unlock(pr);
1106 
1107 	if (old_rules != NULL)
1108 		drop_rules(old_rules);
1109 }
1110 
1111 /*
1112  * Assign already built rules to a jail.
1113  */
1114 static void
1115 set_rules(struct prison *const pr, struct rules *const rules)
1116 {
1117 	struct rules *old_rules;
1118 	void **rsv;
1119 
1120 	check_rules_use_count(rules, 0);
1121 	hold_rules(rules);
1122 	rsv = osd_reserve(osd_jail_slot);
1123 
1124 	prison_lock(pr);
1125 	old_rules = osd_jail_get(pr, osd_jail_slot);
1126 	osd_jail_set_reserved(pr, osd_jail_slot, rsv, rules);
1127 	prison_unlock(pr);
1128 	if (old_rules != NULL)
1129 		drop_rules(old_rules);
1130 }
1131 
1132 /*
1133  * Assigns empty rules to a jail.
1134  */
1135 static void
1136 set_empty_rules(struct prison *const pr)
1137 {
1138 	struct rules *const rules = alloc_rules();
1139 
1140 	set_rules(pr, rules);
1141 }
1142 
1143 /*
1144  * Parse a rules specification and assign them to a jail.
1145  *
1146  * Returns the same error code as parse_rules() (which see).
1147  */
1148 static int
1149 parse_and_set_rules(struct prison *const pr, const char *rules_string,
1150     struct parse_error **const parse_error)
1151 {
1152 	struct rules *rules;
1153 	int error;
1154 
1155 	error = parse_rules(rules_string, &rules, parse_error);
1156 	if (error != 0)
1157 		return (error);
1158 	set_rules(pr, rules);
1159 	return (0);
1160 }
1161 
1162 static int
1163 mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS)
1164 {
1165 	char *const buf = malloc(MAC_RULE_STRING_LEN, M_DO, M_WAITOK);
1166 	struct prison *const td_pr = req->td->td_ucred->cr_prison;
1167 	struct prison *pr;
1168 	struct rules *rules;
1169 	struct parse_error *parse_error;
1170 	int error;
1171 
1172 	rules = find_rules(td_pr, &pr);
1173 	strlcpy(buf, rules->string, MAC_RULE_STRING_LEN);
1174 	prison_unlock(pr);
1175 
1176 	error = sysctl_handle_string(oidp, buf, MAC_RULE_STRING_LEN, req);
1177 	if (error != 0 || req->newptr == NULL)
1178 		goto out;
1179 
1180 	/* Set our prison's rules, not that of the jail we inherited from. */
1181 	error = parse_and_set_rules(td_pr, buf, &parse_error);
1182 	if (error != 0) {
1183 		if (print_parse_error)
1184 			printf("MAC/do: Parse error at index %zu: %s\n",
1185 			    parse_error->pos, parse_error->msg);
1186 		free_parse_error(parse_error);
1187 	}
1188 out:
1189 	free(buf, M_DO);
1190 	return (error);
1191 }
1192 
1193 SYSCTL_PROC(_security_mac_do, OID_AUTO, rules,
1194     CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON|CTLFLAG_MPSAFE,
1195     0, 0, mac_do_sysctl_rules, "A",
1196     "Rules");
1197 
1198 
1199 SYSCTL_JAIL_PARAM_SYS_SUBNODE(mac, do, CTLFLAG_RW, "Jail MAC/do parameters");
1200 SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAC_RULE_STRING_LEN,
1201     "Jail MAC/do rules");
1202 
1203 
1204 static int
1205 mac_do_jail_create(void *obj, void *data __unused)
1206 {
1207 	struct prison *const pr = obj;
1208 
1209 	set_empty_rules(pr);
1210 	return (0);
1211 }
1212 
1213 static int
1214 mac_do_jail_get(void *obj, void *data)
1215 {
1216 	struct prison *ppr, *const pr = obj;
1217 	struct vfsoptlist *const opts = data;
1218 	struct rules *rules;
1219 	int jsys, error;
1220 
1221 	rules = find_rules(pr, &ppr);
1222 
1223 	jsys = pr == ppr ?
1224 	    (TAILQ_EMPTY(&rules->head) ? JAIL_SYS_DISABLE : JAIL_SYS_NEW) :
1225 	    JAIL_SYS_INHERIT;
1226 	error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys));
1227 	if (error != 0 && error != ENOENT)
1228 		goto done;
1229 
1230 	error = vfs_setopts(opts, "mac.do.rules", rules->string);
1231 	if (error != 0 && error != ENOENT)
1232 		goto done;
1233 
1234 	error = 0;
1235 done:
1236 	prison_unlock(ppr);
1237 	return (error);
1238 }
1239 
1240 /*
1241  * -1 is used as a sentinel in mac_do_jail_check() and mac_do_jail_set() below.
1242  */
1243 _Static_assert(-1 != JAIL_SYS_DISABLE && -1 != JAIL_SYS_NEW &&
1244     -1 != JAIL_SYS_INHERIT,
1245     "mac_do(4) uses -1 as a sentinel for uninitialized 'jsys'.");
1246 
1247 /*
1248  * We perform only cheap checks here, i.e., we do not really parse the rules
1249  * specification string, if any.
1250  */
1251 static int
1252 mac_do_jail_check(void *obj, void *data)
1253 {
1254 	struct vfsoptlist *opts = data;
1255 	char *rules_string;
1256 	int error, jsys, size;
1257 
1258 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1259 	if (error == ENOENT)
1260 		jsys = -1;
1261 	else {
1262 		if (error != 0)
1263 			return (error);
1264 		if (jsys != JAIL_SYS_DISABLE && jsys != JAIL_SYS_NEW &&
1265 		    jsys != JAIL_SYS_INHERIT)
1266 			return (EINVAL);
1267 	}
1268 
1269 	/*
1270 	 * We use vfs_getopt() here instead of vfs_getopts() to get the length.
1271 	 * We perform the additional checks done by the latter here, even if
1272 	 * jail_set() calls vfs_getopts() itself later (they becoming
1273 	 * inconsistent wouldn't cause any security problem).
1274 	 */
1275 	error = vfs_getopt(opts, "mac.do.rules", (void**)&rules_string, &size);
1276 	if (error == ENOENT) {
1277 		/*
1278 		 * Default (in absence of "mac.do.rules") is to disable (and, in
1279 		 * particular, not inherit).
1280 		 */
1281 		if (jsys == -1)
1282 			jsys = JAIL_SYS_DISABLE;
1283 
1284 		if (jsys == JAIL_SYS_NEW) {
1285 			vfs_opterror(opts, "'mac.do.rules' must be specified "
1286 			    "given 'mac.do''s value");
1287 			return (EINVAL);
1288 		}
1289 
1290 		/* Absence of "mac.do.rules" at this point is OK. */
1291 		error = 0;
1292 	} else {
1293 		if (error != 0)
1294 			return (error);
1295 
1296 		/* Not a proper string. */
1297 		if (size == 0 || rules_string[size - 1] != '\0') {
1298 			vfs_opterror(opts, "'mac.do.rules' not a proper string");
1299 			return (EINVAL);
1300 		}
1301 
1302 		if (size > MAC_RULE_STRING_LEN) {
1303 			vfs_opterror(opts, "'mdo.rules' too long");
1304 			return (ENAMETOOLONG);
1305 		}
1306 
1307 		if (jsys == -1)
1308 			/* Default (if "mac.do.rules" is present). */
1309 			jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE :
1310 			    JAIL_SYS_NEW;
1311 
1312 		/*
1313 		 * Be liberal and accept JAIL_SYS_DISABLE and JAIL_SYS_INHERIT
1314 		 * with an explicit empty rules specification.
1315 		 */
1316 		switch (jsys) {
1317 		case JAIL_SYS_DISABLE:
1318 		case JAIL_SYS_INHERIT:
1319 			if (rules_string[0] != '\0') {
1320 				vfs_opterror(opts, "'mac.do.rules' specified "
1321 				    "but should not given 'mac.do''s value");
1322 				return (EINVAL);
1323 			}
1324 			break;
1325 		}
1326 	}
1327 
1328 	return (error);
1329 }
1330 
1331 static int
1332 mac_do_jail_set(void *obj, void *data)
1333 {
1334 	struct prison *pr = obj;
1335 	struct vfsoptlist *opts = data;
1336 	char *rules_string;
1337 	struct parse_error *parse_error;
1338 	int error, jsys;
1339 
1340 	/*
1341 	 * The invariants checks used below correspond to what has already been
1342 	 * checked in jail_check() above.
1343 	 */
1344 
1345 	error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys));
1346 	MPASS(error == 0 || error == ENOENT);
1347 	if (error != 0)
1348 		jsys = -1; /* Mark unfilled. */
1349 
1350 	rules_string = vfs_getopts(opts, "mac.do.rules", &error);
1351 	MPASS(error == 0 || error == ENOENT);
1352 	if (error == 0) {
1353 		MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN);
1354 		if (jsys == -1)
1355 			/* Default (if "mac.do.rules" is present). */
1356 			jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE :
1357 			    JAIL_SYS_NEW;
1358 		else
1359 			MPASS(jsys == JAIL_SYS_NEW ||
1360 			    ((jsys == JAIL_SYS_DISABLE ||
1361 			    jsys == JAIL_SYS_INHERIT) &&
1362 			    rules_string[0] == '\0'));
1363 	} else {
1364 		MPASS(jsys != JAIL_SYS_NEW);
1365 		if (jsys == -1)
1366 			/*
1367 			 * Default (in absence of "mac.do.rules") is to disable
1368 			 * (and, in particular, not inherit).
1369 			 */
1370 			jsys = JAIL_SYS_DISABLE;
1371 		/* If disabled, we'll store an empty rule specification. */
1372 		if (jsys == JAIL_SYS_DISABLE)
1373 			rules_string = "";
1374 	}
1375 
1376 	switch (jsys) {
1377 	case JAIL_SYS_INHERIT:
1378 		remove_rules(pr);
1379 		error = 0;
1380 		break;
1381 	case JAIL_SYS_DISABLE:
1382 	case JAIL_SYS_NEW:
1383 		error = parse_and_set_rules(pr, rules_string, &parse_error);
1384 		if (error != 0) {
1385 			vfs_opterror(opts,
1386 			    "MAC/do: Parse error at index %zu: %s\n",
1387 			    parse_error->pos, parse_error->msg);
1388 			free_parse_error(parse_error);
1389 		}
1390 		break;
1391 	default:
1392 		__assert_unreachable();
1393 	}
1394 	return (error);
1395 }
1396 
1397 /*
1398  * OSD jail methods.
1399  *
1400  * There is no PR_METHOD_REMOVE, as OSD storage is destroyed by the common jail
1401  * code (see prison_cleanup()), which triggers a run of our dealloc_osd()
1402  * destructor.
1403  */
1404 static const osd_method_t osd_methods[PR_MAXMETHOD] = {
1405 	[PR_METHOD_CREATE] = mac_do_jail_create,
1406 	[PR_METHOD_GET] = mac_do_jail_get,
1407 	[PR_METHOD_CHECK] = mac_do_jail_check,
1408 	[PR_METHOD_SET] = mac_do_jail_set,
1409 };
1410 
1411 
1412 static void
1413 mac_do_init(struct mac_policy_conf *mpc)
1414 {
1415 	struct prison *pr;
1416 
1417 	osd_jail_slot = osd_jail_register(dealloc_osd, osd_methods);
1418 	set_empty_rules(&prison0);
1419 	sx_slock(&allprison_lock);
1420 	TAILQ_FOREACH(pr, &allprison, pr_list)
1421 	    set_empty_rules(pr);
1422 	sx_sunlock(&allprison_lock);
1423 }
1424 
1425 static void
1426 mac_do_destroy(struct mac_policy_conf *mpc)
1427 {
1428 	osd_jail_deregister(osd_jail_slot);
1429 }
1430 
1431 static bool
1432 rule_applies(struct ucred *cred, struct rule *r)
1433 {
1434 	if (r->from_type == IT_UID && r->from_id == cred->cr_uid)
1435 		return (true);
1436 	if (r->from_type == IT_GID && groupmember(r->from_id, cred))
1437 		return (true);
1438 	return (false);
1439 }
1440 
1441 static int
1442 mac_do_priv_grant(struct ucred *cred, int priv)
1443 {
1444 	struct rule *r;
1445 	struct prison *pr;
1446 	struct rules *rule;
1447 
1448 	if (do_enabled == 0)
1449 		return (EPERM);
1450 
1451 	rule = find_rules(cred->cr_prison, &pr);
1452 	TAILQ_FOREACH(r, &rule->head, r_entries) {
1453 		if (rule_applies(cred, r)) {
1454 			switch (priv) {
1455 			case PRIV_CRED_SETGROUPS:
1456 			case PRIV_CRED_SETUID:
1457 				prison_unlock(pr);
1458 				return (0);
1459 			default:
1460 				break;
1461 			}
1462 		}
1463 	}
1464 	prison_unlock(pr);
1465 	return (EPERM);
1466 }
1467 
1468 static int
1469 mac_do_check_setgroups(struct ucred *cred, int ngrp, gid_t *groups)
1470 {
1471 	struct rule *r;
1472 	char *fullpath = NULL;
1473 	char *freebuf = NULL;
1474 	struct prison *pr;
1475 	struct rules *rule;
1476 
1477 	if (do_enabled == 0)
1478 		return (0);
1479 	if (cred->cr_uid == 0)
1480 		return (0);
1481 
1482 	if (vn_fullpath(curproc->p_textvp, &fullpath, &freebuf) != 0)
1483 		return (EPERM);
1484 	if (strcmp(fullpath, "/usr/bin/mdo") != 0) {
1485 		free(freebuf, M_TEMP);
1486 		return (EPERM);
1487 	}
1488 	free(freebuf, M_TEMP);
1489 
1490 	rule = find_rules(cred->cr_prison, &pr);
1491 	TAILQ_FOREACH(r, &rule->head, r_entries) {
1492 		if (rule_applies(cred, r)) {
1493 			prison_unlock(pr);
1494 			return (0);
1495 		}
1496 	}
1497 	prison_unlock(pr);
1498 
1499 	return (EPERM);
1500 }
1501 
1502 static int
1503 mac_do_check_setuid(struct ucred *cred, uid_t uid)
1504 {
1505 	struct rule *r;
1506 	char *fullpath = NULL;
1507 	char *freebuf = NULL;
1508 	struct prison *pr;
1509 	struct rules *rule;
1510 	struct id_spec uid_is = {.id = uid};
1511 	int error;
1512 
1513 	if (do_enabled == 0)
1514 		return (0);
1515 	if (cred->cr_uid == uid || cred->cr_uid == 0 || cred->cr_ruid == 0)
1516 		return (0);
1517 
1518 	if (vn_fullpath(curproc->p_textvp, &fullpath, &freebuf) != 0)
1519 		return (EPERM);
1520 	if (strcmp(fullpath, "/usr/bin/mdo") != 0) {
1521 		free(freebuf, M_TEMP);
1522 		return (EPERM);
1523 	}
1524 	free(freebuf, M_TEMP);
1525 
1526 	error = EPERM;
1527 	rule = find_rules(cred->cr_prison, &pr);
1528 	TAILQ_FOREACH(r, &rule->head, r_entries) {
1529 		if (!((r->from_type == IT_UID && cred->cr_uid == r->from_id) ||
1530 		    (r->from_type == IT_GID && groupmember(r->from_id, cred))))
1531 			continue;
1532 
1533 		if (r->uid_flags & MDF_ANY ||
1534 		    ((r->uid_flags & MDF_CURRENT) && (uid == cred->cr_uid ||
1535 		    uid == cred->cr_ruid || uid == cred->cr_svuid)) ||
1536 		    bsearch(&uid_is, r->uids, r->uids_nb, sizeof(*r->uids),
1537 		    id_spec_cmp) != NULL) {
1538 			error = 0;
1539 			break;
1540 		}
1541 	}
1542 	prison_unlock(pr);
1543 	return (error);
1544 }
1545 
1546 static struct mac_policy_ops do_ops = {
1547 	.mpo_destroy = mac_do_destroy,
1548 	.mpo_init = mac_do_init,
1549 	.mpo_cred_check_setuid = mac_do_check_setuid,
1550 	.mpo_cred_check_setgroups = mac_do_check_setgroups,
1551 	.mpo_priv_grant = mac_do_priv_grant,
1552 };
1553 
1554 MAC_POLICY_SET(&do_ops, mac_do, "MAC/do",
1555    MPC_LOADTIME_FLAG_UNLOADOK, NULL);
1556 MODULE_VERSION(mac_do, 1);
1557