ugidfw_system.c revision 184214
1/*- 2 * Copyright (c) 1999-2002, 2007 Robert N. M. Watson 3 * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 4 * Copyright (c) 2005 Tom Rhodes 5 * Copyright (c) 2006 SPARTA, Inc. 6 * All rights reserved. 7 * 8 * This software was developed by Robert Watson for the TrustedBSD Project. 9 * It was later enhanced by Tom Rhodes for the TrustedBSD Project. 10 * 11 * This software was developed for the FreeBSD Project in part by Network 12 * Associates Laboratories, the Security Research Division of Network 13 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 14 * as part of the DARPA CHATS research program. 15 * 16 * This software was enhanced by SPARTA ISSO under SPAWAR contract 17 * N66001-04-C-6019 ("SEFOS"). 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 184214 2008-10-23 20:26:15Z des $ 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#include <sys/stat.h> 65 66#include <security/mac/mac_policy.h> 67#include <security/mac_bsdextended/mac_bsdextended.h> 68 69static struct mtx ugidfw_mtx; 70 71SYSCTL_DECL(_security_mac); 72 73SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 74 "TrustedBSD extended BSD MAC policy controls"); 75 76static int ugidfw_enabled = 1; 77SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 78 &ugidfw_enabled, 0, "Enforce extended BSD policy"); 79TUNABLE_INT("security.mac.bsdextended.enabled", &ugidfw_enabled); 80 81MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 82 83#define MAC_BSDEXTENDED_MAXRULES 250 84static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 85static int rule_count = 0; 86static int rule_slots = 0; 87static int rule_version = MB_VERSION; 88 89SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 90 &rule_count, 0, "Number of defined rules\n"); 91SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 92 &rule_slots, 0, "Number of used rule slots\n"); 93SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 94 &rule_version, 0, "Version number for API\n"); 95 96/* 97 * This is just used for logging purposes, eventually we would like to log 98 * much more then failed requests. 99 */ 100static int ugidfw_logging; 101SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 102 &ugidfw_logging, 0, "Log failed authorization requests"); 103 104/* 105 * This tunable is here for compatibility. It will allow the user to switch 106 * between the new mode (first rule matches) and the old functionality (all 107 * rules match). 108 */ 109static int ugidfw_firstmatch_enabled; 110SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 111 CTLFLAG_RW, &ugidfw_firstmatch_enabled, 1, 112 "Disable/enable match first rule functionality"); 113 114static int 115ugidfw_rule_valid(struct mac_bsdextended_rule *rule) 116{ 117 118 if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 119 return (EINVAL); 120 if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 121 return (EINVAL); 122 if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 123 return (EINVAL); 124 if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 125 return (EINVAL); 126 if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 127 (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 128 return (EINVAL); 129 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 130 return (EINVAL); 131 return (0); 132} 133 134static int 135sysctl_rule(SYSCTL_HANDLER_ARGS) 136{ 137 struct mac_bsdextended_rule temprule, *ruleptr; 138 u_int namelen; 139 int error, index, *name; 140 141 error = 0; 142 name = (int *)arg1; 143 namelen = arg2; 144 if (namelen != 1) 145 return (EINVAL); 146 index = name[0]; 147 if (index >= MAC_BSDEXTENDED_MAXRULES) 148 return (ENOENT); 149 150 ruleptr = NULL; 151 if (req->newptr && req->newlen != 0) { 152 error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 153 if (error) 154 return (error); 155 ruleptr = malloc(sizeof(*ruleptr), M_MACBSDEXTENDED, 156 M_WAITOK | M_ZERO); 157 } 158 159 mtx_lock(&ugidfw_mtx); 160 if (req->oldptr) { 161 if (index < 0 || index > rule_slots + 1) { 162 error = ENOENT; 163 goto out; 164 } 165 if (rules[index] == NULL) { 166 error = ENOENT; 167 goto out; 168 } 169 temprule = *rules[index]; 170 } 171 if (req->newptr && req->newlen == 0) { 172 KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 173 ruleptr = rules[index]; 174 if (ruleptr == NULL) { 175 error = ENOENT; 176 goto out; 177 } 178 rule_count--; 179 rules[index] = NULL; 180 } else if (req->newptr) { 181 error = ugidfw_rule_valid(&temprule); 182 if (error) 183 goto out; 184 if (rules[index] == NULL) { 185 *ruleptr = temprule; 186 rules[index] = ruleptr; 187 ruleptr = NULL; 188 if (index + 1 > rule_slots) 189 rule_slots = index + 1; 190 rule_count++; 191 } else 192 *rules[index] = temprule; 193 } 194out: 195 mtx_unlock(&ugidfw_mtx); 196 if (ruleptr != NULL) 197 free(ruleptr, M_MACBSDEXTENDED); 198 if (req->oldptr && error == 0) 199 error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 200 return (error); 201} 202 203SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW, 204 sysctl_rule, "BSD extended MAC rules"); 205 206static void 207ugidfw_init(struct mac_policy_conf *mpc) 208{ 209 210 mtx_init(&ugidfw_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 211} 212 213static void 214ugidfw_destroy(struct mac_policy_conf *mpc) 215{ 216 217 mtx_destroy(&ugidfw_mtx); 218} 219 220static int 221ugidfw_rulecheck(struct mac_bsdextended_rule *rule, 222 struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 223{ 224 int mac_granted, match, priv_granted; 225 int i; 226 227 /* 228 * Is there a subject match? 229 */ 230 mtx_assert(&ugidfw_mtx, MA_OWNED); 231 if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 232 match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 233 cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 234 (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 235 cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 236 (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 237 cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 238 if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 239 match = !match; 240 if (!match) 241 return (0); 242 } 243 244 if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 245 match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 246 cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 247 (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 248 cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 249 if (!match) { 250 for (i = 0; i < cred->cr_ngroups; i++) { 251 if (cred->cr_groups[i] 252 <= rule->mbr_subject.mbs_gid_max && 253 cred->cr_groups[i] 254 >= rule->mbr_subject.mbs_gid_min) { 255 match = 1; 256 break; 257 } 258 } 259 } 260 if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 261 match = !match; 262 if (!match) 263 return (0); 264 } 265 266 if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 267 match = (cred->cr_prison != NULL && 268 cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 269 if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 270 match = !match; 271 if (!match) 272 return (0); 273 } 274 275 /* 276 * Is there an object match? 277 */ 278 if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 279 match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 280 vap->va_uid >= rule->mbr_object.mbo_uid_min); 281 if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 282 match = !match; 283 if (!match) 284 return (0); 285 } 286 287 if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 288 match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 289 vap->va_gid >= rule->mbr_object.mbo_gid_min); 290 if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 291 match = !match; 292 if (!match) 293 return (0); 294 } 295 296 if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 297 match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 298 &(rule->mbr_object.mbo_fsid), 299 sizeof(rule->mbr_object.mbo_fsid)) == 0); 300 if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 301 match = !match; 302 if (!match) 303 return (0); 304 } 305 306 if (rule->mbr_object.mbo_flags & MBO_SUID) { 307 match = (vap->va_mode & S_ISUID); 308 if (rule->mbr_object.mbo_neg & MBO_SUID) 309 match = !match; 310 if (!match) 311 return (0); 312 } 313 314 if (rule->mbr_object.mbo_flags & MBO_SGID) { 315 match = (vap->va_mode & S_ISGID); 316 if (rule->mbr_object.mbo_neg & MBO_SGID) 317 match = !match; 318 if (!match) 319 return (0); 320 } 321 322 if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 323 match = (vap->va_uid == cred->cr_uid || 324 vap->va_uid == cred->cr_ruid || 325 vap->va_uid == cred->cr_svuid); 326 if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 327 match = !match; 328 if (!match) 329 return (0); 330 } 331 332 if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 333 match = (groupmember(vap->va_gid, cred) || 334 vap->va_gid == cred->cr_rgid || 335 vap->va_gid == cred->cr_svgid); 336 if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 337 match = !match; 338 if (!match) 339 return (0); 340 } 341 342 if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 343 switch (vap->va_type) { 344 case VREG: 345 match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 346 break; 347 case VDIR: 348 match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 349 break; 350 case VBLK: 351 match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 352 break; 353 case VCHR: 354 match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 355 break; 356 case VLNK: 357 match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 358 break; 359 case VSOCK: 360 match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 361 break; 362 case VFIFO: 363 match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 364 break; 365 default: 366 match = 0; 367 } 368 if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 369 match = !match; 370 if (!match) 371 return (0); 372 } 373 374 /* 375 * MBI_APPEND should not be here as it should get converted to 376 * MBI_WRITE. 377 */ 378 priv_granted = 0; 379 mac_granted = rule->mbr_mode; 380 if ((acc_mode & MBI_ADMIN) && (mac_granted & MBI_ADMIN) == 0 && 381 priv_check_cred(cred, PRIV_VFS_ADMIN, 0) == 0) 382 priv_granted |= MBI_ADMIN; 383 if ((acc_mode & MBI_EXEC) && (mac_granted & MBI_EXEC) == 0 && 384 priv_check_cred(cred, (vap->va_type == VDIR) ? PRIV_VFS_LOOKUP : 385 PRIV_VFS_EXEC, 0) == 0) 386 priv_granted |= MBI_EXEC; 387 if ((acc_mode & MBI_READ) && (mac_granted & MBI_READ) == 0 && 388 priv_check_cred(cred, PRIV_VFS_READ, 0) == 0) 389 priv_granted |= MBI_READ; 390 if ((acc_mode & MBI_STAT) && (mac_granted & MBI_STAT) == 0 && 391 priv_check_cred(cred, PRIV_VFS_STAT, 0) == 0) 392 priv_granted |= MBI_STAT; 393 if ((acc_mode & MBI_WRITE) && (mac_granted & MBI_WRITE) == 0 && 394 priv_check_cred(cred, PRIV_VFS_WRITE, 0) == 0) 395 priv_granted |= MBI_WRITE; 396 /* 397 * Is the access permitted? 398 */ 399 if (((mac_granted | priv_granted) & acc_mode) != acc_mode) { 400 if (ugidfw_logging) 401 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 402 " on %d:%d failed. \n", cred->cr_ruid, 403 cred->cr_rgid, acc_mode, vap->va_uid, 404 vap->va_gid); 405 return (EACCES); 406 } 407 408 /* 409 * If the rule matched, permits access, and first match is enabled, 410 * return success. 411 */ 412 if (ugidfw_firstmatch_enabled) 413 return (EJUSTRETURN); 414 else 415 return (0); 416} 417 418static int 419ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 420 int acc_mode) 421{ 422 int error, i; 423 424 /* 425 * Since we do not separately handle append, map append to write. 426 */ 427 if (acc_mode & MBI_APPEND) { 428 acc_mode &= ~MBI_APPEND; 429 acc_mode |= MBI_WRITE; 430 } 431 mtx_lock(&ugidfw_mtx); 432 for (i = 0; i < rule_slots; i++) { 433 if (rules[i] == NULL) 434 continue; 435 error = ugidfw_rulecheck(rules[i], cred, 436 vp, vap, acc_mode); 437 if (error == EJUSTRETURN) 438 break; 439 if (error) { 440 mtx_unlock(&ugidfw_mtx); 441 return (error); 442 } 443 } 444 mtx_unlock(&ugidfw_mtx); 445 return (0); 446} 447 448static int 449ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 450{ 451 int error; 452 struct vattr vap; 453 454 if (!ugidfw_enabled) 455 return (0); 456 error = VOP_GETATTR(vp, &vap, cred); 457 if (error) 458 return (error); 459 return (ugidfw_check(cred, vp, &vap, acc_mode)); 460} 461 462/* 463 * Object-specific entry point implementations are sorted alphabetically by 464 * object type and then by operation. 465 */ 466static int 467ugidfw_system_check_acct(struct ucred *cred, struct vnode *vp, 468 struct label *vplabel) 469{ 470 471 if (vp != NULL) 472 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 473 else 474 return (0); 475} 476 477static int 478ugidfw_system_check_auditctl(struct ucred *cred, struct vnode *vp, 479 struct label *vplabel) 480{ 481 482 if (vp != NULL) 483 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 484 else 485 return (0); 486} 487 488static int 489ugidfw_system_check_swapon(struct ucred *cred, struct vnode *vp, 490 struct label *vplabel) 491{ 492 493 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 494} 495 496static int 497ugidfw_vnode_check_access(struct ucred *cred, struct vnode *vp, 498 struct label *vplabel, int acc_mode) 499{ 500 501 return (ugidfw_check_vp(cred, vp, acc_mode)); 502} 503 504static int 505ugidfw_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, 506 struct label *dvplabel) 507{ 508 509 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 510} 511 512static int 513ugidfw_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, 514 struct label *dvplabel) 515{ 516 517 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 518} 519 520static int 521ugidfw_check_create_vnode(struct ucred *cred, struct vnode *dvp, 522 struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 523{ 524 525 return (ugidfw_check_vp(cred, dvp, MBI_WRITE)); 526} 527 528static int 529ugidfw_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 530 struct label *vplabel, acl_type_t type) 531{ 532 533 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 534} 535 536static int 537ugidfw_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 538 struct label *vplabel, int attrnamespace, const char *name) 539{ 540 541 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 542} 543 544static int 545ugidfw_vnode_check_exec(struct ucred *cred, struct vnode *vp, 546 struct label *vplabel, struct image_params *imgp, 547 struct label *execlabel) 548{ 549 550 return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 551} 552 553static int 554ugidfw_vnode_check_getacl(struct ucred *cred, struct vnode *vp, 555 struct label *vplabel, acl_type_t type) 556{ 557 558 return (ugidfw_check_vp(cred, vp, MBI_STAT)); 559} 560 561static int 562ugidfw_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 563 struct label *vplabel, int attrnamespace, const char *name, 564 struct uio *uio) 565{ 566 567 return (ugidfw_check_vp(cred, vp, MBI_READ)); 568} 569 570static int 571ugidfw_vnode_check_link(struct ucred *cred, struct vnode *dvp, 572 struct label *dvplabel, struct vnode *vp, struct label *label, 573 struct componentname *cnp) 574{ 575 int error; 576 577 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 578 if (error) 579 return (error); 580 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 581 if (error) 582 return (error); 583 return (0); 584} 585 586static int 587ugidfw_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 588 struct label *vplabel, int attrnamespace) 589{ 590 591 return (ugidfw_check_vp(cred, vp, MBI_READ)); 592} 593 594static int 595ugidfw_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, 596 struct label *dvplabel, struct componentname *cnp) 597{ 598 599 return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 600} 601 602static int 603ugidfw_vnode_check_open(struct ucred *cred, struct vnode *vp, 604 struct label *vplabel, int acc_mode) 605{ 606 607 return (ugidfw_check_vp(cred, vp, acc_mode)); 608} 609 610static int 611ugidfw_vnode_check_readdir(struct ucred *cred, struct vnode *dvp, 612 struct label *dvplabel) 613{ 614 615 return (ugidfw_check_vp(cred, dvp, MBI_READ)); 616} 617 618static int 619ugidfw_vnode_check_readdlink(struct ucred *cred, struct vnode *vp, 620 struct label *vplabel) 621{ 622 623 return (ugidfw_check_vp(cred, vp, MBI_READ)); 624} 625 626static int 627ugidfw_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 628 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 629 struct componentname *cnp) 630{ 631 int error; 632 633 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 634 if (error) 635 return (error); 636 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 637} 638 639static int 640ugidfw_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 641 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 642 int samedir, struct componentname *cnp) 643{ 644 int error; 645 646 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 647 if (error) 648 return (error); 649 if (vp != NULL) 650 error = ugidfw_check_vp(cred, vp, MBI_WRITE); 651 return (error); 652} 653 654static int 655ugidfw_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 656 struct label *vplabel) 657{ 658 659 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 660} 661 662static int 663ugidfw_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 664 struct label *vplabel, acl_type_t type, struct acl *acl) 665{ 666 667 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 668} 669 670static int 671ugidfw_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 672 struct label *vplabel, int attrnamespace, const char *name, 673 struct uio *uio) 674{ 675 676 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 677} 678 679static int 680ugidfw_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 681 struct label *vplabel, u_long flags) 682{ 683 684 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 685} 686 687static int 688ugidfw_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 689 struct label *vplabel, mode_t mode) 690{ 691 692 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 693} 694 695static int 696ugidfw_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 697 struct label *vplabel, uid_t uid, gid_t gid) 698{ 699 700 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 701} 702 703static int 704ugidfw_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 705 struct label *vplabel, struct timespec atime, struct timespec utime) 706{ 707 708 return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 709} 710 711static int 712ugidfw_vnode_check_stat(struct ucred *active_cred, 713 struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 714{ 715 716 return (ugidfw_check_vp(active_cred, vp, MBI_STAT)); 717} 718 719static int 720ugidfw_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 721 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 722 struct componentname *cnp) 723{ 724 int error; 725 726 error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 727 if (error) 728 return (error); 729 return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 730} 731 732static struct mac_policy_ops ugidfw_ops = 733{ 734 .mpo_destroy = ugidfw_destroy, 735 .mpo_init = ugidfw_init, 736 .mpo_system_check_acct = ugidfw_system_check_acct, 737 .mpo_system_check_auditctl = ugidfw_system_check_auditctl, 738 .mpo_system_check_swapon = ugidfw_system_check_swapon, 739 .mpo_vnode_check_access = ugidfw_vnode_check_access, 740 .mpo_vnode_check_chdir = ugidfw_vnode_check_chdir, 741 .mpo_vnode_check_chroot = ugidfw_vnode_check_chroot, 742 .mpo_vnode_check_create = ugidfw_check_create_vnode, 743 .mpo_vnode_check_deleteacl = ugidfw_vnode_check_deleteacl, 744 .mpo_vnode_check_deleteextattr = ugidfw_vnode_check_deleteextattr, 745 .mpo_vnode_check_exec = ugidfw_vnode_check_exec, 746 .mpo_vnode_check_getacl = ugidfw_vnode_check_getacl, 747 .mpo_vnode_check_getextattr = ugidfw_vnode_check_getextattr, 748 .mpo_vnode_check_link = ugidfw_vnode_check_link, 749 .mpo_vnode_check_listextattr = ugidfw_vnode_check_listextattr, 750 .mpo_vnode_check_lookup = ugidfw_vnode_check_lookup, 751 .mpo_vnode_check_open = ugidfw_vnode_check_open, 752 .mpo_vnode_check_readdir = ugidfw_vnode_check_readdir, 753 .mpo_vnode_check_readlink = ugidfw_vnode_check_readdlink, 754 .mpo_vnode_check_rename_from = ugidfw_vnode_check_rename_from, 755 .mpo_vnode_check_rename_to = ugidfw_vnode_check_rename_to, 756 .mpo_vnode_check_revoke = ugidfw_vnode_check_revoke, 757 .mpo_vnode_check_setacl = ugidfw_check_setacl_vnode, 758 .mpo_vnode_check_setextattr = ugidfw_vnode_check_setextattr, 759 .mpo_vnode_check_setflags = ugidfw_vnode_check_setflags, 760 .mpo_vnode_check_setmode = ugidfw_vnode_check_setmode, 761 .mpo_vnode_check_setowner = ugidfw_vnode_check_setowner, 762 .mpo_vnode_check_setutimes = ugidfw_vnode_check_setutimes, 763 .mpo_vnode_check_stat = ugidfw_vnode_check_stat, 764 .mpo_vnode_check_unlink = ugidfw_vnode_check_unlink, 765}; 766 767MAC_POLICY_SET(&ugidfw_ops, mac_bsdextended, "TrustedBSD MAC/BSD Extended", 768 MPC_LOADTIME_FLAG_UNLOADOK, NULL, 0); 769