ugidfw_system.c revision 164033
1101099Srwatson/*- 2145412Strhodes * Copyright (c) 2005 Tom Rhodes 3126097Srwatson * Copyright (c) 1999-2002 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 164033 2006-11-06 13:42:10Z 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/types.h> 46101099Srwatson#include <sys/param.h> 47101099Srwatson#include <sys/acl.h> 48101099Srwatson#include <sys/conf.h> 49101099Srwatson#include <sys/kernel.h> 50157986Sdwmalone#include <sys/jail.h> 51145412Strhodes#include <sys/lock.h> 52101099Srwatson#include <sys/mac.h> 53101099Srwatson#include <sys/malloc.h> 54101099Srwatson#include <sys/mount.h> 55145412Strhodes#include <sys/mutex.h> 56101099Srwatson#include <sys/proc.h> 57101099Srwatson#include <sys/systm.h> 58101099Srwatson#include <sys/sysproto.h> 59101099Srwatson#include <sys/sysent.h> 60101099Srwatson#include <sys/vnode.h> 61101099Srwatson#include <sys/file.h> 62101099Srwatson#include <sys/socket.h> 63101099Srwatson#include <sys/socketvar.h> 64101099Srwatson#include <sys/sysctl.h> 65134132Strhodes#include <sys/syslog.h> 66157986Sdwmalone#include <sys/ucred.h> 67101099Srwatson 68101099Srwatson#include <net/bpfdesc.h> 69101099Srwatson#include <net/if.h> 70101099Srwatson#include <net/if_types.h> 71101099Srwatson#include <net/if_var.h> 72101099Srwatson 73101099Srwatson#include <vm/vm.h> 74101099Srwatson 75101099Srwatson#include <sys/mac_policy.h> 76101099Srwatson 77101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h> 78101099Srwatson 79145412Strhodesstatic struct mtx mac_bsdextended_mtx; 80145412Strhodes 81101099SrwatsonSYSCTL_DECL(_security_mac); 82101099Srwatson 83101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 84101099Srwatson "TrustedBSD extended BSD MAC policy controls"); 85101099Srwatson 86101099Srwatsonstatic int mac_bsdextended_enabled = 1; 87101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 88101099Srwatson &mac_bsdextended_enabled, 0, "Enforce extended BSD policy"); 89101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled); 90101099Srwatson 91101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 92101099Srwatson 93101099Srwatson#define MAC_BSDEXTENDED_MAXRULES 250 94101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 95101099Srwatsonstatic int rule_count = 0; 96101099Srwatsonstatic int rule_slots = 0; 97157986Sdwmalonestatic int rule_version = MB_VERSION; 98101099Srwatson 99101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 100101099Srwatson &rule_count, 0, "Number of defined rules\n"); 101101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 102101099Srwatson &rule_slots, 0, "Number of used rule slots\n"); 103157986SdwmaloneSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 104157986Sdwmalone &rule_version, 0, "Version number for API\n"); 105101099Srwatson 106134132Strhodes/* 107145412Strhodes * This is just used for logging purposes, eventually we would like 108134132Strhodes * to log much more then failed requests. 109134132Strhodes */ 110134132Strhodesstatic int mac_bsdextended_logging; 111134132StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 112134132Strhodes &mac_bsdextended_logging, 0, "Log failed authorization requests"); 113134132Strhodes 114134132Strhodes/* 115134131Strhodes * This tunable is here for compatibility. It will allow the user 116134131Strhodes * to switch between the new mode (first rule matches) and the old 117134131Strhodes * functionality (all rules match). 118134131Strhodes */ 119101099Srwatsonstatic int 120134131Strhodesmac_bsdextended_firstmatch_enabled; 121134131StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 122135039Strhodes CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1, 123134131Strhodes "Disable/enable match first rule functionality"); 124134131Strhodes 125134131Strhodesstatic int 126101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule) 127101099Srwatson{ 128101099Srwatson 129157986Sdwmalone if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 130101099Srwatson return (EINVAL); 131101099Srwatson 132157986Sdwmalone if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 133101099Srwatson return (EINVAL); 134101099Srwatson 135157986Sdwmalone if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 136157986Sdwmalone return (EINVAL); 137157986Sdwmalone 138157986Sdwmalone if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 139157986Sdwmalone return (EINVAL); 140157986Sdwmalone 141157986Sdwmalone if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 142157986Sdwmalone (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 143157986Sdwmalone return (EINVAL); 144157986Sdwmalone 145136739Srwatson if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 146101099Srwatson return (EINVAL); 147101099Srwatson 148101099Srwatson return (0); 149101099Srwatson} 150101099Srwatson 151101099Srwatsonstatic int 152101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS) 153101099Srwatson{ 154101099Srwatson struct mac_bsdextended_rule temprule, *ruleptr; 155101099Srwatson u_int namelen; 156101099Srwatson int error, index, *name; 157101099Srwatson 158145412Strhodes error = 0; 159101099Srwatson name = (int *)arg1; 160101099Srwatson namelen = arg2; 161101099Srwatson 162101099Srwatson /* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */ 163101099Srwatson 164101099Srwatson if (namelen != 1) 165101099Srwatson return (EINVAL); 166101099Srwatson 167101099Srwatson index = name[0]; 168154386Scsjp if (index >= MAC_BSDEXTENDED_MAXRULES) 169101099Srwatson return (ENOENT); 170101099Srwatson 171145412Strhodes ruleptr = NULL; 172145412Strhodes if (req->newptr && req->newlen != 0) { 173145412Strhodes error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 174101099Srwatson if (error) 175101099Srwatson return (error); 176145412Strhodes MALLOC(ruleptr, struct mac_bsdextended_rule *, 177145412Strhodes sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO); 178101099Srwatson } 179101099Srwatson 180145412Strhodes mtx_lock(&mac_bsdextended_mtx); 181145412Strhodes 182145412Strhodes if (req->oldptr) { 183145412Strhodes if (index < 0 || index > rule_slots + 1) { 184145412Strhodes error = ENOENT; 185145412Strhodes goto out; 186101099Srwatson } 187145412Strhodes if (rules[index] == NULL) { 188145412Strhodes error = ENOENT; 189145412Strhodes goto out; 190145412Strhodes } 191145412Strhodes temprule = *rules[index]; 192145412Strhodes } 193101099Srwatson 194145412Strhodes if (req->newptr && req->newlen == 0) { 195145412Strhodes /* printf("deletion\n"); */ 196145412Strhodes KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 197145412Strhodes ruleptr = rules[index]; 198145412Strhodes if (ruleptr == NULL) { 199145412Strhodes error = ENOENT; 200145412Strhodes goto out; 201145412Strhodes } 202145412Strhodes rule_count--; 203145412Strhodes rules[index] = NULL; 204145412Strhodes } else if (req->newptr) { 205101099Srwatson error = mac_bsdextended_rule_valid(&temprule); 206101099Srwatson if (error) 207145412Strhodes goto out; 208101099Srwatson 209101099Srwatson if (rules[index] == NULL) { 210101099Srwatson /* printf("addition\n"); */ 211101099Srwatson *ruleptr = temprule; 212101099Srwatson rules[index] = ruleptr; 213145412Strhodes ruleptr = NULL; 214145412Strhodes if (index + 1 > rule_slots) 215145412Strhodes rule_slots = index + 1; 216101099Srwatson rule_count++; 217101099Srwatson } else { 218101099Srwatson /* printf("replacement\n"); */ 219101099Srwatson *rules[index] = temprule; 220101099Srwatson } 221101099Srwatson } 222101099Srwatson 223145412Strhodesout: 224145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 225145412Strhodes if (ruleptr != NULL) 226145412Strhodes FREE(ruleptr, M_MACBSDEXTENDED); 227148482Strhodes if (req->oldptr && error == 0) 228145412Strhodes error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 229145412Strhodes 230148482Strhodes return (error); 231101099Srwatson} 232101099Srwatson 233101099SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, 234101099Srwatson CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules"); 235101099Srwatson 236101099Srwatsonstatic void 237101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc) 238101099Srwatson{ 239101099Srwatson 240101099Srwatson /* Initialize ruleset lock. */ 241145412Strhodes mtx_init(&mac_bsdextended_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 242145412Strhodes 243101099Srwatson /* Register dynamic sysctl's for rules. */ 244101099Srwatson} 245101099Srwatson 246101099Srwatsonstatic void 247101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc) 248101099Srwatson{ 249101099Srwatson 250145412Strhodes /* Destroy ruleset lock. */ 251145412Strhodes mtx_destroy(&mac_bsdextended_mtx); 252145412Strhodes 253101099Srwatson /* Tear down sysctls. */ 254101099Srwatson} 255101099Srwatson 256101099Srwatsonstatic int 257101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule, 258157986Sdwmalone struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 259101099Srwatson{ 260101099Srwatson int match; 261157986Sdwmalone int i; 262101099Srwatson 263101099Srwatson /* 264101099Srwatson * Is there a subject match? 265101099Srwatson */ 266145412Strhodes mtx_assert(&mac_bsdextended_mtx, MA_OWNED); 267157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 268157986Sdwmalone match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 269157986Sdwmalone cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 270157986Sdwmalone (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 271157986Sdwmalone cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 272157986Sdwmalone (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 273157986Sdwmalone cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 274101099Srwatson 275157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 276101099Srwatson match = !match; 277101099Srwatson 278101099Srwatson if (!match) 279101099Srwatson return (0); 280101099Srwatson } 281101099Srwatson 282157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 283157986Sdwmalone match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 284157986Sdwmalone cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 285157986Sdwmalone (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 286157986Sdwmalone cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 287101099Srwatson 288157986Sdwmalone if (!match) { 289157986Sdwmalone for (i = 0; i < cred->cr_ngroups; i++) 290157986Sdwmalone if (cred->cr_groups[i] 291157986Sdwmalone <= rule->mbr_subject.mbs_gid_max && 292157986Sdwmalone cred->cr_groups[i] 293157986Sdwmalone >= rule->mbr_subject.mbs_gid_min) { 294157986Sdwmalone match = 1; 295157986Sdwmalone break; 296157986Sdwmalone } 297157986Sdwmalone } 298157986Sdwmalone 299157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 300101099Srwatson match = !match; 301101099Srwatson 302101099Srwatson if (!match) 303101099Srwatson return (0); 304101099Srwatson } 305101099Srwatson 306157986Sdwmalone if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 307157986Sdwmalone match = (cred->cr_prison != NULL && 308157986Sdwmalone cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 309157986Sdwmalone 310157986Sdwmalone if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 311157986Sdwmalone match = !match; 312157986Sdwmalone 313157986Sdwmalone if (!match) 314157986Sdwmalone return (0); 315157986Sdwmalone } 316157986Sdwmalone 317101099Srwatson /* 318101099Srwatson * Is there an object match? 319101099Srwatson */ 320157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 321157986Sdwmalone match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 322157986Sdwmalone vap->va_uid >= rule->mbr_object.mbo_uid_min); 323101099Srwatson 324157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 325101099Srwatson match = !match; 326101099Srwatson 327101099Srwatson if (!match) 328101099Srwatson return (0); 329101099Srwatson } 330101099Srwatson 331157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 332157986Sdwmalone match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 333157986Sdwmalone vap->va_gid >= rule->mbr_object.mbo_gid_min); 334101099Srwatson 335157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 336101099Srwatson match = !match; 337101099Srwatson 338101099Srwatson if (!match) 339101099Srwatson return (0); 340101099Srwatson } 341101099Srwatson 342157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 343157986Sdwmalone match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 344157986Sdwmalone &(rule->mbr_object.mbo_fsid), 345157986Sdwmalone sizeof(rule->mbr_object.mbo_fsid)) == 0); 346157986Sdwmalone 347157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 348157986Sdwmalone match = !match; 349157986Sdwmalone 350157986Sdwmalone if (!match) 351157986Sdwmalone return 0; 352157986Sdwmalone } 353157986Sdwmalone 354157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SUID) { 355157986Sdwmalone match = (vap->va_mode & VSUID); 356157986Sdwmalone 357157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_SUID) 358157986Sdwmalone match = !match; 359157986Sdwmalone 360157986Sdwmalone if (!match) 361157986Sdwmalone return 0; 362157986Sdwmalone } 363157986Sdwmalone 364157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_SGID) { 365157986Sdwmalone match = (vap->va_mode & VSGID); 366157986Sdwmalone 367157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_SGID) 368157986Sdwmalone match = !match; 369157986Sdwmalone 370157986Sdwmalone if (!match) 371157986Sdwmalone return 0; 372157986Sdwmalone } 373157986Sdwmalone 374157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 375157986Sdwmalone match = (vap->va_uid == cred->cr_uid || 376157986Sdwmalone vap->va_uid == cred->cr_ruid || 377157986Sdwmalone vap->va_uid == cred->cr_svuid); 378157986Sdwmalone 379157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 380157986Sdwmalone match = !match; 381157986Sdwmalone 382157986Sdwmalone if (!match) 383157986Sdwmalone return 0; 384157986Sdwmalone } 385157986Sdwmalone 386157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 387157986Sdwmalone match = (groupmember(vap->va_gid, cred) || 388157986Sdwmalone vap->va_gid == cred->cr_rgid || 389157986Sdwmalone vap->va_gid == cred->cr_svgid); 390157986Sdwmalone 391157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 392157986Sdwmalone match = !match; 393157986Sdwmalone 394157986Sdwmalone if (!match) 395157986Sdwmalone return 0; 396157986Sdwmalone } 397157986Sdwmalone 398157986Sdwmalone if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 399157986Sdwmalone switch (vap->va_type) { 400157986Sdwmalone case VREG: 401157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 402157986Sdwmalone break; 403157986Sdwmalone case VDIR: 404157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 405157986Sdwmalone break; 406157986Sdwmalone case VBLK: 407157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 408157986Sdwmalone break; 409157986Sdwmalone case VCHR: 410157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 411157986Sdwmalone break; 412157986Sdwmalone case VLNK: 413157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 414157986Sdwmalone break; 415157986Sdwmalone case VSOCK: 416157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 417157986Sdwmalone break; 418157986Sdwmalone case VFIFO: 419157986Sdwmalone match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 420157986Sdwmalone break; 421157986Sdwmalone default: 422157986Sdwmalone match = 0; 423157986Sdwmalone } 424157986Sdwmalone 425157986Sdwmalone if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 426157986Sdwmalone match = !match; 427157986Sdwmalone 428157986Sdwmalone if (!match) 429157986Sdwmalone return 0; 430157986Sdwmalone } 431157986Sdwmalone 432101099Srwatson /* 433101099Srwatson * Is the access permitted? 434101099Srwatson */ 435101099Srwatson if ((rule->mbr_mode & acc_mode) != acc_mode) { 436134132Strhodes if (mac_bsdextended_logging) 437134132Strhodes log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 438134132Strhodes " on %d:%d failed. \n", cred->cr_ruid, 439157986Sdwmalone cred->cr_rgid, acc_mode, vap->va_uid, vap->va_gid); 440134132Strhodes return (EACCES); /* Matching rule denies access */ 441101099Srwatson } 442145412Strhodes 443134131Strhodes /* 444145412Strhodes * If the rule matched, permits access, and first match is enabled, 445145412Strhodes * return success. 446134131Strhodes */ 447134131Strhodes if (mac_bsdextended_firstmatch_enabled) 448134131Strhodes return (EJUSTRETURN); 449134131Strhodes else 450134131Strhodes return(0); 451101099Srwatson} 452101099Srwatson 453101099Srwatsonstatic int 454157986Sdwmalonemac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 455106212Srwatson int acc_mode) 456101099Srwatson{ 457101099Srwatson int error, i; 458101099Srwatson 459164033Srwatson /* 460164033Srwatson * XXXRW: More specific privilege selection needed? 461164033Srwatson */ 462132563Srwatson if (suser_cred(cred, 0) == 0) 463132563Srwatson return (0); 464132563Srwatson 465145412Strhodes mtx_lock(&mac_bsdextended_mtx); 466101099Srwatson for (i = 0; i < rule_slots; i++) { 467101099Srwatson if (rules[i] == NULL) 468101099Srwatson continue; 469101099Srwatson 470108376Srwatson /* 471145412Strhodes * Since we do not separately handle append, map append to 472108376Srwatson * write. 473108376Srwatson */ 474136739Srwatson if (acc_mode & MBI_APPEND) { 475136739Srwatson acc_mode &= ~MBI_APPEND; 476136739Srwatson acc_mode |= MBI_WRITE; 477108376Srwatson } 478108376Srwatson 479157986Sdwmalone error = mac_bsdextended_rulecheck(rules[i], cred, 480157986Sdwmalone vp, vap, acc_mode); 481134131Strhodes if (error == EJUSTRETURN) 482134131Strhodes break; 483145412Strhodes if (error) { 484145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 485101099Srwatson return (error); 486145412Strhodes } 487101099Srwatson } 488145412Strhodes mtx_unlock(&mac_bsdextended_mtx); 489101099Srwatson return (0); 490101099Srwatson} 491101099Srwatson 492101099Srwatsonstatic int 493156300Sdwmalonemac_bsdextended_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 494112575Srwatson{ 495156300Sdwmalone int error; 496112575Srwatson struct vattr vap; 497112575Srwatson 498112575Srwatson if (!mac_bsdextended_enabled) 499112575Srwatson return (0); 500112575Srwatson 501112575Srwatson error = VOP_GETATTR(vp, &vap, cred, curthread); 502112575Srwatson if (error) 503112575Srwatson return (error); 504156300Sdwmalone 505157986Sdwmalone return (mac_bsdextended_check(cred, vp, &vap, acc_mode)); 506112575Srwatson} 507112575Srwatson 508112575Srwatsonstatic int 509156300Sdwmalonemac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp, 510156300Sdwmalone struct label *label) 511156300Sdwmalone{ 512156300Sdwmalone 513156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 514156300Sdwmalone} 515156300Sdwmalone 516156300Sdwmalonestatic int 517101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp, 518106212Srwatson struct label *label, int acc_mode) 519101099Srwatson{ 520101099Srwatson 521156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, acc_mode)); 522101099Srwatson} 523101099Srwatson 524101099Srwatsonstatic int 525101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, 526101099Srwatson struct label *dlabel) 527101099Srwatson{ 528101099Srwatson 529156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 530101099Srwatson} 531101099Srwatson 532101099Srwatsonstatic int 533101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, 534101099Srwatson struct label *dlabel) 535101099Srwatson{ 536101099Srwatson 537156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 538101099Srwatson} 539101099Srwatson 540101099Srwatsonstatic int 541101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp, 542101099Srwatson struct label *dlabel, struct componentname *cnp, struct vattr *vap) 543101099Srwatson{ 544101099Srwatson 545156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_WRITE)); 546101099Srwatson} 547101099Srwatson 548101099Srwatsonstatic int 549101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp, 550101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 551101099Srwatson struct componentname *cnp) 552101099Srwatson{ 553101099Srwatson int error; 554101099Srwatson 555156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 556101099Srwatson if (error) 557101099Srwatson return (error); 558101099Srwatson 559156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 560101099Srwatson} 561101099Srwatson 562101099Srwatsonstatic int 563101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 564101099Srwatson struct label *label, acl_type_t type) 565101099Srwatson{ 566101099Srwatson 567156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 568101099Srwatson} 569101099Srwatson 570101099Srwatsonstatic int 571119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 572119202Srwatson struct label *label, int attrnamespace, const char *name) 573119202Srwatson{ 574119202Srwatson 575156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 576119202Srwatson} 577119202Srwatson 578119202Srwatsonstatic int 579101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp, 580106648Srwatson struct label *label, struct image_params *imgp, 581106648Srwatson struct label *execlabel) 582101099Srwatson{ 583101099Srwatson 584156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 585101099Srwatson} 586101099Srwatson 587101099Srwatsonstatic int 588101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp, 589101099Srwatson struct label *label, acl_type_t type) 590101099Srwatson{ 591101099Srwatson 592156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_STAT)); 593101099Srwatson} 594101099Srwatson 595101099Srwatsonstatic int 596101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 597101099Srwatson struct label *label, int attrnamespace, const char *name, struct uio *uio) 598101099Srwatson{ 599101099Srwatson 600156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 601101099Srwatson} 602101099Srwatson 603101099Srwatsonstatic int 604104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp, 605104530Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 606104530Srwatson struct componentname *cnp) 607104530Srwatson{ 608104530Srwatson int error; 609104530Srwatson 610156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 611104530Srwatson if (error) 612104530Srwatson return (error); 613104530Srwatson 614156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 615104530Srwatson if (error) 616104530Srwatson return (error); 617104530Srwatson return (0); 618104530Srwatson} 619104530Srwatson 620104530Srwatsonstatic int 621119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 622119202Srwatson struct label *label, int attrnamespace) 623119202Srwatson{ 624119202Srwatson 625156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 626119202Srwatson} 627119202Srwatson 628119202Srwatsonstatic int 629101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 630101099Srwatson struct label *dlabel, struct componentname *cnp) 631101099Srwatson{ 632117247Srwatson 633156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC)); 634101099Srwatson} 635101099Srwatson 636101099Srwatsonstatic int 637101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp, 638106212Srwatson struct label *filelabel, int acc_mode) 639101099Srwatson{ 640101099Srwatson 641156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, acc_mode)); 642101099Srwatson} 643101099Srwatson 644101099Srwatsonstatic int 645101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, 646101099Srwatson struct label *dlabel) 647101099Srwatson{ 648101099Srwatson 649156300Sdwmalone return (mac_bsdextended_check_vp(cred, dvp, MBI_READ)); 650101099Srwatson} 651101099Srwatson 652101099Srwatsonstatic int 653101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp, 654101099Srwatson struct label *label) 655101099Srwatson{ 656101099Srwatson 657156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_READ)); 658101099Srwatson} 659101099Srwatson 660101099Srwatsonstatic int 661101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 662101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, 663101099Srwatson struct componentname *cnp) 664101099Srwatson{ 665101099Srwatson int error; 666101099Srwatson 667156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 668101099Srwatson if (error) 669101099Srwatson return (error); 670156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 671101099Srwatson 672101099Srwatson return (error); 673101099Srwatson} 674101099Srwatson 675101099Srwatsonstatic int 676101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 677101099Srwatson struct label *dlabel, struct vnode *vp, struct label *label, int samedir, 678101099Srwatson struct componentname *cnp) 679101099Srwatson{ 680101099Srwatson int error; 681101099Srwatson 682156300Sdwmalone error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE); 683101099Srwatson if (error) 684101099Srwatson return (error); 685101099Srwatson 686156300Sdwmalone if (vp != NULL) 687156300Sdwmalone error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE); 688101099Srwatson 689101099Srwatson return (error); 690101099Srwatson} 691101099Srwatson 692101099Srwatsonstatic int 693101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp, 694101099Srwatson struct label *label) 695101099Srwatson{ 696101099Srwatson 697156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 698101099Srwatson} 699101099Srwatson 700101099Srwatsonstatic int 701101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 702101099Srwatson struct label *label, acl_type_t type, struct acl *acl) 703101099Srwatson{ 704101099Srwatson 705156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 706101099Srwatson} 707101099Srwatson 708101099Srwatsonstatic int 709101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 710101099Srwatson struct label *label, int attrnamespace, const char *name, struct uio *uio) 711101099Srwatson{ 712101099Srwatson 713156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE)); 714101099Srwatson} 715101099Srwatson 716101099Srwatsonstatic int 717101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp, 718101099Srwatson struct label *label, u_long flags) 719101099Srwatson{ 720101099Srwatson 721156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 722101099Srwatson} 723101099Srwatson 724101099Srwatsonstatic int 725101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp, 726101099Srwatson struct label *label, mode_t mode) 727101099Srwatson{ 728101099Srwatson 729156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 730101099Srwatson} 731101099Srwatson 732101099Srwatsonstatic int 733101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp, 734101099Srwatson struct label *label, uid_t uid, gid_t gid) 735101099Srwatson{ 736101099Srwatson 737156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 738101099Srwatson} 739101099Srwatson 740101099Srwatsonstatic int 741101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 742101099Srwatson struct label *label, struct timespec atime, struct timespec utime) 743101099Srwatson{ 744101099Srwatson 745156300Sdwmalone return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN)); 746101099Srwatson} 747101099Srwatson 748101099Srwatsonstatic int 749102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred, 750102129Srwatson struct ucred *file_cred, struct vnode *vp, struct label *label) 751101099Srwatson{ 752101099Srwatson 753156300Sdwmalone return (mac_bsdextended_check_vp(active_cred, vp, MBI_STAT)); 754101099Srwatson} 755101099Srwatson 756106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops = 757101099Srwatson{ 758106217Srwatson .mpo_destroy = mac_bsdextended_destroy, 759106217Srwatson .mpo_init = mac_bsdextended_init, 760112575Srwatson .mpo_check_system_swapon = mac_bsdextended_check_system_swapon, 761106217Srwatson .mpo_check_vnode_access = mac_bsdextended_check_vnode_access, 762106217Srwatson .mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir, 763106217Srwatson .mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot, 764106217Srwatson .mpo_check_vnode_create = mac_bsdextended_check_create_vnode, 765106217Srwatson .mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete, 766106217Srwatson .mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl, 767119202Srwatson .mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr, 768106217Srwatson .mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec, 769106217Srwatson .mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl, 770106217Srwatson .mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr, 771106217Srwatson .mpo_check_vnode_link = mac_bsdextended_check_vnode_link, 772119202Srwatson .mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr, 773106217Srwatson .mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup, 774106217Srwatson .mpo_check_vnode_open = mac_bsdextended_check_vnode_open, 775106217Srwatson .mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir, 776106217Srwatson .mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink, 777106217Srwatson .mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from, 778106217Srwatson .mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to, 779106217Srwatson .mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke, 780106217Srwatson .mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode, 781106217Srwatson .mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr, 782106217Srwatson .mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags, 783106217Srwatson .mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode, 784106217Srwatson .mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner, 785106217Srwatson .mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes, 786106217Srwatson .mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat, 787101099Srwatson}; 788101099Srwatson 789112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended, 790101099Srwatson "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL); 791