ugidfw_vnode.c revision 166905
1101099Srwatson/*- 2145412Strhodes * Copyright (c) 2005 Tom Rhodes 3166905Srwatson * Copyright (c) 1999-2002, 2007 Robert N. M. Watson 4145412Strhodes * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5101099Srwatson * All rights reserved. 6101099Srwatson * 7101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project. 8145412Strhodes * It was later enhanced by Tom Rhodes for the TrustedBSD Project. 9101099Srwatson * 10106393Srwatson * This software was developed for the FreeBSD Project in part by Network 11106393Srwatson * Associates Laboratories, the Security Research Division of Network 12106393Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13106393Srwatson * as part of the DARPA CHATS research program. 14101099Srwatson * 15101099Srwatson * Redistribution and use in source and binary forms, with or without 16101099Srwatson * modification, are permitted provided that the following conditions 17101099Srwatson * are met: 18101099Srwatson * 1. Redistributions of source code must retain the above copyright 19101099Srwatson * notice, this list of conditions and the following disclaimer. 20101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright 21101099Srwatson * notice, this list of conditions and the following disclaimer in the 22101099Srwatson * documentation and/or other materials provided with the distribution. 23101099Srwatson * 24101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27101099Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34101099Srwatson * SUCH DAMAGE. 35101099Srwatson * 36101099Srwatson * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 166905 2007-02-23 14:39:04Z rwatson $ 37101099Srwatson */ 38136774Srwatson 39101099Srwatson/* 40101099Srwatson * Developed by the TrustedBSD Project. 41101099Srwatson * "BSD Extended" MAC policy, allowing the administrator to impose 42101099Srwatson * mandatory rules regarding users and some system objects. 43101099Srwatson */ 44101099Srwatson 45101099Srwatson#include <sys/param.h> 46101099Srwatson#include <sys/acl.h> 47101099Srwatson#include <sys/kernel.h> 48157986Sdwmalone#include <sys/jail.h> 49145412Strhodes#include <sys/lock.h> 50101099Srwatson#include <sys/malloc.h> 51166905Srwatson#include <sys/module.h> 52101099Srwatson#include <sys/mount.h> 53145412Strhodes#include <sys/mutex.h> 54101099Srwatson#include <sys/systm.h> 55101099Srwatson#include <sys/vnode.h> 56101099Srwatson#include <sys/sysctl.h> 57134132Strhodes#include <sys/syslog.h> 58101099Srwatson 59165469Srwatson#include <security/mac/mac_policy.h> 60101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h> 61101099Srwatson 62145412Strhodesstatic struct mtx mac_bsdextended_mtx; 63145412Strhodes 64101099SrwatsonSYSCTL_DECL(_security_mac); 65101099Srwatson 66101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 67101099Srwatson "TrustedBSD extended BSD MAC policy controls"); 68101099Srwatson 69101099Srwatsonstatic int mac_bsdextended_enabled = 1; 70101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 71101099Srwatson &mac_bsdextended_enabled, 0, "Enforce extended BSD policy"); 72101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled); 73101099Srwatson 74101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 75101099Srwatson 76101099Srwatson#define MAC_BSDEXTENDED_MAXRULES 250 77101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 78101099Srwatsonstatic int rule_count = 0; 79101099Srwatsonstatic int rule_slots = 0; 80157986Sdwmalonestatic int rule_version = MB_VERSION; 81101099Srwatson 82101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 83101099Srwatson &rule_count, 0, "Number of defined rules\n"); 84101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 85101099Srwatson &rule_slots, 0, "Number of used rule slots\n"); 86157986SdwmaloneSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 87157986Sdwmalone &rule_version, 0, "Version number for API\n"); 88101099Srwatson 89134132Strhodes/* 90145412Strhodes * This is just used for logging purposes, eventually we would like 91134132Strhodes * to log much more then failed requests. 92134132Strhodes */ 93134132Strhodesstatic int mac_bsdextended_logging; 94134132StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 95134132Strhodes &mac_bsdextended_logging, 0, "Log failed authorization requests"); 96134132Strhodes 97134132Strhodes/* 98134131Strhodes * This tunable is here for compatibility. It will allow the user 99134131Strhodes * to switch between the new mode (first rule matches) and the old 100134131Strhodes * functionality (all rules match). 101134131Strhodes */ 102101099Srwatsonstatic int 103134131Strhodesmac_bsdextended_firstmatch_enabled; 104134131StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 105135039Strhodes CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1, 106134131Strhodes "Disable/enable match first rule functionality"); 107134131Strhodes 108134131Strhodesstatic int 109101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule) 110101099Srwatson{ 111101099Srwatson 112157986Sdwmalone if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 113101099Srwatson return (EINVAL); 114101099Srwatson 115157986Sdwmalone if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 116101099Srwatson return (EINVAL); 117101099Srwatson 118157986Sdwmalone if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 119157986Sdwmalone return (EINVAL); 120157986Sdwmalone 121157986Sdwmalone if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 122157986Sdwmalone return (EINVAL); 123157986Sdwmalone 124157986Sdwmalone if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 125157986Sdwmalone (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 126157986Sdwmalone return (EINVAL); 127157986Sdwmalone 128136739Srwatson if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 129101099Srwatson return (EINVAL); 130101099Srwatson 131101099Srwatson return (0); 132101099Srwatson} 133101099Srwatson 134101099Srwatsonstatic int 135101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS) 136101099Srwatson{ 137101099Srwatson struct mac_bsdextended_rule temprule, *ruleptr; 138101099Srwatson u_int namelen; 139101099Srwatson int error, index, *name; 140101099Srwatson 141145412Strhodes error = 0; 142101099Srwatson name = (int *)arg1; 143101099Srwatson namelen = arg2; 144101099Srwatson 145101099Srwatson /* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */ 146101099Srwatson 147101099Srwatson if (namelen != 1) 148101099Srwatson return (EINVAL); 149101099Srwatson 150101099Srwatson index = name[0]; 151154386Scsjp if (index >= MAC_BSDEXTENDED_MAXRULES) 152101099Srwatson return (ENOENT); 153101099Srwatson 154145412Strhodes ruleptr = NULL; 155145412Strhodes if (req->newptr && req->newlen != 0) { 156145412Strhodes error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 157101099Srwatson if (error) 158101099Srwatson return (error); 159145412Strhodes MALLOC(ruleptr, struct mac_bsdextended_rule *, 160145412Strhodes sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO); 161101099Srwatson } 162101099Srwatson 163145412Strhodes mtx_lock(&mac_bsdextended_mtx); 164145412Strhodes 165145412Strhodes if (req->oldptr) { 166145412Strhodes if (index < 0 || index > rule_slots + 1) { 167145412Strhodes error = ENOENT; 168145412Strhodes goto out; 169101099Srwatson } 170145412Strhodes if (rules[index] == NULL) { 171145412Strhodes error = ENOENT; 172145412Strhodes goto out; 173145412Strhodes } 174145412Strhodes temprule = *rules[index]; 175145412Strhodes } 176101099Srwatson 177145412Strhodes if (req->newptr && req->newlen == 0) { 178145412Strhodes /* printf("deletion\n"); */ 179145412Strhodes KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 180145412Strhodes ruleptr = rules[index]; 181145412Strhodes if (ruleptr == NULL) { 182145412Strhodes error = ENOENT; 183145412Strhodes goto out; 184145412Strhodes } 185145412Strhodes rule_count--; 186145412Strhodes rules[index] = NULL; 187145412Strhodes } else if (req->newptr) { 188101099Srwatson error = mac_bsdextended_rule_valid(&temprule); 189101099Srwatson if (error) 190145412Strhodes goto out; 191101099Srwatson 192101099Srwatson if (rules[index] == NULL) { 193101099Srwatson /* printf("addition\n"); */ 194101099Srwatson *ruleptr = temprule; 195101099Srwatson rules[index] = ruleptr; 196145412Strhodes ruleptr = NULL; 197145412Strhodes if (index + 1 > rule_slots) 198145412Strhodes rule_slots = index + 1; 199101099Srwatson rule_count++; 200101099Srwatson } else { 201101099Srwatson /* printf("replacement\n"); */ 202101099Srwatson *rules[index] = temprule; 203101099Srwatson } 204101099Srwatson } 205101099Srwatson 206145412Strhodesout: 207145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 208145412Strhodes if (ruleptr != NULL) 209145412Strhodes FREE(ruleptr, M_MACBSDEXTENDED); 210148482Strhodes if (req->oldptr && error == 0) 211145412Strhodes error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 212145412Strhodes 213148482Strhodes return (error); 214101099Srwatson} 215101099Srwatson 216101099SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, 217101099Srwatson CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules"); 218101099Srwatson 219101099Srwatsonstatic void 220101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc) 221101099Srwatson{ 222101099Srwatson 223101099Srwatson /* Initialize ruleset lock. */ 224145412Strhodes mtx_init(&mac_bsdextended_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 225145412Strhodes 226101099Srwatson /* Register dynamic sysctl's for rules. */ 227101099Srwatson} 228101099Srwatson 229101099Srwatsonstatic void 230101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc) 231101099Srwatson{ 232101099Srwatson 233145412Strhodes /* Destroy ruleset lock. */ 234145412Strhodes mtx_destroy(&mac_bsdextended_mtx); 235145412Strhodes 236101099Srwatson /* Tear down sysctls. */ 237101099Srwatson} 238101099Srwatson 239101099Srwatsonstatic int 240101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule, 241157986Sdwmalone struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 242101099Srwatson{ 243101099Srwatson int match; 244157986Sdwmalone int i; 245101099Srwatson 246101099Srwatson /* 247101099Srwatson * Is there a subject match? 248101099Srwatson */ 249145412Strhodes mtx_assert(&mac_bsdextended_mtx, MA_OWNED); 250157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 251157986Sdwmalone match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 252157986Sdwmalone cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 253157986Sdwmalone (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 254157986Sdwmalone cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 255157986Sdwmalone (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 256157986Sdwmalone cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 257101099Srwatson 258157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 259101099Srwatson match = !match; 260101099Srwatson 261101099Srwatson if (!match) 262101099Srwatson return (0); 263101099Srwatson } 264101099Srwatson 265157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 266157986Sdwmalone match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 267157986Sdwmalone cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 268157986Sdwmalone (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 269157986Sdwmalone cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 270101099Srwatson 271157986Sdwmalone if (!match) { 272157986Sdwmalone for (i = 0; i < cred->cr_ngroups; i++) 273157986Sdwmalone if (cred->cr_groups[i] 274157986Sdwmalone <= rule->mbr_subject.mbs_gid_max && 275157986Sdwmalone cred->cr_groups[i] 276157986Sdwmalone >= rule->mbr_subject.mbs_gid_min) { 277157986Sdwmalone match = 1; 278157986Sdwmalone break; 279157986Sdwmalone } 280157986Sdwmalone } 281157986Sdwmalone 282157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 283101099Srwatson match = !match; 284101099Srwatson 285101099Srwatson if (!match) 286101099Srwatson return (0); 287101099Srwatson } 288101099Srwatson 289157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 290157986Sdwmalone match = (cred->cr_prison != NULL && 291157986Sdwmalone cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 292157986Sdwmalone 293157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 294157986Sdwmalone match = !match; 295157986Sdwmalone 296157986Sdwmalone if (!match) 297157986Sdwmalone return (0); 298157986Sdwmalone } 299157986Sdwmalone 300101099Srwatson /* 301101099Srwatson * Is there an object match? 302101099Srwatson */ 303157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 304157986Sdwmalone match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 305157986Sdwmalone vap->va_uid >= rule->mbr_object.mbo_uid_min); 306101099Srwatson 307157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 308101099Srwatson match = !match; 309101099Srwatson 310101099Srwatson if (!match) 311101099Srwatson return (0); 312101099Srwatson } 313101099Srwatson 314157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 315157986Sdwmalone match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 316157986Sdwmalone vap->va_gid >= rule->mbr_object.mbo_gid_min); 317101099Srwatson 318157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 319101099Srwatson match = !match; 320101099Srwatson 321101099Srwatson if (!match) 322101099Srwatson return (0); 323101099Srwatson } 324101099Srwatson 325157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 326157986Sdwmalone match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 327157986Sdwmalone &(rule->mbr_object.mbo_fsid), 328157986Sdwmalone sizeof(rule->mbr_object.mbo_fsid)) == 0); 329157986Sdwmalone 330157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 331157986Sdwmalone match = !match; 332157986Sdwmalone 333157986Sdwmalone if (!match) 334157986Sdwmalone return 0; 335157986Sdwmalone } 336157986Sdwmalone 337157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SUID) { 338157986Sdwmalone match = (vap->va_mode & VSUID); 339157986Sdwmalone 340157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_SUID) 341157986Sdwmalone match = !match; 342157986Sdwmalone 343157986Sdwmalone if (!match) 344157986Sdwmalone return 0; 345157986Sdwmalone } 346157986Sdwmalone 347157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SGID) { 348157986Sdwmalone match = (vap->va_mode & VSGID); 349157986Sdwmalone 350157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_SGID) 351157986Sdwmalone match = !match; 352157986Sdwmalone 353157986Sdwmalone if (!match) 354157986Sdwmalone return 0; 355157986Sdwmalone } 356157986Sdwmalone 357157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 358157986Sdwmalone match = (vap->va_uid == cred->cr_uid || 359157986Sdwmalone vap->va_uid == cred->cr_ruid || 360157986Sdwmalone vap->va_uid == cred->cr_svuid); 361157986Sdwmalone 362157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 363157986Sdwmalone match = !match; 364157986Sdwmalone 365157986Sdwmalone if (!match) 366157986Sdwmalone return 0; 367157986Sdwmalone } 368157986Sdwmalone 369157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 370157986Sdwmalone match = (groupmember(vap->va_gid, cred) || 371157986Sdwmalone vap->va_gid == cred->cr_rgid || 372157986Sdwmalone vap->va_gid == cred->cr_svgid); 373157986Sdwmalone 374157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 375157986Sdwmalone match = !match; 376157986Sdwmalone 377157986Sdwmalone if (!match) 378157986Sdwmalone return 0; 379157986Sdwmalone } 380157986Sdwmalone 381157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 382157986Sdwmalone switch (vap->va_type) { 383157986Sdwmalone case VREG: 384157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 385157986Sdwmalone break; 386157986Sdwmalone case VDIR: 387157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 388157986Sdwmalone break; 389157986Sdwmalone case VBLK: 390157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 391157986Sdwmalone break; 392157986Sdwmalone case VCHR: 393157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 394157986Sdwmalone break; 395157986Sdwmalone case VLNK: 396157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 397157986Sdwmalone break; 398157986Sdwmalone case VSOCK: 399157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 400157986Sdwmalone break; 401157986Sdwmalone case VFIFO: 402157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 403157986Sdwmalone break; 404157986Sdwmalone default: 405157986Sdwmalone match = 0; 406157986Sdwmalone } 407157986Sdwmalone 408157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 409157986Sdwmalone match = !match; 410157986Sdwmalone 411157986Sdwmalone if (!match) 412157986Sdwmalone return 0; 413157986Sdwmalone } 414157986Sdwmalone 415101099Srwatson /* 416101099Srwatson * Is the access permitted? 417101099Srwatson */ 418101099Srwatson if ((rule->mbr_mode & acc_mode) != acc_mode) { 419134132Strhodes if (mac_bsdextended_logging) 420134132Strhodes log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 421134132Strhodes " on %d:%d failed. \n", cred->cr_ruid, 422157986Sdwmalone cred->cr_rgid, acc_mode, vap->va_uid, vap->va_gid); 423134132Strhodes return (EACCES); /* Matching rule denies access */ 424101099Srwatson } 425145412Strhodes 426134131Strhodes /* 427145412Strhodes * If the rule matched, permits access, and first match is enabled, 428145412Strhodes * return success. 429134131Strhodes */ 430134131Strhodes if (mac_bsdextended_firstmatch_enabled) 431134131Strhodes return (EJUSTRETURN); 432134131Strhodes else 433134131Strhodes return(0); 434101099Srwatson} 435101099Srwatson 436101099Srwatsonstatic int 437157986Sdwmalonemac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 438106212Srwatson int acc_mode) 439101099Srwatson{ 440101099Srwatson int error, i; 441101099Srwatson 442164033Srwatson /* 443164033Srwatson * XXXRW: More specific privilege selection needed? 444164033Srwatson */ 445132563Srwatson if (suser_cred(cred, 0) == 0) 446132563Srwatson return (0); 447132563Srwatson 448166843Srwatson /* 449166843Srwatson * Since we do not separately handle append, map append to write. 450166843Srwatson */ 451166843Srwatson if (acc_mode & MBI_APPEND) { 452166843Srwatson acc_mode &= ~MBI_APPEND; 453166843Srwatson acc_mode |= MBI_WRITE; 454166843Srwatson } 455166843Srwatson 456145412Strhodes mtx_lock(&mac_bsdextended_mtx); 457101099Srwatson for (i = 0; i < rule_slots; i++) { 458101099Srwatson if (rules[i] == NULL) 459101099Srwatson continue; 460101099Srwatson 461157986Sdwmalone error = mac_bsdextended_rulecheck(rules[i], cred, 462157986Sdwmalone vp, vap, acc_mode); 463134131Strhodes if (error == EJUSTRETURN) 464134131Strhodes break; 465145412Strhodes if (error) { 466145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 467101099Srwatson return (error); 468145412Strhodes } 469101099Srwatson } 470145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 471101099Srwatson return (0); 472101099Srwatson} 473101099Srwatson 474101099Srwatsonstatic int 475156300Sdwmalonemac_bsdextended_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 476112575Srwatson{ 477156300Sdwmalone int error; 478112575Srwatson struct vattr vap; 479112575Srwatson 480112575Srwatson if (!mac_bsdextended_enabled) 481112575Srwatson return (0); 482112575Srwatson 483112575Srwatson error = VOP_GETATTR(vp, &vap, cred, curthread); 484112575Srwatson if (error) 485112575Srwatson return (error); 486156300Sdwmalone 487157986Sdwmalone return (mac_bsdextended_check(cred, vp, &vap, acc_mode)); 488112575Srwatson} 489112575Srwatson 490112575Srwatsonstatic int 491156300Sdwmalonemac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp, 492156300Sdwmalone struct label *label) 493156300Sdwmalone{ 494156300Sdwmalone 495156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 496156300Sdwmalone} 497156300Sdwmalone 498156300Sdwmalonestatic int 499101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp, 500106212Srwatson struct label *label, int acc_mode) 501101099Srwatson{ 502101099Srwatson 503156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, acc_mode)); 504101099Srwatson} 505101099Srwatson 506101099Srwatsonstatic int 507101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, 508101099Srwatson struct label *dlabel) 509101099Srwatson{ 510101099Srwatson 511156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 512101099Srwatson} 513101099Srwatson 514101099Srwatsonstatic int 515101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, 516101099Srwatson struct label *dlabel) 517101099Srwatson{ 518101099Srwatson 519156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 520101099Srwatson} 521101099Srwatson 522101099Srwatsonstatic int 523101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp, 524101099Srwatson struct label *dlabel, struct componentname *cnp, struct vattr *vap) 525101099Srwatson{ 526101099Srwatson 527156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_WRITE)); 528101099Srwatson} 529101099Srwatson 530101099Srwatsonstatic int 531101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp, 532101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 533101099Srwatson struct componentname *cnp) 534101099Srwatson{ 535101099Srwatson int error; 536101099Srwatson 537156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 538101099Srwatson if (error) 539101099Srwatson return (error); 540101099Srwatson 541156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 542101099Srwatson} 543101099Srwatson 544101099Srwatsonstatic int 545101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 546101099Srwatson struct label *label, acl_type_t type) 547101099Srwatson{ 548101099Srwatson 549156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 550101099Srwatson} 551101099Srwatson 552101099Srwatsonstatic int 553119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 554119202Srwatson struct label *label, int attrnamespace, const char *name) 555119202Srwatson{ 556119202Srwatson 557156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 558119202Srwatson} 559119202Srwatson 560119202Srwatsonstatic int 561101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp, 562106648Srwatson struct label *label, struct image_params *imgp, 563106648Srwatson struct label *execlabel) 564101099Srwatson{ 565101099Srwatson 566156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 567101099Srwatson} 568101099Srwatson 569101099Srwatsonstatic int 570101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp, 571101099Srwatson struct label *label, acl_type_t type) 572101099Srwatson{ 573101099Srwatson 574156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_STAT)); 575101099Srwatson} 576101099Srwatson 577101099Srwatsonstatic int 578101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 579101099Srwatson struct label *label, int attrnamespace, const char *name, struct uio *uio) 580101099Srwatson{ 581101099Srwatson 582156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 583101099Srwatson} 584101099Srwatson 585101099Srwatsonstatic int 586104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp, 587104530Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 588104530Srwatson struct componentname *cnp) 589104530Srwatson{ 590104530Srwatson int error; 591104530Srwatson 592156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 593104530Srwatson if (error) 594104530Srwatson return (error); 595104530Srwatson 596156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 597104530Srwatson if (error) 598104530Srwatson return (error); 599104530Srwatson return (0); 600104530Srwatson} 601104530Srwatson 602104530Srwatsonstatic int 603119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 604119202Srwatson struct label *label, int attrnamespace) 605119202Srwatson{ 606119202Srwatson 607156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 608119202Srwatson} 609119202Srwatson 610119202Srwatsonstatic int 611101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 612101099Srwatson struct label *dlabel, struct componentname *cnp) 613101099Srwatson{ 614117247Srwatson 615156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 616101099Srwatson} 617101099Srwatson 618101099Srwatsonstatic int 619101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp, 620106212Srwatson struct label *filelabel, int acc_mode) 621101099Srwatson{ 622101099Srwatson 623156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, acc_mode)); 624101099Srwatson} 625101099Srwatson 626101099Srwatsonstatic int 627101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, 628101099Srwatson struct label *dlabel) 629101099Srwatson{ 630101099Srwatson 631156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_READ)); 632101099Srwatson} 633101099Srwatson 634101099Srwatsonstatic int 635101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp, 636101099Srwatson struct label *label) 637101099Srwatson{ 638101099Srwatson 639156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 640101099Srwatson} 641101099Srwatson 642101099Srwatsonstatic int 643101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 644101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 645101099Srwatson struct componentname *cnp) 646101099Srwatson{ 647101099Srwatson int error; 648101099Srwatson 649156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 650101099Srwatson if (error) 651101099Srwatson return (error); 652156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 653101099Srwatson 654101099Srwatson return (error); 655101099Srwatson} 656101099Srwatson 657101099Srwatsonstatic int 658101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 659101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, int samedir, 660101099Srwatson struct componentname *cnp) 661101099Srwatson{ 662101099Srwatson int error; 663101099Srwatson 664156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 665101099Srwatson if (error) 666101099Srwatson return (error); 667101099Srwatson 668156300Sdwmalone if (vp != NULL) 669156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 670101099Srwatson 671101099Srwatson return (error); 672101099Srwatson} 673101099Srwatson 674101099Srwatsonstatic int 675101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp, 676101099Srwatson struct label *label) 677101099Srwatson{ 678101099Srwatson 679156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 680101099Srwatson} 681101099Srwatson 682101099Srwatsonstatic int 683101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 684101099Srwatson struct label *label, acl_type_t type, struct acl *acl) 685101099Srwatson{ 686101099Srwatson 687156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 688101099Srwatson} 689101099Srwatson 690101099Srwatsonstatic int 691101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 692101099Srwatson struct label *label, int attrnamespace, const char *name, struct uio *uio) 693101099Srwatson{ 694101099Srwatson 695156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 696101099Srwatson} 697101099Srwatson 698101099Srwatsonstatic int 699101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp, 700101099Srwatson struct label *label, u_long flags) 701101099Srwatson{ 702101099Srwatson 703156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 704101099Srwatson} 705101099Srwatson 706101099Srwatsonstatic int 707101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp, 708101099Srwatson struct label *label, mode_t mode) 709101099Srwatson{ 710101099Srwatson 711156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 712101099Srwatson} 713101099Srwatson 714101099Srwatsonstatic int 715101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp, 716101099Srwatson struct label *label, uid_t uid, gid_t gid) 717101099Srwatson{ 718101099Srwatson 719156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 720101099Srwatson} 721101099Srwatson 722101099Srwatsonstatic int 723101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 724101099Srwatson struct label *label, struct timespec atime, struct timespec utime) 725101099Srwatson{ 726101099Srwatson 727156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 728101099Srwatson} 729101099Srwatson 730101099Srwatsonstatic int 731102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred, 732102129Srwatson struct ucred *file_cred, struct vnode *vp, struct label *label) 733101099Srwatson{ 734101099Srwatson 735156300Sdwmalone return (mac_bsdextended_check_vp(active_cred, vp, MBI_STAT)); 736101099Srwatson} 737101099Srwatson 738106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops = 739101099Srwatson{ 740106217Srwatson .mpo_destroy = mac_bsdextended_destroy, 741106217Srwatson .mpo_init = mac_bsdextended_init, 742112575Srwatson .mpo_check_system_swapon = mac_bsdextended_check_system_swapon, 743106217Srwatson .mpo_check_vnode_access = mac_bsdextended_check_vnode_access, 744106217Srwatson .mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir, 745106217Srwatson .mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot, 746106217Srwatson .mpo_check_vnode_create = mac_bsdextended_check_create_vnode, 747106217Srwatson .mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete, 748106217Srwatson .mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl, 749119202Srwatson .mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr, 750106217Srwatson .mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec, 751106217Srwatson .mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl, 752106217Srwatson .mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr, 753106217Srwatson .mpo_check_vnode_link = mac_bsdextended_check_vnode_link, 754119202Srwatson .mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr, 755106217Srwatson .mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup, 756106217Srwatson .mpo_check_vnode_open = mac_bsdextended_check_vnode_open, 757106217Srwatson .mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir, 758106217Srwatson .mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink, 759106217Srwatson .mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from, 760106217Srwatson .mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to, 761106217Srwatson .mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke, 762106217Srwatson .mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode, 763106217Srwatson .mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr, 764106217Srwatson .mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags, 765106217Srwatson .mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode, 766106217Srwatson .mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner, 767106217Srwatson .mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes, 768106217Srwatson .mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat, 769101099Srwatson}; 770101099Srwatson 771112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended, 772101099Srwatson "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL); 773