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, *rule_next; 315 316 TAILQ_FOREACH_SAFE(rule, head, r_entries, rule_next) { 317 free(rule->uids, M_DO); 318 free(rule->gids, M_DO); 319 free(rule, M_DO); 320 } 321 free(rules, M_DO); 322 } 323 324 static struct rules * 325 alloc_rules(void) 326 { 327 struct rules *const rules = malloc(sizeof(*rules), M_DO, M_WAITOK); 328 329 _Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!"); 330 rules->string[0] = 0; 331 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_jail_osd(void *const value) 1068 { 1069 struct rules *const rules = value; 1070 1071 /* 1072 * If called because the "holding" jail goes down, no one should be 1073 * using the rules but us at this point because no threads of that jail 1074 * (or its sub-jails) should currently be executing (in particular, 1075 * currently executing setcred()). The case of module unload is more 1076 * complex. Although the MAC framework takes care that no hook is 1077 * called while a module is unloading, the unload could happen between 1078 * two calls to MAC hooks in the course of, e.g., executing setcred(), 1079 * where the rules' reference count has been bumped to keep them alive 1080 * even if the rules on the "holding" jail has been concurrently 1081 * changed. These other references are held in our thread OSD slot, so 1082 * we ensure that all thread's slots are freed first in mac_do_destroy() 1083 * to be able to check that only one reference remains. 1084 */ 1085 check_rules_use_count(rules, 1); 1086 toast_rules(rules); 1087 } 1088 1089 /* 1090 * Remove the rules specifically associated to a prison. 1091 * 1092 * In practice, this means that the rules become inherited (from the closest 1093 * ascendant that has some). 1094 * 1095 * Destroys the 'osd_jail_slot' slot of the passed jail. 1096 */ 1097 static void 1098 remove_rules(struct prison *const pr) 1099 { 1100 struct rules *old_rules; 1101 int error __unused; 1102 1103 prison_lock(pr); 1104 /* 1105 * We go to the burden of extracting rules first instead of just letting 1106 * osd_jail_del() calling dealloc_jail_osd() as we want to decrement 1107 * their use count, and possibly free them, outside of the prison lock. 1108 */ 1109 old_rules = osd_jail_get(pr, osd_jail_slot); 1110 error = osd_jail_set(pr, osd_jail_slot, NULL); 1111 /* osd_set() never fails nor allocate memory when 'value' is NULL. */ 1112 MPASS(error == 0); 1113 /* 1114 * This completely frees the OSD slot, but doesn't call the destructor 1115 * since we've just put NULL in the slot. 1116 */ 1117 osd_jail_del(pr, osd_jail_slot); 1118 prison_unlock(pr); 1119 1120 if (old_rules != NULL) 1121 drop_rules(old_rules); 1122 } 1123 1124 /* 1125 * Assign already built rules to a jail. 1126 */ 1127 static void 1128 set_rules(struct prison *const pr, struct rules *const rules) 1129 { 1130 struct rules *old_rules; 1131 void **rsv; 1132 1133 check_rules_use_count(rules, 0); 1134 hold_rules(rules); 1135 rsv = osd_reserve(osd_jail_slot); 1136 1137 prison_lock(pr); 1138 old_rules = osd_jail_get(pr, osd_jail_slot); 1139 osd_jail_set_reserved(pr, osd_jail_slot, rsv, rules); 1140 prison_unlock(pr); 1141 if (old_rules != NULL) 1142 drop_rules(old_rules); 1143 } 1144 1145 /* 1146 * Assigns empty rules to a jail. 1147 */ 1148 static void 1149 set_empty_rules(struct prison *const pr) 1150 { 1151 struct rules *const rules = alloc_rules(); 1152 1153 set_rules(pr, rules); 1154 } 1155 1156 /* 1157 * Parse a rules specification and assign them to a jail. 1158 * 1159 * Returns the same error code as parse_rules() (which see). 1160 */ 1161 static int 1162 parse_and_set_rules(struct prison *const pr, const char *rules_string, 1163 struct parse_error **const parse_error) 1164 { 1165 struct rules *rules; 1166 int error; 1167 1168 error = parse_rules(rules_string, &rules, parse_error); 1169 if (error != 0) 1170 return (error); 1171 set_rules(pr, rules); 1172 return (0); 1173 } 1174 1175 static int 1176 mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) 1177 { 1178 char *const buf = malloc(MAC_RULE_STRING_LEN, M_DO, M_WAITOK); 1179 struct prison *const td_pr = req->td->td_ucred->cr_prison; 1180 struct prison *pr; 1181 struct rules *rules; 1182 struct parse_error *parse_error; 1183 int error; 1184 1185 rules = find_rules(td_pr, &pr); 1186 strlcpy(buf, rules->string, MAC_RULE_STRING_LEN); 1187 prison_unlock(pr); 1188 1189 error = sysctl_handle_string(oidp, buf, MAC_RULE_STRING_LEN, req); 1190 if (error != 0 || req->newptr == NULL) 1191 goto out; 1192 1193 /* Set our prison's rules, not that of the jail we inherited from. */ 1194 error = parse_and_set_rules(td_pr, buf, &parse_error); 1195 if (error != 0) { 1196 if (print_parse_error) 1197 printf("MAC/do: Parse error at index %zu: %s\n", 1198 parse_error->pos, parse_error->msg); 1199 free_parse_error(parse_error); 1200 } 1201 out: 1202 free(buf, M_DO); 1203 return (error); 1204 } 1205 1206 SYSCTL_PROC(_security_mac_do, OID_AUTO, rules, 1207 CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON|CTLFLAG_MPSAFE, 1208 0, 0, mac_do_sysctl_rules, "A", 1209 "Rules"); 1210 1211 1212 SYSCTL_JAIL_PARAM_SYS_SUBNODE(mac, do, CTLFLAG_RW, "Jail MAC/do parameters"); 1213 SYSCTL_JAIL_PARAM_STRING(_mac_do, rules, CTLFLAG_RW, MAC_RULE_STRING_LEN, 1214 "Jail MAC/do rules"); 1215 1216 1217 static int 1218 mac_do_jail_create(void *obj, void *data __unused) 1219 { 1220 struct prison *const pr = obj; 1221 1222 set_empty_rules(pr); 1223 return (0); 1224 } 1225 1226 static int 1227 mac_do_jail_get(void *obj, void *data) 1228 { 1229 struct prison *ppr, *const pr = obj; 1230 struct vfsoptlist *const opts = data; 1231 struct rules *rules; 1232 int jsys, error; 1233 1234 rules = find_rules(pr, &ppr); 1235 1236 jsys = pr == ppr ? 1237 (TAILQ_EMPTY(&rules->head) ? JAIL_SYS_DISABLE : JAIL_SYS_NEW) : 1238 JAIL_SYS_INHERIT; 1239 error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys)); 1240 if (error != 0 && error != ENOENT) 1241 goto done; 1242 1243 error = vfs_setopts(opts, "mac.do.rules", rules->string); 1244 if (error != 0 && error != ENOENT) 1245 goto done; 1246 1247 error = 0; 1248 done: 1249 prison_unlock(ppr); 1250 return (error); 1251 } 1252 1253 /* 1254 * -1 is used as a sentinel in mac_do_jail_check() and mac_do_jail_set() below. 1255 */ 1256 _Static_assert(-1 != JAIL_SYS_DISABLE && -1 != JAIL_SYS_NEW && 1257 -1 != JAIL_SYS_INHERIT, 1258 "mac_do(4) uses -1 as a sentinel for uninitialized 'jsys'."); 1259 1260 /* 1261 * We perform only cheap checks here, i.e., we do not really parse the rules 1262 * specification string, if any. 1263 */ 1264 static int 1265 mac_do_jail_check(void *obj, void *data) 1266 { 1267 struct vfsoptlist *opts = data; 1268 char *rules_string; 1269 int error, jsys, size; 1270 1271 error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys)); 1272 if (error == ENOENT) 1273 jsys = -1; 1274 else { 1275 if (error != 0) 1276 return (error); 1277 if (jsys != JAIL_SYS_DISABLE && jsys != JAIL_SYS_NEW && 1278 jsys != JAIL_SYS_INHERIT) 1279 return (EINVAL); 1280 } 1281 1282 /* 1283 * We use vfs_getopt() here instead of vfs_getopts() to get the length. 1284 * We perform the additional checks done by the latter here, even if 1285 * jail_set() calls vfs_getopts() itself later (they becoming 1286 * inconsistent wouldn't cause any security problem). 1287 */ 1288 error = vfs_getopt(opts, "mac.do.rules", (void**)&rules_string, &size); 1289 if (error == ENOENT) { 1290 /* 1291 * Default (in absence of "mac.do.rules") is to disable (and, in 1292 * particular, not inherit). 1293 */ 1294 if (jsys == -1) 1295 jsys = JAIL_SYS_DISABLE; 1296 1297 if (jsys == JAIL_SYS_NEW) { 1298 vfs_opterror(opts, "'mac.do.rules' must be specified " 1299 "given 'mac.do''s value"); 1300 return (EINVAL); 1301 } 1302 1303 /* Absence of "mac.do.rules" at this point is OK. */ 1304 error = 0; 1305 } else { 1306 if (error != 0) 1307 return (error); 1308 1309 /* Not a proper string. */ 1310 if (size == 0 || rules_string[size - 1] != '\0') { 1311 vfs_opterror(opts, "'mac.do.rules' not a proper string"); 1312 return (EINVAL); 1313 } 1314 1315 if (size > MAC_RULE_STRING_LEN) { 1316 vfs_opterror(opts, "'mdo.rules' too long"); 1317 return (ENAMETOOLONG); 1318 } 1319 1320 if (jsys == -1) 1321 /* Default (if "mac.do.rules" is present). */ 1322 jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE : 1323 JAIL_SYS_NEW; 1324 1325 /* 1326 * Be liberal and accept JAIL_SYS_DISABLE and JAIL_SYS_INHERIT 1327 * with an explicit empty rules specification. 1328 */ 1329 switch (jsys) { 1330 case JAIL_SYS_DISABLE: 1331 case JAIL_SYS_INHERIT: 1332 if (rules_string[0] != '\0') { 1333 vfs_opterror(opts, "'mac.do.rules' specified " 1334 "but should not given 'mac.do''s value"); 1335 return (EINVAL); 1336 } 1337 break; 1338 } 1339 } 1340 1341 return (error); 1342 } 1343 1344 static int 1345 mac_do_jail_set(void *obj, void *data) 1346 { 1347 struct prison *pr = obj; 1348 struct vfsoptlist *opts = data; 1349 char *rules_string; 1350 struct parse_error *parse_error; 1351 int error, jsys; 1352 1353 /* 1354 * The invariants checks used below correspond to what has already been 1355 * checked in jail_check() above. 1356 */ 1357 1358 error = vfs_copyopt(opts, "mac.do", &jsys, sizeof(jsys)); 1359 MPASS(error == 0 || error == ENOENT); 1360 if (error != 0) 1361 jsys = -1; /* Mark unfilled. */ 1362 1363 rules_string = vfs_getopts(opts, "mac.do.rules", &error); 1364 MPASS(error == 0 || error == ENOENT); 1365 if (error == 0) { 1366 MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN); 1367 if (jsys == -1) 1368 /* Default (if "mac.do.rules" is present). */ 1369 jsys = rules_string[0] == '\0' ? JAIL_SYS_DISABLE : 1370 JAIL_SYS_NEW; 1371 else 1372 MPASS(jsys == JAIL_SYS_NEW || 1373 ((jsys == JAIL_SYS_DISABLE || 1374 jsys == JAIL_SYS_INHERIT) && 1375 rules_string[0] == '\0')); 1376 } else { 1377 MPASS(jsys != JAIL_SYS_NEW); 1378 if (jsys == -1) 1379 /* 1380 * Default (in absence of "mac.do.rules") is to disable 1381 * (and, in particular, not inherit). 1382 */ 1383 jsys = JAIL_SYS_DISABLE; 1384 /* If disabled, we'll store an empty rule specification. */ 1385 if (jsys == JAIL_SYS_DISABLE) 1386 rules_string = ""; 1387 } 1388 1389 switch (jsys) { 1390 case JAIL_SYS_INHERIT: 1391 remove_rules(pr); 1392 error = 0; 1393 break; 1394 case JAIL_SYS_DISABLE: 1395 case JAIL_SYS_NEW: 1396 error = parse_and_set_rules(pr, rules_string, &parse_error); 1397 if (error != 0) { 1398 vfs_opterror(opts, 1399 "MAC/do: Parse error at index %zu: %s\n", 1400 parse_error->pos, parse_error->msg); 1401 free_parse_error(parse_error); 1402 } 1403 break; 1404 default: 1405 __assert_unreachable(); 1406 } 1407 return (error); 1408 } 1409 1410 /* 1411 * OSD jail methods. 1412 * 1413 * There is no PR_METHOD_REMOVE, as OSD storage is destroyed by the common jail 1414 * code (see prison_cleanup()), which triggers a run of our dealloc_jail_osd() 1415 * destructor. 1416 */ 1417 static const osd_method_t osd_methods[PR_MAXMETHOD] = { 1418 [PR_METHOD_CREATE] = mac_do_jail_create, 1419 [PR_METHOD_GET] = mac_do_jail_get, 1420 [PR_METHOD_CHECK] = mac_do_jail_check, 1421 [PR_METHOD_SET] = mac_do_jail_set, 1422 }; 1423 1424 1425 /* 1426 * Common header structure. 1427 * 1428 * Each structure that is used to pass information between some MAC check 1429 * function and priv_grant() must start with this header. 1430 */ 1431 struct mac_do_data_header { 1432 /* Size of the allocated buffer holding the containing structure. */ 1433 size_t allocated_size; 1434 /* Full size of the containing structure. */ 1435 size_t size; 1436 /* 1437 * For convenience, we use privilege numbers as an identifier for the 1438 * containing structure's type, since there is one distinct privilege 1439 * for each privilege changing function we are supporting. 0 in 'priv' 1440 * indicates this header is uninitialized. 1441 */ 1442 int priv; 1443 /* Rules to apply. */ 1444 struct rules *rules; 1445 }; 1446 1447 /* 1448 * The case of unusable or absent per-thread data can actually happen as nothing 1449 * prevents, e.g., priv_check*() with privilege 'priv' to be called standalone, 1450 * as it is currently by, e.g., the Linux emulator for PRIV_CRED_SETUID. We 1451 * interpret such calls to priv_check*() as full, unrestricted requests for 1452 * 'priv', contrary to what we're doing here for selected operations, and 1453 * consequently will not grant the requested privilege. 1454 * 1455 * Also, we protect ourselves from a concurrent change of 'do_enabled' while 1456 * a call to setcred() is in progress by storing the rules per-thread 1457 * which is then consulted by each successive hook so that they all have 1458 * a coherent view of the specifications, and we empty the slot (actually, mark 1459 * it as empty) when MAC/do is disabled. 1460 */ 1461 static int 1462 check_data_usable(const void *const data, const size_t size, const int priv) 1463 { 1464 const struct mac_do_data_header *const hdr = data; 1465 1466 if (hdr == NULL || hdr->priv == 0) 1467 return (ENOENT); 1468 /* 1469 * Impacting changes in the protocols we are based on... Don't crash in 1470 * production. 1471 */ 1472 if (hdr->priv != priv) { 1473 MPASS(hdr->priv == priv); 1474 return (EBUSY); 1475 } 1476 MPASS(hdr->size == size); 1477 MPASS(hdr->size <= hdr->allocated_size); 1478 return (0); 1479 } 1480 1481 static void 1482 clear_data(void *const data) 1483 { 1484 struct mac_do_data_header *const hdr = data; 1485 1486 if (hdr != NULL) { 1487 drop_rules(hdr->rules); 1488 /* We don't deallocate so as to save time on next access. */ 1489 hdr->priv = 0; 1490 } 1491 } 1492 1493 static void * 1494 fetch_data(void) 1495 { 1496 return (osd_thread_get_unlocked(curthread, osd_thread_slot)); 1497 } 1498 1499 static bool 1500 is_data_reusable(const void *const data, const size_t size) 1501 { 1502 const struct mac_do_data_header *const hdr = data; 1503 1504 return (hdr != NULL && size <= hdr->allocated_size); 1505 } 1506 1507 static void 1508 set_data_header(void *const data, const size_t size, const int priv, 1509 struct rules *const rules) 1510 { 1511 struct mac_do_data_header *const hdr = data; 1512 1513 MPASS(hdr->priv == 0); 1514 MPASS(priv != 0); 1515 MPASS(size <= hdr->allocated_size); 1516 hdr->size = size; 1517 hdr->priv = priv; 1518 hdr->rules = rules; 1519 } 1520 1521 /* The proc lock (and any other non-sleepable lock) must not be held. */ 1522 static void * 1523 alloc_data(void *const data, const size_t size) 1524 { 1525 struct mac_do_data_header *const hdr = realloc(data, size, M_DO, 1526 M_WAITOK); 1527 1528 MPASS(size >= sizeof(struct mac_do_data_header)); 1529 hdr->allocated_size = size; 1530 hdr->priv = 0; 1531 if (hdr != data) { 1532 /* 1533 * This call either reuses the existing memory allocated for the 1534 * slot or tries to allocate some without blocking. 1535 */ 1536 int error = osd_thread_set(curthread, osd_thread_slot, hdr); 1537 1538 if (error != 0) { 1539 /* Going to make a M_WAITOK allocation. */ 1540 void **const rsv = osd_reserve(osd_thread_slot); 1541 1542 error = osd_thread_set_reserved(curthread, 1543 osd_thread_slot, rsv, hdr); 1544 MPASS(error == 0); 1545 } 1546 } 1547 return (hdr); 1548 } 1549 1550 /* Destructor for 'osd_thread_slot'. */ 1551 static void 1552 dealloc_thread_osd(void *const value) 1553 { 1554 free(value, M_DO); 1555 } 1556 1557 /* 1558 * Whether to grant access to some primary group according to flags. 1559 * 1560 * The passed 'flags' must be those of a rule's matching GID, or the IT_GID type 1561 * flags when MDF_CURRENT has been matched. 1562 * 1563 * Return values: 1564 * - 0: Access granted. 1565 * - EJUSTRETURN: Flags are agnostic. 1566 */ 1567 static int 1568 grant_primary_group_from_flags(const flags_t flags) 1569 { 1570 return ((flags & MDF_PRIMARY) != 0 ? 0 : EJUSTRETURN); 1571 } 1572 1573 /* 1574 * Same as grant_primary_group_from_flags(), but for supplementary groups. 1575 * 1576 * Return values: 1577 * - 0: Access granted. 1578 * - EJUSTRETURN: Flags are agnostic. 1579 * - EPERM: Access denied. 1580 */ 1581 static int 1582 grant_supplementary_group_from_flags(const flags_t flags) 1583 { 1584 if ((flags & MDF_SUPP_MASK) != 0) 1585 return ((flags & MDF_SUPP_DONT) != 0 ? EPERM : 0); 1586 1587 return (EJUSTRETURN); 1588 } 1589 1590 static int 1591 rule_grant_supplementary_groups(const struct rule *const rule, 1592 const struct ucred *const old_cred, const struct ucred *const new_cred) 1593 { 1594 const gid_t *const old_groups = old_cred->cr_groups; 1595 const gid_t *const new_groups = new_cred->cr_groups; 1596 const int old_ngroups = old_cred->cr_ngroups; 1597 const int new_ngroups = new_cred->cr_ngroups; 1598 const flags_t gid_flags = rule->gid_flags; 1599 const bool current_has_supp = (gid_flags & MDF_CURRENT) != 0 && 1600 (gid_flags & MDF_SUPP_MASK) != 0; 1601 id_nb_t rule_idx = 0; 1602 int old_idx = 1, new_idx = 1; 1603 1604 if ((gid_flags & MDF_ANY_SUPP) != 0 && 1605 (gid_flags & MDF_MAY_REJ_SUPP) == 0) 1606 /* 1607 * Any set of supplementary groups is accepted, no need to loop 1608 * over them. 1609 */ 1610 return (0); 1611 1612 for (; new_idx < new_ngroups; ++new_idx) { 1613 const gid_t gid = new_groups[new_idx]; 1614 bool may_accept = false; 1615 1616 if ((gid_flags & MDF_ANY_SUPP) != 0) 1617 may_accept = true; 1618 1619 /* Do we have to check for the current supplementary groups? */ 1620 if (current_has_supp) { 1621 /* 1622 * Linear search, as both supplementary groups arrays 1623 * are sorted. Advancing 'old_idx' with a binary search 1624 * on absence of MDF_SUPP_MUST doesn't seem worth it in 1625 * practice. 1626 */ 1627 for (; old_idx < old_ngroups; ++old_idx) { 1628 const gid_t old_gid = old_groups[old_idx]; 1629 1630 if (old_gid < gid) { 1631 /* Mandatory but absent. */ 1632 if ((gid_flags & MDF_SUPP_MUST) != 0) 1633 return (EPERM); 1634 } else if (old_gid == gid) { 1635 switch (gid_flags & MDF_SUPP_MASK) { 1636 case MDF_SUPP_DONT: 1637 /* Present but forbidden. */ 1638 return (EPERM); 1639 case MDF_SUPP_ALLOW: 1640 case MDF_SUPP_MUST: 1641 may_accept = true; 1642 break; 1643 default: 1644 #ifdef INVARIANTS 1645 __assert_unreachable(); 1646 #else 1647 /* Better be safe than sorry. */ 1648 return (EPERM); 1649 #endif 1650 } 1651 ++old_idx; 1652 break; 1653 } 1654 else 1655 break; 1656 } 1657 } 1658 1659 /* 1660 * Search by GID for a corresponding 'struct id_spec'. 1661 * 1662 * Again, linear search, with same note on not using binary 1663 * search optimization as above (the trigger would be absence of 1664 * MDF_EXPLICIT_SUPP_MUST this time). 1665 */ 1666 for (; rule_idx < rule->gids_nb; ++rule_idx) { 1667 const struct id_spec is = rule->gids[rule_idx]; 1668 1669 if (is.id < gid) { 1670 /* Mandatory but absent. */ 1671 if ((is.flags & MDF_SUPP_MUST) != 0) 1672 return (EPERM); 1673 } else if (is.id == gid) { 1674 switch (is.flags & MDF_SUPP_MASK) { 1675 case MDF_SUPP_DONT: 1676 /* Present but forbidden. */ 1677 return (EPERM); 1678 case MDF_SUPP_ALLOW: 1679 case MDF_SUPP_MUST: 1680 may_accept = true; 1681 break; 1682 case 0: 1683 /* Primary group only. */ 1684 break; 1685 default: 1686 #ifdef INVARIANTS 1687 __assert_unreachable(); 1688 #else 1689 /* Better be safe than sorry. */ 1690 return (EPERM); 1691 #endif 1692 } 1693 ++rule_idx; 1694 break; 1695 } 1696 else 1697 break; 1698 } 1699 1700 /* 'gid' wasn't explicitly accepted. */ 1701 if (!may_accept) 1702 return (EPERM); 1703 } 1704 1705 /* 1706 * If we must have all current groups and we didn't browse all 1707 * of them at this point (because the remaining ones have GIDs 1708 * greater than the last requested group), we are simply missing 1709 * them. 1710 */ 1711 if ((gid_flags & MDF_CURRENT) != 0 && 1712 (gid_flags & MDF_SUPP_MUST) != 0 && 1713 old_idx < old_ngroups) 1714 return (EPERM); 1715 /* 1716 * Similarly, we have to finish browsing all GIDs from the rule 1717 * in case some are marked mandatory. 1718 */ 1719 if ((gid_flags & MDF_EXPLICIT_SUPP_MUST) != 0) { 1720 for (; rule_idx < rule->gids_nb; ++rule_idx) { 1721 const struct id_spec is = rule->gids[rule_idx]; 1722 1723 if ((is.flags & MDF_SUPP_MUST) != 0) 1724 return (EPERM); 1725 } 1726 } 1727 1728 return (0); 1729 } 1730 1731 static int 1732 rule_grant_primary_group(const struct rule *const rule, 1733 const struct ucred *const old_cred, const gid_t gid) 1734 { 1735 struct id_spec gid_is = {.flags = 0}; 1736 const struct id_spec *found_is; 1737 int error; 1738 1739 if ((rule->gid_flags & MDF_ANY) != 0) 1740 return (0); 1741 1742 /* Was MDF_CURRENT specified, and is 'gid' a current GID? */ 1743 if ((rule->gid_flags & MDF_CURRENT) != 0 && 1744 group_is_primary(gid, old_cred)) { 1745 error = grant_primary_group_from_flags(rule->gid_flags); 1746 if (error == 0) 1747 return (0); 1748 } 1749 1750 /* Search by GID for a corresponding 'struct id_spec'. */ 1751 gid_is.id = gid; 1752 found_is = bsearch(&gid_is, rule->gids, rule->gids_nb, 1753 sizeof(*rule->gids), id_spec_cmp); 1754 1755 if (found_is != NULL) { 1756 error = grant_primary_group_from_flags(found_is->flags); 1757 if (error == 0) 1758 return (0); 1759 } 1760 1761 return (EPERM); 1762 } 1763 1764 static int 1765 rule_grant_primary_groups(const struct rule *const rule, 1766 const struct ucred *const old_cred, const struct ucred *const new_cred) 1767 { 1768 int error; 1769 1770 /* Shortcut. */ 1771 if ((rule->gid_flags & MDF_ANY) != 0) 1772 return (0); 1773 1774 error = rule_grant_primary_group(rule, old_cred, new_cred->cr_gid); 1775 if (error != 0) 1776 return (error); 1777 error = rule_grant_primary_group(rule, old_cred, new_cred->cr_rgid); 1778 if (error != 0) 1779 return (error); 1780 error = rule_grant_primary_group(rule, old_cred, new_cred->cr_svgid); 1781 if (error != 0) 1782 return (error); 1783 return (0); 1784 } 1785 1786 static bool 1787 user_is_current(const uid_t uid, const struct ucred *const old_cred) 1788 { 1789 return (uid == old_cred->cr_uid || uid == old_cred->cr_ruid || 1790 uid == old_cred->cr_svuid); 1791 } 1792 1793 static int 1794 rule_grant_user(const struct rule *const rule, 1795 const struct ucred *const old_cred, const uid_t uid) 1796 { 1797 struct id_spec uid_is = {.flags = 0}; 1798 const struct id_spec *found_is; 1799 1800 if ((rule->uid_flags & MDF_ANY) != 0) 1801 return (0); 1802 1803 /* Was MDF_CURRENT specified, and is 'uid' a current UID? */ 1804 if ((rule->uid_flags & MDF_CURRENT) != 0 && 1805 user_is_current(uid, old_cred)) 1806 return (0); 1807 1808 /* Search by UID for a corresponding 'struct id_spec'. */ 1809 uid_is.id = uid; 1810 found_is = bsearch(&uid_is, rule->uids, rule->uids_nb, 1811 sizeof(*rule->uids), id_spec_cmp); 1812 1813 if (found_is != NULL) 1814 return (0); 1815 1816 return (EPERM); 1817 } 1818 1819 static int 1820 rule_grant_users(const struct rule *const rule, 1821 const struct ucred *const old_cred, const struct ucred *const new_cred) 1822 { 1823 int error; 1824 1825 /* Shortcut. */ 1826 if ((rule->uid_flags & MDF_ANY) != 0) 1827 return (0); 1828 1829 error = rule_grant_user(rule, old_cred, new_cred->cr_uid); 1830 if (error != 0) 1831 return (error); 1832 error = rule_grant_user(rule, old_cred, new_cred->cr_ruid); 1833 if (error != 0) 1834 return (error); 1835 error = rule_grant_user(rule, old_cred, new_cred->cr_svuid); 1836 if (error != 0) 1837 return (error); 1838 1839 return (0); 1840 } 1841 1842 static int 1843 rule_grant_setcred(const struct rule *const rule, 1844 const struct ucred *const old_cred, const struct ucred *const new_cred) 1845 { 1846 int error; 1847 1848 error = rule_grant_users(rule, old_cred, new_cred); 1849 if (error != 0) 1850 return (error); 1851 error = rule_grant_primary_groups(rule, old_cred, new_cred); 1852 if (error != 0) 1853 return (error); 1854 error = rule_grant_supplementary_groups(rule, old_cred, new_cred); 1855 if (error != 0) 1856 return (error); 1857 1858 return (0); 1859 } 1860 1861 static bool 1862 rule_applies(const struct rule *const rule, const struct ucred *const cred) 1863 { 1864 if (rule->from_type == IT_UID && rule->from_id == cred->cr_uid) 1865 return (true); 1866 if (rule->from_type == IT_GID && groupmember(rule->from_id, cred)) 1867 return (true); 1868 return (false); 1869 } 1870 1871 /* 1872 * To pass data between check_setcred() and priv_grant() (on PRIV_CRED_SETCRED). 1873 */ 1874 struct mac_do_setcred_data { 1875 struct mac_do_data_header hdr; 1876 const struct ucred *new_cred; 1877 u_int setcred_flags; 1878 }; 1879 1880 static int 1881 mac_do_priv_grant(struct ucred *cred, int priv) 1882 { 1883 struct mac_do_setcred_data *const data = fetch_data(); 1884 const struct rules *rules; 1885 const struct ucred *new_cred; 1886 const struct rule *rule; 1887 u_int setcred_flags; 1888 int error; 1889 1890 /* Bail out fast if we aren't concerned. */ 1891 if (priv != PRIV_CRED_SETCRED) 1892 return (EPERM); 1893 1894 /* 1895 * Do we have to do something? 1896 */ 1897 if (check_data_usable(data, sizeof(*data), priv) != 0) 1898 /* No. */ 1899 return (EPERM); 1900 1901 rules = data->hdr.rules; 1902 new_cred = data->new_cred; 1903 KASSERT(new_cred != NULL, 1904 ("priv_check*() called before mac_cred_check_setcred()")); 1905 setcred_flags = data->setcred_flags; 1906 1907 /* 1908 * Explicitly check that only the flags we currently support are present 1909 * in order to avoid accepting transitions with other changes than those 1910 * we are actually going to check. Currently, this rules out the 1911 * SETCREDF_MAC_LABEL flag. This may be improved by adding code 1912 * actually checking whether the requested label and the current one 1913 * would differ. 1914 */ 1915 if ((setcred_flags & ~(SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID | 1916 SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID | 1917 SETCREDF_SUPP_GROUPS)) != 0) 1918 return (EPERM); 1919 1920 /* 1921 * Browse rules, and for those that match the requestor, call specific 1922 * privilege granting functions interpreting the "to"/"target" part. 1923 */ 1924 error = EPERM; 1925 TAILQ_FOREACH(rule, &rules->head, r_entries) 1926 if (rule_applies(rule, cred)) { 1927 error = rule_grant_setcred(rule, cred, new_cred); 1928 if (error != EPERM) 1929 break; 1930 } 1931 1932 return (error); 1933 } 1934 1935 static int 1936 check_proc(void) 1937 { 1938 char *path, *to_free; 1939 int error; 1940 1941 /* 1942 * Only grant privileges if requested by the right executable. 1943 * 1944 * XXXOC: We may want to base this check on a tunable path and/or 1945 * a specific MAC label. Going even further, e.g., envisioning to 1946 * completely replace the path check with the latter, we would need to 1947 * install FreeBSD on a FS with multilabel enabled by default, which in 1948 * practice entails adding an option to ZFS to set MNT_MULTILABEL 1949 * automatically on mounts, ensuring that root (and more if using 1950 * different partitions) ZFS or UFS filesystems are created with 1951 * multilabel turned on, and having the installation procedure support 1952 * setting a MAC label per file (perhaps via additions to mtree(1)). So 1953 * this probably isn't going to happen overnight, if ever. 1954 */ 1955 if (vn_fullpath(curproc->p_textvp, &path, &to_free) != 0) 1956 return (EPERM); 1957 error = strcmp(path, "/usr/bin/mdo") == 0 ? 0 : EPERM; 1958 free(to_free, M_TEMP); 1959 return (error); 1960 } 1961 1962 static void 1963 mac_do_setcred_enter(void) 1964 { 1965 struct rules *rules; 1966 struct prison *pr; 1967 struct mac_do_setcred_data * data; 1968 int error; 1969 1970 /* 1971 * If not enabled, don't prepare data. Other hooks will check for that 1972 * to know if they have to do something. 1973 */ 1974 if (do_enabled == 0) 1975 return; 1976 1977 /* 1978 * MAC/do only applies to a process launched from a given executable. 1979 * For other processes, we just won't intervene (we don't deny requests, 1980 * nor do we grant privileges to them). 1981 */ 1982 error = check_proc(); 1983 if (error != 0) 1984 return; 1985 1986 /* 1987 * Find the currently applicable rules. 1988 */ 1989 rules = find_rules(curproc->p_ucred->cr_prison, &pr); 1990 hold_rules(rules); 1991 prison_unlock(pr); 1992 1993 /* 1994 * Setup thread data to be used by other hooks. 1995 */ 1996 data = fetch_data(); 1997 if (!is_data_reusable(data, sizeof(*data))) 1998 data = alloc_data(data, sizeof(*data)); 1999 set_data_header(data, sizeof(*data), PRIV_CRED_SETCRED, rules); 2000 /* Not really necessary, but helps to catch programming errors. */ 2001 data->new_cred = NULL; 2002 data->setcred_flags = 0; 2003 } 2004 2005 static int 2006 mac_do_check_setcred(u_int flags, const struct ucred *const old_cred, 2007 struct ucred *const new_cred) 2008 { 2009 struct mac_do_setcred_data *const data = fetch_data(); 2010 2011 /* 2012 * Do we have to do something? 2013 */ 2014 if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) != 0) 2015 /* No. */ 2016 return (0); 2017 2018 /* 2019 * Keep track of the setcred() flags and the new credentials for 2020 * priv_check*(). 2021 */ 2022 data->new_cred = new_cred; 2023 data->setcred_flags = flags; 2024 2025 return (0); 2026 } 2027 2028 static void 2029 mac_do_setcred_exit(void) 2030 { 2031 struct mac_do_setcred_data *const data = fetch_data(); 2032 2033 if (check_data_usable(data, sizeof(*data), PRIV_CRED_SETCRED) == 0) 2034 /* 2035 * This doesn't deallocate the small per-thread data storage, 2036 * which can be reused on subsequent calls. (That data is of 2037 * course deallocated as the current thread dies or this module 2038 * is unloaded.) 2039 */ 2040 clear_data(data); 2041 } 2042 2043 static void 2044 mac_do_init(struct mac_policy_conf *mpc) 2045 { 2046 struct prison *pr; 2047 2048 osd_jail_slot = osd_jail_register(dealloc_jail_osd, osd_methods); 2049 set_empty_rules(&prison0); 2050 sx_slock(&allprison_lock); 2051 TAILQ_FOREACH(pr, &allprison, pr_list) 2052 set_empty_rules(pr); 2053 sx_sunlock(&allprison_lock); 2054 2055 osd_thread_slot = osd_thread_register(dealloc_thread_osd); 2056 } 2057 2058 static void 2059 mac_do_destroy(struct mac_policy_conf *mpc) 2060 { 2061 /* 2062 * osd_thread_deregister() must be called before osd_jail_deregister(), 2063 * for the reason explained in dealloc_jail_osd(). 2064 */ 2065 osd_thread_deregister(osd_thread_slot); 2066 osd_jail_deregister(osd_jail_slot); 2067 } 2068 2069 static struct mac_policy_ops do_ops = { 2070 .mpo_init = mac_do_init, 2071 .mpo_destroy = mac_do_destroy, 2072 .mpo_cred_setcred_enter = mac_do_setcred_enter, 2073 .mpo_cred_check_setcred = mac_do_check_setcred, 2074 .mpo_cred_setcred_exit = mac_do_setcred_exit, 2075 .mpo_priv_grant = mac_do_priv_grant, 2076 }; 2077 2078 MAC_POLICY_SET(&do_ops, mac_do, "MAC/do", MPC_LOADTIME_FLAG_UNLOADOK, NULL); 2079 MODULE_VERSION(mac_do, 1); 2080