41 */ 42 43/* 44 * Developed by the TrustedBSD Project. 45 * 46 * "BSD Extended" MAC policy, allowing the administrator to impose mandatory 47 * firewall-like rules regarding users and file system objects. 48 */ 49 50#include <sys/param.h> 51#include <sys/acl.h> 52#include <sys/kernel.h> 53#include <sys/jail.h> 54#include <sys/lock.h> 55#include <sys/malloc.h> 56#include <sys/module.h> 57#include <sys/mount.h> 58#include <sys/mutex.h> 59#include <sys/priv.h> 60#include <sys/systm.h> 61#include <sys/vnode.h> 62#include <sys/sysctl.h> 63#include <sys/syslog.h> 64 65#include <security/mac/mac_policy.h> 66#include <security/mac_bsdextended/mac_bsdextended.h> 67 68static struct mtx ugidfw_mtx; 69 70SYSCTL_DECL(_security_mac); 71 72SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 73 "TrustedBSD extended BSD MAC policy controls"); 74 75static int ugidfw_enabled = 1; 76SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 77 &ugidfw_enabled, 0, "Enforce extended BSD policy"); 78TUNABLE_INT("security.mac.bsdextended.enabled", &ugidfw_enabled); 79 80MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 81 82#define MAC_BSDEXTENDED_MAXRULES 250 83static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 84static int rule_count = 0; 85static int rule_slots = 0; 86static int rule_version = MB_VERSION; 87 88SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 89 &rule_count, 0, "Number of defined rules\n"); 90SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 91 &rule_slots, 0, "Number of used rule slots\n"); 92SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 93 &rule_version, 0, "Version number for API\n"); 94 95/* 96 * This is just used for logging purposes, eventually we would like to log 97 * much more then failed requests. 98 */ 99static int ugidfw_logging; 100SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 101 &ugidfw_logging, 0, "Log failed authorization requests"); 102 103/* 104 * This tunable is here for compatibility. It will allow the user to switch 105 * between the new mode (first rule matches) and the old functionality (all 106 * rules match). 107 */ 108static int ugidfw_firstmatch_enabled; 109SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 110 CTLFLAG_RW, &ugidfw_firstmatch_enabled, 1, 111 "Disable/enable match first rule functionality"); 112 113static int 114ugidfw_rule_valid(struct mac_bsdextended_rule *rule) 115{ 116 117 if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 118 return (EINVAL); 119 if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 120 return (EINVAL); 121 if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 122 return (EINVAL); 123 if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 124 return (EINVAL); 125 if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 126 (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 127 return (EINVAL); 128 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 129 return (EINVAL); 130 return (0); 131} 132 133static int 134sysctl_rule(SYSCTL_HANDLER_ARGS) 135{ 136 struct mac_bsdextended_rule temprule, *ruleptr; 137 u_int namelen; 138 int error, index, *name; 139 140 error = 0; 141 name = (int *)arg1; 142 namelen = arg2; 143 if (namelen != 1) 144 return (EINVAL); 145 index = name[0]; 146 if (index >= MAC_BSDEXTENDED_MAXRULES) 147 return (ENOENT); 148 149 ruleptr = NULL; 150 if (req->newptr && req->newlen != 0) { 151 error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 152 if (error) 153 return (error); 154 MALLOC(ruleptr, struct mac_bsdextended_rule *, 155 sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO); 156 } 157 158 mtx_lock(&ugidfw_mtx); 159 if (req->oldptr) { 160 if (index < 0 || index > rule_slots + 1) { 161 error = ENOENT; 162 goto out; 163 } 164 if (rules[index] == NULL) { 165 error = ENOENT; 166 goto out; 167 } 168 temprule = *rules[index]; 169 } 170 if (req->newptr && req->newlen == 0) { 171 KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 172 ruleptr = rules[index]; 173 if (ruleptr == NULL) { 174 error = ENOENT; 175 goto out; 176 } 177 rule_count--; 178 rules[index] = NULL; 179 } else if (req->newptr) { 180 error = ugidfw_rule_valid(&temprule); 181 if (error) 182 goto out; 183 if (rules[index] == NULL) { 184 *ruleptr = temprule; 185 rules[index] = ruleptr; 186 ruleptr = NULL; 187 if (index + 1 > rule_slots) 188 rule_slots = index + 1; 189 rule_count++; 190 } else 191 *rules[index] = temprule; 192 } 193out: 194 mtx_unlock(&ugidfw_mtx); 195 if (ruleptr != NULL) 196 FREE(ruleptr, M_MACBSDEXTENDED); 197 if (req->oldptr && error == 0) 198 error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 199 return (error); 200} 201 202SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW, 203 sysctl_rule, "BSD extended MAC rules"); 204 205static void 206ugidfw_init(struct mac_policy_conf *mpc) 207{ 208 209 mtx_init(&ugidfw_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 210} 211 212static void 213ugidfw_destroy(struct mac_policy_conf *mpc) 214{ 215 216 mtx_destroy(&ugidfw_mtx); 217} 218 219static int 220ugidfw_rulecheck(struct mac_bsdextended_rule *rule, 221 struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 222{ 223 int match; 224 int i; 225 226 /* 227 * Is there a subject match? 228 */ 229 mtx_assert(&ugidfw_mtx, MA_OWNED); 230 if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 231 match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 232 cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 233 (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 234 cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 235 (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 236 cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 237 if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 238 match = !match; 239 if (!match) 240 return (0); 241 } 242 243 if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 244 match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 245 cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 246 (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 247 cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 248 if (!match) { 249 for (i = 0; i < cred->cr_ngroups; i++) { 250 if (cred->cr_groups[i] 251 <= rule->mbr_subject.mbs_gid_max && 252 cred->cr_groups[i] 253 >= rule->mbr_subject.mbs_gid_min) { 254 match = 1; 255 break; 256 } 257 } 258 } 259 if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 260 match = !match; 261 if (!match) 262 return (0); 263 } 264 265 if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 266 match = (cred->cr_prison != NULL && 267 cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 268 if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 269 match = !match; 270 if (!match) 271 return (0); 272 } 273 274 /* 275 * Is there an object match? 276 */ 277 if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 278 match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 279 vap->va_uid >= rule->mbr_object.mbo_uid_min); 280 if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 281 match = !match; 282 if (!match) 283 return (0); 284 } 285 286 if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 287 match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 288 vap->va_gid >= rule->mbr_object.mbo_gid_min); 289 if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 290 match = !match; 291 if (!match) 292 return (0); 293 } 294 295 if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 296 match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 297 &(rule->mbr_object.mbo_fsid), 298 sizeof(rule->mbr_object.mbo_fsid)) == 0); 299 if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 300 match = !match; 301 if (!match) 302 return (0); 303 } 304 305 if (rule->mbr_object.mbo_flags & MBO_SUID) { 306 match = (vap->va_mode & VSUID); 307 if (rule->mbr_object.mbo_neg & MBO_SUID) 308 match = !match; 309 if (!match) 310 return (0); 311 } 312 313 if (rule->mbr_object.mbo_flags & MBO_SGID) { 314 match = (vap->va_mode & VSGID); 315 if (rule->mbr_object.mbo_neg & MBO_SGID) 316 match = !match; 317 if (!match) 318 return (0); 319 } 320 321 if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 322 match = (vap->va_uid == cred->cr_uid || 323 vap->va_uid == cred->cr_ruid || 324 vap->va_uid == cred->cr_svuid); 325 if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 326 match = !match; 327 if (!match) 328 return (0); 329 } 330 331 if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 332 match = (groupmember(vap->va_gid, cred) || 333 vap->va_gid == cred->cr_rgid || 334 vap->va_gid == cred->cr_svgid); 335 if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 336 match = !match; 337 if (!match) 338 return (0); 339 } 340 341 if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 342 switch (vap->va_type) { 343 case VREG: 344 match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 345 break; 346 case VDIR: 347 match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 348 break; 349 case VBLK: 350 match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 351 break; 352 case VCHR: 353 match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 354 break; 355 case VLNK: 356 match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 357 break; 358 case VSOCK: 359 match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 360 break; 361 case VFIFO: 362 match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 363 break; 364 default: 365 match = 0; 366 } 367 if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 368 match = !match; 369 if (!match) 370 return (0); 371 } 372 373 /* 374 * Is the access permitted? 375 */ 376 if ((rule->mbr_mode & acc_mode) != acc_mode) { 377 if (ugidfw_logging) 378 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 379 " on %d:%d failed. \n", cred->cr_ruid, 380 cred->cr_rgid, acc_mode, vap->va_uid, 381 vap->va_gid); 382 return (EACCES); 383 } 384 385 /* 386 * If the rule matched, permits access, and first match is enabled, 387 * return success. 388 */ 389 if (ugidfw_firstmatch_enabled) 390 return (EJUSTRETURN); 391 else 392 return (0); 393} 394 395static int 396ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 397 int acc_mode) 398{ 399 int error, i; 400 401 /* 402 * XXXRW: More specific privilege selection needed. 403 */ 404 if (suser_cred(cred, 0) == 0) 405 return (0); 406 407 /* 408 * Since we do not separately handle append, map append to write. 409 */ 410 if (acc_mode & MBI_APPEND) { 411 acc_mode &= ~MBI_APPEND; 412 acc_mode |= MBI_WRITE; 413 } 414 mtx_lock(&ugidfw_mtx); 415 for (i = 0; i < rule_slots; i++) { 416 if (rules[i] == NULL) 417 continue; 418 error = ugidfw_rulecheck(rules[i], cred, 419 vp, vap, acc_mode); 420 if (error == EJUSTRETURN) 421 break; 422 if (error) { 423 mtx_unlock(&ugidfw_mtx); 424 return (error); 425 } 426 } 427 mtx_unlock(&ugidfw_mtx); 428 return (0); 429} 430 431static int 432ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 433{ 434 int error; 435 struct vattr vap; 436 437 if (!ugidfw_enabled) 438 return (0); 439 error = VOP_GETATTR(vp, &vap, cred, curthread); 440 if (error) 441 return (error); 442 return (ugidfw_check(cred, vp, &vap, acc_mode)); 443} 444 445/* 446 * Object-specific entry point implementations are sorted alphabetically by 447 * object type and then by operation. 448 */ 449static int 450ugidfw_system_check_acct(struct ucred *cred, struct vnode *vp, 451 struct label *vplabel) 452{ 453 454 if (vp != NULL) 455 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 456 else 457 return (0); 458} 459 460static int 461ugidfw_system_check_auditctl(struct ucred *cred, struct vnode *vp, 462 struct label *vplabel) 463{ 464 465 if (vp != NULL) 466 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 467 else 468 return (0); 469} 470 471static int 472ugidfw_system_check_swapon(struct ucred *cred, struct vnode *vp, 473 struct label *vplabel) 474{ 475 476 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 477} 478 479static int 480ugidfw_vnode_check_access(struct ucred *cred, struct vnode *vp, 481 struct label *vplabel, int acc_mode) 482{ 483 484 return (ugidfw_check_vp(cred, vp, acc_mode)); 485} 486 487static int 488ugidfw_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, 489 struct label *dvplabel) 490{ 491 492 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 493} 494 495static int 496ugidfw_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, 497 struct label *dvplabel) 498{ 499 500 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 501} 502 503static int 504ugidfw_check_create_vnode(struct ucred *cred, struct vnode *dvp, 505 struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 506{ 507 508 return (ugidfw_check_vp(cred, dvp, MBI_WRITE)); 509} 510 511static int 512ugidfw_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 513 struct label *vplabel, acl_type_t type) 514{ 515 516 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 517} 518 519static int 520ugidfw_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 521 struct label *vplabel, int attrnamespace, const char *name) 522{ 523 524 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 525} 526 527static int 528ugidfw_vnode_check_exec(struct ucred *cred, struct vnode *vp, 529 struct label *vplabel, struct image_params *imgp, 530 struct label *execlabel) 531{ 532 533 return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 534} 535 536static int 537ugidfw_vnode_check_getacl(struct ucred *cred, struct vnode *vp, 538 struct label *vplabel, acl_type_t type) 539{ 540 541 return (ugidfw_check_vp(cred, vp, MBI_STAT)); 542} 543 544static int 545ugidfw_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 546 struct label *vplabel, int attrnamespace, const char *name, 547 struct uio *uio) 548{ 549 550 return (ugidfw_check_vp(cred, vp, MBI_READ)); 551} 552 553static int 554ugidfw_vnode_check_link(struct ucred *cred, struct vnode *dvp, 555 struct label *dvplabel, struct vnode *vp, struct label *label, 556 struct componentname *cnp) 557{ 558 int error; 559 560 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 561 if (error) 562 return (error); 563 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 564 if (error) 565 return (error); 566 return (0); 567} 568 569static int 570ugidfw_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 571 struct label *vplabel, int attrnamespace) 572{ 573 574 return (ugidfw_check_vp(cred, vp, MBI_READ)); 575} 576 577static int 578ugidfw_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, 579 struct label *dvplabel, struct componentname *cnp) 580{ 581 582 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 583} 584 585static int 586ugidfw_vnode_check_open(struct ucred *cred, struct vnode *vp, 587 struct label *vplabel, int acc_mode) 588{ 589 590 return (ugidfw_check_vp(cred, vp, acc_mode)); 591} 592 593static int 594ugidfw_vnode_check_readdir(struct ucred *cred, struct vnode *dvp, 595 struct label *dvplabel) 596{ 597 598 return (ugidfw_check_vp(cred, dvp, MBI_READ)); 599} 600 601static int 602ugidfw_vnode_check_readdlink(struct ucred *cred, struct vnode *vp, 603 struct label *vplabel) 604{ 605 606 return (ugidfw_check_vp(cred, vp, MBI_READ)); 607} 608 609static int 610ugidfw_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 611 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 612 struct componentname *cnp) 613{ 614 int error; 615 616 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 617 if (error) 618 return (error); 619 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 620} 621 622static int 623ugidfw_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 624 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 625 int samedir, struct componentname *cnp) 626{ 627 int error; 628 629 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 630 if (error) 631 return (error); 632 if (vp != NULL) 633 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 634 return (error); 635} 636 637static int 638ugidfw_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 639 struct label *vplabel) 640{ 641 642 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 643} 644 645static int 646ugidfw_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 647 struct label *vplabel, acl_type_t type, struct acl *acl) 648{ 649 650 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 651} 652 653static int 654ugidfw_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 655 struct label *vplabel, int attrnamespace, const char *name, 656 struct uio *uio) 657{ 658 659 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 660} 661 662static int 663ugidfw_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 664 struct label *vplabel, u_long flags) 665{ 666 667 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 668} 669 670static int 671ugidfw_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 672 struct label *vplabel, mode_t mode) 673{ 674 675 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 676} 677 678static int 679ugidfw_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 680 struct label *vplabel, uid_t uid, gid_t gid) 681{ 682 683 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 684} 685 686static int 687ugidfw_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 688 struct label *vplabel, struct timespec atime, struct timespec utime) 689{ 690 691 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 692} 693 694static int 695ugidfw_vnode_check_stat(struct ucred *active_cred, 696 struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 697{ 698 699 return (ugidfw_check_vp(active_cred, vp, MBI_STAT)); 700} 701 702static int 703ugidfw_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 704 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 705 struct componentname *cnp) 706{ 707 int error; 708 709 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 710 if (error) 711 return (error); 712 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 713} 714 715static struct mac_policy_ops ugidfw_ops = 716{ 717 .mpo_destroy = ugidfw_destroy, 718 .mpo_init = ugidfw_init, 719 .mpo_system_check_acct = ugidfw_system_check_acct, 720 .mpo_system_check_auditctl = ugidfw_system_check_auditctl, 721 .mpo_system_check_swapon = ugidfw_system_check_swapon, 722 .mpo_vnode_check_access = ugidfw_vnode_check_access, 723 .mpo_vnode_check_chdir = ugidfw_vnode_check_chdir, 724 .mpo_vnode_check_chroot = ugidfw_vnode_check_chroot, 725 .mpo_vnode_check_create = ugidfw_check_create_vnode, 726 .mpo_vnode_check_deleteacl = ugidfw_vnode_check_deleteacl, 727 .mpo_vnode_check_deleteextattr = ugidfw_vnode_check_deleteextattr, 728 .mpo_vnode_check_exec = ugidfw_vnode_check_exec, 729 .mpo_vnode_check_getacl = ugidfw_vnode_check_getacl, 730 .mpo_vnode_check_getextattr = ugidfw_vnode_check_getextattr, 731 .mpo_vnode_check_link = ugidfw_vnode_check_link, 732 .mpo_vnode_check_listextattr = ugidfw_vnode_check_listextattr, 733 .mpo_vnode_check_lookup = ugidfw_vnode_check_lookup, 734 .mpo_vnode_check_open = ugidfw_vnode_check_open, 735 .mpo_vnode_check_readdir = ugidfw_vnode_check_readdir, 736 .mpo_vnode_check_readlink = ugidfw_vnode_check_readdlink, 737 .mpo_vnode_check_rename_from = ugidfw_vnode_check_rename_from, 738 .mpo_vnode_check_rename_to = ugidfw_vnode_check_rename_to, 739 .mpo_vnode_check_revoke = ugidfw_vnode_check_revoke, 740 .mpo_vnode_check_setacl = ugidfw_check_setacl_vnode, 741 .mpo_vnode_check_setextattr = ugidfw_vnode_check_setextattr, 742 .mpo_vnode_check_setflags = ugidfw_vnode_check_setflags, 743 .mpo_vnode_check_setmode = ugidfw_vnode_check_setmode, 744 .mpo_vnode_check_setowner = ugidfw_vnode_check_setowner, 745 .mpo_vnode_check_setutimes = ugidfw_vnode_check_setutimes, 746 .mpo_vnode_check_stat = ugidfw_vnode_check_stat, 747 .mpo_vnode_check_unlink = ugidfw_vnode_check_unlink, 748}; 749 750MAC_POLICY_SET(&ugidfw_ops, mac_bsdextended, "TrustedBSD MAC/BSD Extended",
| 41 */ 42 43/* 44 * Developed by the TrustedBSD Project. 45 * 46 * "BSD Extended" MAC policy, allowing the administrator to impose mandatory 47 * firewall-like rules regarding users and file system objects. 48 */ 49 50#include <sys/param.h> 51#include <sys/acl.h> 52#include <sys/kernel.h> 53#include <sys/jail.h> 54#include <sys/lock.h> 55#include <sys/malloc.h> 56#include <sys/module.h> 57#include <sys/mount.h> 58#include <sys/mutex.h> 59#include <sys/priv.h> 60#include <sys/systm.h> 61#include <sys/vnode.h> 62#include <sys/sysctl.h> 63#include <sys/syslog.h> 64 65#include <security/mac/mac_policy.h> 66#include <security/mac_bsdextended/mac_bsdextended.h> 67 68static struct mtx ugidfw_mtx; 69 70SYSCTL_DECL(_security_mac); 71 72SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 73 "TrustedBSD extended BSD MAC policy controls"); 74 75static int ugidfw_enabled = 1; 76SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 77 &ugidfw_enabled, 0, "Enforce extended BSD policy"); 78TUNABLE_INT("security.mac.bsdextended.enabled", &ugidfw_enabled); 79 80MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 81 82#define MAC_BSDEXTENDED_MAXRULES 250 83static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 84static int rule_count = 0; 85static int rule_slots = 0; 86static int rule_version = MB_VERSION; 87 88SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 89 &rule_count, 0, "Number of defined rules\n"); 90SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 91 &rule_slots, 0, "Number of used rule slots\n"); 92SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 93 &rule_version, 0, "Version number for API\n"); 94 95/* 96 * This is just used for logging purposes, eventually we would like to log 97 * much more then failed requests. 98 */ 99static int ugidfw_logging; 100SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 101 &ugidfw_logging, 0, "Log failed authorization requests"); 102 103/* 104 * This tunable is here for compatibility. It will allow the user to switch 105 * between the new mode (first rule matches) and the old functionality (all 106 * rules match). 107 */ 108static int ugidfw_firstmatch_enabled; 109SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 110 CTLFLAG_RW, &ugidfw_firstmatch_enabled, 1, 111 "Disable/enable match first rule functionality"); 112 113static int 114ugidfw_rule_valid(struct mac_bsdextended_rule *rule) 115{ 116 117 if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 118 return (EINVAL); 119 if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 120 return (EINVAL); 121 if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 122 return (EINVAL); 123 if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 124 return (EINVAL); 125 if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 126 (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 127 return (EINVAL); 128 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 129 return (EINVAL); 130 return (0); 131} 132 133static int 134sysctl_rule(SYSCTL_HANDLER_ARGS) 135{ 136 struct mac_bsdextended_rule temprule, *ruleptr; 137 u_int namelen; 138 int error, index, *name; 139 140 error = 0; 141 name = (int *)arg1; 142 namelen = arg2; 143 if (namelen != 1) 144 return (EINVAL); 145 index = name[0]; 146 if (index >= MAC_BSDEXTENDED_MAXRULES) 147 return (ENOENT); 148 149 ruleptr = NULL; 150 if (req->newptr && req->newlen != 0) { 151 error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 152 if (error) 153 return (error); 154 MALLOC(ruleptr, struct mac_bsdextended_rule *, 155 sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO); 156 } 157 158 mtx_lock(&ugidfw_mtx); 159 if (req->oldptr) { 160 if (index < 0 || index > rule_slots + 1) { 161 error = ENOENT; 162 goto out; 163 } 164 if (rules[index] == NULL) { 165 error = ENOENT; 166 goto out; 167 } 168 temprule = *rules[index]; 169 } 170 if (req->newptr && req->newlen == 0) { 171 KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 172 ruleptr = rules[index]; 173 if (ruleptr == NULL) { 174 error = ENOENT; 175 goto out; 176 } 177 rule_count--; 178 rules[index] = NULL; 179 } else if (req->newptr) { 180 error = ugidfw_rule_valid(&temprule); 181 if (error) 182 goto out; 183 if (rules[index] == NULL) { 184 *ruleptr = temprule; 185 rules[index] = ruleptr; 186 ruleptr = NULL; 187 if (index + 1 > rule_slots) 188 rule_slots = index + 1; 189 rule_count++; 190 } else 191 *rules[index] = temprule; 192 } 193out: 194 mtx_unlock(&ugidfw_mtx); 195 if (ruleptr != NULL) 196 FREE(ruleptr, M_MACBSDEXTENDED); 197 if (req->oldptr && error == 0) 198 error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 199 return (error); 200} 201 202SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW, 203 sysctl_rule, "BSD extended MAC rules"); 204 205static void 206ugidfw_init(struct mac_policy_conf *mpc) 207{ 208 209 mtx_init(&ugidfw_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 210} 211 212static void 213ugidfw_destroy(struct mac_policy_conf *mpc) 214{ 215 216 mtx_destroy(&ugidfw_mtx); 217} 218 219static int 220ugidfw_rulecheck(struct mac_bsdextended_rule *rule, 221 struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 222{ 223 int match; 224 int i; 225 226 /* 227 * Is there a subject match? 228 */ 229 mtx_assert(&ugidfw_mtx, MA_OWNED); 230 if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 231 match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 232 cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 233 (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 234 cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 235 (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 236 cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 237 if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 238 match = !match; 239 if (!match) 240 return (0); 241 } 242 243 if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 244 match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 245 cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 246 (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 247 cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 248 if (!match) { 249 for (i = 0; i < cred->cr_ngroups; i++) { 250 if (cred->cr_groups[i] 251 <= rule->mbr_subject.mbs_gid_max && 252 cred->cr_groups[i] 253 >= rule->mbr_subject.mbs_gid_min) { 254 match = 1; 255 break; 256 } 257 } 258 } 259 if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 260 match = !match; 261 if (!match) 262 return (0); 263 } 264 265 if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 266 match = (cred->cr_prison != NULL && 267 cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 268 if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 269 match = !match; 270 if (!match) 271 return (0); 272 } 273 274 /* 275 * Is there an object match? 276 */ 277 if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 278 match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 279 vap->va_uid >= rule->mbr_object.mbo_uid_min); 280 if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 281 match = !match; 282 if (!match) 283 return (0); 284 } 285 286 if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 287 match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 288 vap->va_gid >= rule->mbr_object.mbo_gid_min); 289 if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 290 match = !match; 291 if (!match) 292 return (0); 293 } 294 295 if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 296 match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 297 &(rule->mbr_object.mbo_fsid), 298 sizeof(rule->mbr_object.mbo_fsid)) == 0); 299 if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 300 match = !match; 301 if (!match) 302 return (0); 303 } 304 305 if (rule->mbr_object.mbo_flags & MBO_SUID) { 306 match = (vap->va_mode & VSUID); 307 if (rule->mbr_object.mbo_neg & MBO_SUID) 308 match = !match; 309 if (!match) 310 return (0); 311 } 312 313 if (rule->mbr_object.mbo_flags & MBO_SGID) { 314 match = (vap->va_mode & VSGID); 315 if (rule->mbr_object.mbo_neg & MBO_SGID) 316 match = !match; 317 if (!match) 318 return (0); 319 } 320 321 if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 322 match = (vap->va_uid == cred->cr_uid || 323 vap->va_uid == cred->cr_ruid || 324 vap->va_uid == cred->cr_svuid); 325 if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 326 match = !match; 327 if (!match) 328 return (0); 329 } 330 331 if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 332 match = (groupmember(vap->va_gid, cred) || 333 vap->va_gid == cred->cr_rgid || 334 vap->va_gid == cred->cr_svgid); 335 if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 336 match = !match; 337 if (!match) 338 return (0); 339 } 340 341 if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 342 switch (vap->va_type) { 343 case VREG: 344 match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 345 break; 346 case VDIR: 347 match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 348 break; 349 case VBLK: 350 match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 351 break; 352 case VCHR: 353 match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 354 break; 355 case VLNK: 356 match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 357 break; 358 case VSOCK: 359 match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 360 break; 361 case VFIFO: 362 match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 363 break; 364 default: 365 match = 0; 366 } 367 if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 368 match = !match; 369 if (!match) 370 return (0); 371 } 372 373 /* 374 * Is the access permitted? 375 */ 376 if ((rule->mbr_mode & acc_mode) != acc_mode) { 377 if (ugidfw_logging) 378 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 379 " on %d:%d failed. \n", cred->cr_ruid, 380 cred->cr_rgid, acc_mode, vap->va_uid, 381 vap->va_gid); 382 return (EACCES); 383 } 384 385 /* 386 * If the rule matched, permits access, and first match is enabled, 387 * return success. 388 */ 389 if (ugidfw_firstmatch_enabled) 390 return (EJUSTRETURN); 391 else 392 return (0); 393} 394 395static int 396ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 397 int acc_mode) 398{ 399 int error, i; 400 401 /* 402 * XXXRW: More specific privilege selection needed. 403 */ 404 if (suser_cred(cred, 0) == 0) 405 return (0); 406 407 /* 408 * Since we do not separately handle append, map append to write. 409 */ 410 if (acc_mode & MBI_APPEND) { 411 acc_mode &= ~MBI_APPEND; 412 acc_mode |= MBI_WRITE; 413 } 414 mtx_lock(&ugidfw_mtx); 415 for (i = 0; i < rule_slots; i++) { 416 if (rules[i] == NULL) 417 continue; 418 error = ugidfw_rulecheck(rules[i], cred, 419 vp, vap, acc_mode); 420 if (error == EJUSTRETURN) 421 break; 422 if (error) { 423 mtx_unlock(&ugidfw_mtx); 424 return (error); 425 } 426 } 427 mtx_unlock(&ugidfw_mtx); 428 return (0); 429} 430 431static int 432ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 433{ 434 int error; 435 struct vattr vap; 436 437 if (!ugidfw_enabled) 438 return (0); 439 error = VOP_GETATTR(vp, &vap, cred, curthread); 440 if (error) 441 return (error); 442 return (ugidfw_check(cred, vp, &vap, acc_mode)); 443} 444 445/* 446 * Object-specific entry point implementations are sorted alphabetically by 447 * object type and then by operation. 448 */ 449static int 450ugidfw_system_check_acct(struct ucred *cred, struct vnode *vp, 451 struct label *vplabel) 452{ 453 454 if (vp != NULL) 455 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 456 else 457 return (0); 458} 459 460static int 461ugidfw_system_check_auditctl(struct ucred *cred, struct vnode *vp, 462 struct label *vplabel) 463{ 464 465 if (vp != NULL) 466 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 467 else 468 return (0); 469} 470 471static int 472ugidfw_system_check_swapon(struct ucred *cred, struct vnode *vp, 473 struct label *vplabel) 474{ 475 476 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 477} 478 479static int 480ugidfw_vnode_check_access(struct ucred *cred, struct vnode *vp, 481 struct label *vplabel, int acc_mode) 482{ 483 484 return (ugidfw_check_vp(cred, vp, acc_mode)); 485} 486 487static int 488ugidfw_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, 489 struct label *dvplabel) 490{ 491 492 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 493} 494 495static int 496ugidfw_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, 497 struct label *dvplabel) 498{ 499 500 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 501} 502 503static int 504ugidfw_check_create_vnode(struct ucred *cred, struct vnode *dvp, 505 struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 506{ 507 508 return (ugidfw_check_vp(cred, dvp, MBI_WRITE)); 509} 510 511static int 512ugidfw_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 513 struct label *vplabel, acl_type_t type) 514{ 515 516 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 517} 518 519static int 520ugidfw_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 521 struct label *vplabel, int attrnamespace, const char *name) 522{ 523 524 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 525} 526 527static int 528ugidfw_vnode_check_exec(struct ucred *cred, struct vnode *vp, 529 struct label *vplabel, struct image_params *imgp, 530 struct label *execlabel) 531{ 532 533 return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 534} 535 536static int 537ugidfw_vnode_check_getacl(struct ucred *cred, struct vnode *vp, 538 struct label *vplabel, acl_type_t type) 539{ 540 541 return (ugidfw_check_vp(cred, vp, MBI_STAT)); 542} 543 544static int 545ugidfw_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 546 struct label *vplabel, int attrnamespace, const char *name, 547 struct uio *uio) 548{ 549 550 return (ugidfw_check_vp(cred, vp, MBI_READ)); 551} 552 553static int 554ugidfw_vnode_check_link(struct ucred *cred, struct vnode *dvp, 555 struct label *dvplabel, struct vnode *vp, struct label *label, 556 struct componentname *cnp) 557{ 558 int error; 559 560 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 561 if (error) 562 return (error); 563 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 564 if (error) 565 return (error); 566 return (0); 567} 568 569static int 570ugidfw_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 571 struct label *vplabel, int attrnamespace) 572{ 573 574 return (ugidfw_check_vp(cred, vp, MBI_READ)); 575} 576 577static int 578ugidfw_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, 579 struct label *dvplabel, struct componentname *cnp) 580{ 581 582 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 583} 584 585static int 586ugidfw_vnode_check_open(struct ucred *cred, struct vnode *vp, 587 struct label *vplabel, int acc_mode) 588{ 589 590 return (ugidfw_check_vp(cred, vp, acc_mode)); 591} 592 593static int 594ugidfw_vnode_check_readdir(struct ucred *cred, struct vnode *dvp, 595 struct label *dvplabel) 596{ 597 598 return (ugidfw_check_vp(cred, dvp, MBI_READ)); 599} 600 601static int 602ugidfw_vnode_check_readdlink(struct ucred *cred, struct vnode *vp, 603 struct label *vplabel) 604{ 605 606 return (ugidfw_check_vp(cred, vp, MBI_READ)); 607} 608 609static int 610ugidfw_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 611 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 612 struct componentname *cnp) 613{ 614 int error; 615 616 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 617 if (error) 618 return (error); 619 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 620} 621 622static int 623ugidfw_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 624 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 625 int samedir, struct componentname *cnp) 626{ 627 int error; 628 629 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 630 if (error) 631 return (error); 632 if (vp != NULL) 633 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 634 return (error); 635} 636 637static int 638ugidfw_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 639 struct label *vplabel) 640{ 641 642 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 643} 644 645static int 646ugidfw_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 647 struct label *vplabel, acl_type_t type, struct acl *acl) 648{ 649 650 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 651} 652 653static int 654ugidfw_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 655 struct label *vplabel, int attrnamespace, const char *name, 656 struct uio *uio) 657{ 658 659 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 660} 661 662static int 663ugidfw_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 664 struct label *vplabel, u_long flags) 665{ 666 667 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 668} 669 670static int 671ugidfw_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 672 struct label *vplabel, mode_t mode) 673{ 674 675 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 676} 677 678static int 679ugidfw_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 680 struct label *vplabel, uid_t uid, gid_t gid) 681{ 682 683 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 684} 685 686static int 687ugidfw_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 688 struct label *vplabel, struct timespec atime, struct timespec utime) 689{ 690 691 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 692} 693 694static int 695ugidfw_vnode_check_stat(struct ucred *active_cred, 696 struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 697{ 698 699 return (ugidfw_check_vp(active_cred, vp, MBI_STAT)); 700} 701 702static int 703ugidfw_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 704 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 705 struct componentname *cnp) 706{ 707 int error; 708 709 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 710 if (error) 711 return (error); 712 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 713} 714 715static struct mac_policy_ops ugidfw_ops = 716{ 717 .mpo_destroy = ugidfw_destroy, 718 .mpo_init = ugidfw_init, 719 .mpo_system_check_acct = ugidfw_system_check_acct, 720 .mpo_system_check_auditctl = ugidfw_system_check_auditctl, 721 .mpo_system_check_swapon = ugidfw_system_check_swapon, 722 .mpo_vnode_check_access = ugidfw_vnode_check_access, 723 .mpo_vnode_check_chdir = ugidfw_vnode_check_chdir, 724 .mpo_vnode_check_chroot = ugidfw_vnode_check_chroot, 725 .mpo_vnode_check_create = ugidfw_check_create_vnode, 726 .mpo_vnode_check_deleteacl = ugidfw_vnode_check_deleteacl, 727 .mpo_vnode_check_deleteextattr = ugidfw_vnode_check_deleteextattr, 728 .mpo_vnode_check_exec = ugidfw_vnode_check_exec, 729 .mpo_vnode_check_getacl = ugidfw_vnode_check_getacl, 730 .mpo_vnode_check_getextattr = ugidfw_vnode_check_getextattr, 731 .mpo_vnode_check_link = ugidfw_vnode_check_link, 732 .mpo_vnode_check_listextattr = ugidfw_vnode_check_listextattr, 733 .mpo_vnode_check_lookup = ugidfw_vnode_check_lookup, 734 .mpo_vnode_check_open = ugidfw_vnode_check_open, 735 .mpo_vnode_check_readdir = ugidfw_vnode_check_readdir, 736 .mpo_vnode_check_readlink = ugidfw_vnode_check_readdlink, 737 .mpo_vnode_check_rename_from = ugidfw_vnode_check_rename_from, 738 .mpo_vnode_check_rename_to = ugidfw_vnode_check_rename_to, 739 .mpo_vnode_check_revoke = ugidfw_vnode_check_revoke, 740 .mpo_vnode_check_setacl = ugidfw_check_setacl_vnode, 741 .mpo_vnode_check_setextattr = ugidfw_vnode_check_setextattr, 742 .mpo_vnode_check_setflags = ugidfw_vnode_check_setflags, 743 .mpo_vnode_check_setmode = ugidfw_vnode_check_setmode, 744 .mpo_vnode_check_setowner = ugidfw_vnode_check_setowner, 745 .mpo_vnode_check_setutimes = ugidfw_vnode_check_setutimes, 746 .mpo_vnode_check_stat = ugidfw_vnode_check_stat, 747 .mpo_vnode_check_unlink = ugidfw_vnode_check_unlink, 748}; 749 750MAC_POLICY_SET(&ugidfw_ops, mac_bsdextended, "TrustedBSD MAC/BSD Extended",
|