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