| 508 | #undef FPO |
| 509 | |
| 510 | static int |
| 511 | mac_policy_register(struct mac_policy_conf *mpc) |
| 512 | { |
| 513 | struct mac_policy_conf *tmpc; |
| 514 | int error, slot, static_entry; |
| 515 | |
| 516 | error = 0; |
| 517 | |
| 518 | /* |
| 519 | * We don't technically need exclusive access while !mac_late, but |
| 520 | * hold it for assertion consistency. |
| 521 | */ |
| 522 | mac_policy_xlock(); |
| 523 | |
| 524 | /* |
| 525 | * If the module can potentially be unloaded, or we're loading late, |
| 526 | * we have to stick it in the non-static list and pay an extra |
| 527 | * performance overhead. Otherwise, we can pay a light locking cost |
| 528 | * and stick it in the static list. |
| 529 | */ |
| 530 | static_entry = (!mac_late && |
| 531 | !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); |
| 532 | |
| 533 | if (static_entry) { |
| 534 | LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { |
| 535 | if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { |
| 536 | error = EEXIST; |
| 537 | goto out; |
| 538 | } |
| 539 | } |
| 540 | } else { |
| 541 | LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { |
| 542 | if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { |
| 543 | error = EEXIST; |
| 544 | goto out; |
| 545 | } |
| 546 | } |
| 547 | } |
| 548 | if (mpc->mpc_field_off != NULL) { |
| 549 | slot = ffs(mac_slot_offsets_free); |
| 550 | if (slot == 0) { |
| 551 | error = ENOMEM; |
| 552 | goto out; |
| 553 | } |
| 554 | slot--; |
| 555 | mac_slot_offsets_free &= ~(1 << slot); |
| 556 | *mpc->mpc_field_off = slot; |
| 557 | } |
| 558 | mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; |
| 559 | |
| 560 | /* |
| 561 | * If we're loading a MAC module after the framework has initialized, |
| 562 | * it has to go into the dynamic list. If we're loading it before |
| 563 | * we've finished initializing, it can go into the static list with |
| 564 | * weaker locker requirements. |
| 565 | */ |
| 566 | if (static_entry) |
| 567 | LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); |
no test coverage detected