ugidfw_vnode.c revision 182905
126175Sfenner/*- 275107Sfenner * Copyright (c) 1999-2002, 2007 Robert N. M. Watson 326175Sfenner * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 475107Sfenner * Copyright (c) 2005 Tom Rhodes 575107Sfenner * Copyright (c) 2006 SPARTA, Inc. 6127664Sbms * All rights reserved. 775107Sfenner * 8127664Sbms * This software was developed by Robert Watson for the TrustedBSD Project. 975107Sfenner * It was later enhanced by Tom Rhodes for the TrustedBSD Project. 1075107Sfenner * 1175107Sfenner * This software was developed for the FreeBSD Project in part by Network 12127664Sbms * Associates Laboratories, the Security Research Division of Network 1375107Sfenner * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 1475107Sfenner * as part of the DARPA CHATS research program. 1575107Sfenner * 1675107Sfenner * This software was enhanced by SPARTA ISSO under SPAWAR contract 1775107Sfenner * N66001-04-C-6019 ("SEFOS"). 1875107Sfenner * 1975107Sfenner * Redistribution and use in source and binary forms, with or without 2075107Sfenner * modification, are permitted provided that the following conditions 2175107Sfenner * are met: 22127664Sbms * 1. Redistributions of source code must retain the above copyright 2375107Sfenner * notice, this list of conditions and the following disclaimer. 2475107Sfenner * 2. Redistributions in binary form must reproduce the above copyright 2575107Sfenner * notice, this list of conditions and the following disclaimer in the 2626175Sfenner * documentation and/or other materials provided with the distribution. 27127664Sbms * 2826175Sfenner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29127664Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30147894Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3126175Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 3226175Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3375107Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3475107Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3575107Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3675107Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3775107Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3875107Sfenner * SUCH DAMAGE. 3975107Sfenner * 4075107Sfenner * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 182905 2008-09-10 13:16:41Z trasz $ 4175107Sfenner */ 4275107Sfenner 4375107Sfenner/* 4475107Sfenner * Developed by the TrustedBSD Project. 4575107Sfenner * 4675107Sfenner * "BSD Extended" MAC policy, allowing the administrator to impose mandatory 4775107Sfenner * firewall-like rules regarding users and file system objects. 4875107Sfenner */ 4975107Sfenner 5075107Sfenner#include <sys/param.h> 5175107Sfenner#include <sys/acl.h> 5275107Sfenner#include <sys/kernel.h> 5375107Sfenner#include <sys/jail.h> 5475107Sfenner#include <sys/lock.h> 5598530Sfenner#include <sys/malloc.h> 5698530Sfenner#include <sys/module.h> 5798530Sfenner#include <sys/mount.h> 5898530Sfenner#include <sys/mutex.h> 5998530Sfenner#include <sys/priv.h> 6098530Sfenner#include <sys/systm.h> 6198530Sfenner#include <sys/vnode.h> 6298530Sfenner#include <sys/sysctl.h> 6398530Sfenner#include <sys/syslog.h> 6498530Sfenner#include <sys/stat.h> 6598530Sfenner 6698530Sfenner#include <security/mac/mac_policy.h> 6798530Sfenner#include <security/mac_bsdextended/mac_bsdextended.h> 6898530Sfenner 6998530Sfennerstatic struct mtx ugidfw_mtx; 7098530Sfenner 7198530SfennerSYSCTL_DECL(_security_mac); 7298530Sfenner 7375107SfennerSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0, 7426175Sfenner "TrustedBSD extended BSD MAC policy controls"); 7575107Sfenner 7675107Sfennerstatic int ugidfw_enabled = 1; 7775107SfennerSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW, 7839291Sfenner &ugidfw_enabled, 0, "Enforce extended BSD policy"); 7926175SfennerTUNABLE_INT("security.mac.bsdextended.enabled", &ugidfw_enabled); 8075107Sfenner 8175107SfennerMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule"); 8226175Sfenner 83127664Sbms#define MAC_BSDEXTENDED_MAXRULES 250 84127664Sbmsstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES]; 85127664Sbmsstatic int rule_count = 0; 86147894Ssamstatic int rule_slots = 0; 87147894Ssamstatic int rule_version = MB_VERSION; 88147894Ssam 89147894SsamSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD, 90127664Sbms &rule_count, 0, "Number of defined rules\n"); 9126175SfennerSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD, 9226175Sfenner &rule_slots, 0, "Number of used rule slots\n"); 9375107SfennerSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD, 9475107Sfenner &rule_version, 0, "Version number for API\n"); 9526175Sfenner 9675107Sfenner/* 9775107Sfenner * This is just used for logging purposes, eventually we would like to log 9875107Sfenner * much more then failed requests. 9975107Sfenner */ 10075107Sfennerstatic int ugidfw_logging; 10175107SfennerSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW, 10275107Sfenner &ugidfw_logging, 0, "Log failed authorization requests"); 10326175Sfenner 10498530Sfenner/* 10598530Sfenner * This tunable is here for compatibility. It will allow the user to switch 10698530Sfenner * between the new mode (first rule matches) and the old functionality (all 10798530Sfenner * rules match). 10898530Sfenner */ 10998530Sfennerstatic int ugidfw_firstmatch_enabled; 11098530SfennerSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled, 11198530Sfenner CTLFLAG_RW, &ugidfw_firstmatch_enabled, 1, 11298530Sfenner "Disable/enable match first rule functionality"); 11398530Sfenner 11498530Sfennerstatic int 11598530Sfennerugidfw_rule_valid(struct mac_bsdextended_rule *rule) 11698530Sfenner{ 11798530Sfenner 11898530Sfenner if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 11998530Sfenner return (EINVAL); 12098530Sfenner if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS) 12198530Sfenner return (EINVAL); 12298530Sfenner if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 12398530Sfenner return (EINVAL); 12498530Sfenner if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS) 12598530Sfenner return (EINVAL); 12698530Sfenner if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && 12798530Sfenner (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE) 12898530Sfenner return (EINVAL); 129127664Sbms if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM) 13098530Sfenner return (EINVAL); 13126175Sfenner return (0); 13275107Sfenner} 13398530Sfenner 13498530Sfennerstatic int 13598530Sfennersysctl_rule(SYSCTL_HANDLER_ARGS) 13675107Sfenner{ 13775107Sfenner struct mac_bsdextended_rule temprule, *ruleptr; 13875107Sfenner u_int namelen; 13975107Sfenner int error, index, *name; 14075107Sfenner 14175107Sfenner error = 0; 14275107Sfenner name = (int *)arg1; 14375107Sfenner namelen = arg2; 14475107Sfenner if (namelen != 1) 14598530Sfenner return (EINVAL); 14675107Sfenner index = name[0]; 14775107Sfenner if (index >= MAC_BSDEXTENDED_MAXRULES) 14875107Sfenner return (ENOENT); 14975107Sfenner 15026175Sfenner ruleptr = NULL; 15126175Sfenner if (req->newptr && req->newlen != 0) { 15275107Sfenner error = SYSCTL_IN(req, &temprule, sizeof(temprule)); 15375107Sfenner if (error) 15475107Sfenner return (error); 15526175Sfenner MALLOC(ruleptr, struct mac_bsdextended_rule *, 15675107Sfenner sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO); 15798530Sfenner } 15898530Sfenner 15998530Sfenner mtx_lock(&ugidfw_mtx); 16098530Sfenner if (req->oldptr) { 16198530Sfenner if (index < 0 || index > rule_slots + 1) { 16298530Sfenner error = ENOENT; 16398530Sfenner goto out; 16498530Sfenner } 16598530Sfenner if (rules[index] == NULL) { 16675107Sfenner error = ENOENT; 16775107Sfenner goto out; 168127664Sbms } 169127664Sbms temprule = *rules[index]; 170127664Sbms } 171127664Sbms if (req->newptr && req->newlen == 0) { 172127664Sbms KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL")); 173127664Sbms ruleptr = rules[index]; 174127664Sbms if (ruleptr == NULL) { 175127664Sbms error = ENOENT; 176127664Sbms goto out; 177127664Sbms } 17875107Sfenner rule_count--; 17975107Sfenner rules[index] = NULL; 180127664Sbms } else if (req->newptr) { 181127664Sbms error = ugidfw_rule_valid(&temprule); 18275107Sfenner if (error) 18375107Sfenner goto out; 18475107Sfenner if (rules[index] == NULL) { 18575107Sfenner *ruleptr = temprule; 18675107Sfenner rules[index] = ruleptr; 18775107Sfenner ruleptr = NULL; 18875107Sfenner if (index + 1 > rule_slots) 18975107Sfenner rule_slots = index + 1; 190127664Sbms rule_count++; 191127664Sbms } else 192127664Sbms *rules[index] = temprule; 193127664Sbms } 19475107Sfennerout: 195146768Ssam mtx_unlock(&ugidfw_mtx); 196127664Sbms if (ruleptr != NULL) 197127664Sbms FREE(ruleptr, M_MACBSDEXTENDED); 198147894Ssam if (req->oldptr && error == 0) 199127664Sbms error = SYSCTL_OUT(req, &temprule, sizeof(temprule)); 20075107Sfenner return (error); 20175107Sfenner} 20275107Sfenner 20375107SfennerSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW, 20475107Sfenner sysctl_rule, "BSD extended MAC rules"); 20575107Sfenner 20675107Sfennerstatic void 20775107Sfennerugidfw_init(struct mac_policy_conf *mpc) 20875107Sfenner{ 20975107Sfenner 21075107Sfenner mtx_init(&ugidfw_mtx, "mac_bsdextended lock", NULL, MTX_DEF); 21175107Sfenner} 21275107Sfenner 21375107Sfennerstatic void 21475107Sfennerugidfw_destroy(struct mac_policy_conf *mpc) 21575107Sfenner{ 21675107Sfenner 21798530Sfenner mtx_destroy(&ugidfw_mtx); 21898530Sfenner} 21998530Sfenner 22098530Sfennerstatic int 22198530Sfennerugidfw_rulecheck(struct mac_bsdextended_rule *rule, 22298530Sfenner struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) 22398530Sfenner{ 22475107Sfenner int match; 22575107Sfenner int i; 22675107Sfenner 227127664Sbms /* 228127664Sbms * Is there a subject match? 22975107Sfenner */ 230127664Sbms mtx_assert(&ugidfw_mtx, MA_OWNED); 23175107Sfenner if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) { 23275107Sfenner match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max && 233127664Sbms cred->cr_uid >= rule->mbr_subject.mbs_uid_min) || 23475107Sfenner (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max && 23575107Sfenner cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) || 23675107Sfenner (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max && 237127664Sbms cred->cr_svuid >= rule->mbr_subject.mbs_uid_min)); 238127664Sbms if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED) 23926175Sfenner match = !match; 24098530Sfenner if (!match) 24198530Sfenner return (0); 242127664Sbms } 243127664Sbms 24498530Sfenner if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { 24598530Sfenner match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && 246127664Sbms cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || 247127664Sbms (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && 248127664Sbms cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); 249127664Sbms if (!match) { 250127664Sbms for (i = 0; i < cred->cr_ngroups; i++) { 251127664Sbms if (cred->cr_groups[i] 252147894Ssam <= rule->mbr_subject.mbs_gid_max && 253147894Ssam cred->cr_groups[i] 254147894Ssam >= rule->mbr_subject.mbs_gid_min) { 255147894Ssam match = 1; 256147894Ssam break; 25726175Sfenner } 258147894Ssam } 259147894Ssam } 26098530Sfenner if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED) 26175107Sfenner match = !match; 26275107Sfenner if (!match) 26375107Sfenner return (0); 26475107Sfenner } 26575107Sfenner 26675107Sfenner if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) { 26775107Sfenner match = (cred->cr_prison != NULL && 26875107Sfenner cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison); 26975107Sfenner if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED) 27075107Sfenner match = !match; 27175107Sfenner if (!match) 27275107Sfenner return (0); 27375107Sfenner } 274127664Sbms 27575107Sfenner /* 27675107Sfenner * Is there an object match? 27775107Sfenner */ 27875107Sfenner if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) { 27975107Sfenner match = (vap->va_uid <= rule->mbr_object.mbo_uid_max && 28098530Sfenner vap->va_uid >= rule->mbr_object.mbo_uid_min); 28198530Sfenner if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED) 28298530Sfenner match = !match; 28398530Sfenner if (!match) 28498530Sfenner return (0); 28598530Sfenner } 286127664Sbms 28775107Sfenner if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) { 28875107Sfenner match = (vap->va_gid <= rule->mbr_object.mbo_gid_max && 28975107Sfenner vap->va_gid >= rule->mbr_object.mbo_gid_min); 29075107Sfenner if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED) 29175107Sfenner match = !match; 29275107Sfenner if (!match) 29375107Sfenner return (0); 29475107Sfenner } 29575107Sfenner 29675107Sfenner if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { 297127664Sbms match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid), 298127664Sbms &(rule->mbr_object.mbo_fsid), 299127664Sbms sizeof(rule->mbr_object.mbo_fsid)) == 0); 300127664Sbms if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) 30175107Sfenner match = !match; 30275107Sfenner if (!match) 303127664Sbms return (0); 30475107Sfenner } 30575107Sfenner 30675107Sfenner if (rule->mbr_object.mbo_flags & MBO_SUID) { 307127664Sbms match = (vap->va_mode & S_ISUID); 308127664Sbms if (rule->mbr_object.mbo_neg & MBO_SUID) 309127664Sbms match = !match; 310127664Sbms if (!match) 311127664Sbms return (0); 312127664Sbms } 313127664Sbms 314127664Sbms if (rule->mbr_object.mbo_flags & MBO_SGID) { 315127664Sbms match = (vap->va_mode & S_ISGID); 31675107Sfenner if (rule->mbr_object.mbo_neg & MBO_SGID) 31775107Sfenner match = !match; 318127664Sbms if (!match) 31975107Sfenner return (0); 32075107Sfenner } 321127664Sbms 322127664Sbms if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) { 32375107Sfenner match = (vap->va_uid == cred->cr_uid || 32475107Sfenner vap->va_uid == cred->cr_ruid || 32575107Sfenner vap->va_uid == cred->cr_svuid); 32675107Sfenner if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT) 32798530Sfenner match = !match; 32898530Sfenner if (!match) 32998530Sfenner return (0); 33098530Sfenner } 33198530Sfenner 33298530Sfenner if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) { 33398530Sfenner match = (groupmember(vap->va_gid, cred) || 33498530Sfenner vap->va_gid == cred->cr_rgid || 33598530Sfenner vap->va_gid == cred->cr_svgid); 33698530Sfenner if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT) 33798530Sfenner match = !match; 33898530Sfenner if (!match) 33998530Sfenner return (0); 34098530Sfenner } 34198530Sfenner 34298530Sfenner if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) { 34398530Sfenner switch (vap->va_type) { 34498530Sfenner case VREG: 34598530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_REG); 34698530Sfenner break; 34798530Sfenner case VDIR: 34898530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR); 34998530Sfenner break; 35098530Sfenner case VBLK: 35198530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK); 35298530Sfenner break; 35398530Sfenner case VCHR: 35498530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR); 35598530Sfenner break; 35698530Sfenner case VLNK: 35798530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK); 35898530Sfenner break; 35998530Sfenner case VSOCK: 36098530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK); 36198530Sfenner break; 36298530Sfenner case VFIFO: 36398530Sfenner match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO); 36498530Sfenner break; 36598530Sfenner default: 36698530Sfenner match = 0; 36798530Sfenner } 36898530Sfenner if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED) 36998530Sfenner match = !match; 37098530Sfenner if (!match) 37198530Sfenner return (0); 37298530Sfenner } 37398530Sfenner 37498530Sfenner /* 37598530Sfenner * Is the access permitted? 37698530Sfenner */ 37798530Sfenner if ((rule->mbr_mode & acc_mode) != acc_mode) { 37898530Sfenner if (ugidfw_logging) 37998530Sfenner log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d" 380127664Sbms " on %d:%d failed. \n", cred->cr_ruid, 38198530Sfenner cred->cr_rgid, acc_mode, vap->va_uid, 38298530Sfenner vap->va_gid); 38398530Sfenner return (EACCES); 38498530Sfenner } 38598530Sfenner 38698530Sfenner /* 38798530Sfenner * If the rule matched, permits access, and first match is enabled, 38898530Sfenner * return success. 38998530Sfenner */ 39098530Sfenner if (ugidfw_firstmatch_enabled) 39198530Sfenner return (EJUSTRETURN); 39298530Sfenner else 39398530Sfenner return (0); 39498530Sfenner} 39598530Sfenner 39698530Sfennerstatic int 39798530Sfennerugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, 39898530Sfenner int acc_mode) 39998530Sfenner{ 40098530Sfenner int error, i; 40198530Sfenner 40298530Sfenner /* 40398530Sfenner * XXXRW: More specific privilege selection needed. 40498530Sfenner */ 40598530Sfenner if (suser_cred(cred, 0) == 0) 40698530Sfenner return (0); 407127664Sbms 40898530Sfenner /* 40998530Sfenner * Since we do not separately handle append, map append to write. 41098530Sfenner */ 41198530Sfenner if (acc_mode & MBI_APPEND) { 412127664Sbms acc_mode &= ~MBI_APPEND; 413127664Sbms acc_mode |= MBI_WRITE; 414127664Sbms } 415127664Sbms mtx_lock(&ugidfw_mtx); 416127664Sbms for (i = 0; i < rule_slots; i++) { 417127664Sbms if (rules[i] == NULL) 418127664Sbms continue; 419146768Ssam error = ugidfw_rulecheck(rules[i], cred, 420127664Sbms vp, vap, acc_mode); 421147894Ssam if (error == EJUSTRETURN) 422127664Sbms break; 423127664Sbms if (error) { 424127664Sbms mtx_unlock(&ugidfw_mtx); 425127664Sbms return (error); 426127664Sbms } 427127664Sbms } 42875107Sfenner mtx_unlock(&ugidfw_mtx); 42926175Sfenner return (0); 43026175Sfenner} 43175107Sfenner 43275107Sfennerstatic int 43375107Sfennerugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) 434127664Sbms{ 43575107Sfenner int error; 436127664Sbms struct vattr vap; 437127664Sbms 43826175Sfenner if (!ugidfw_enabled) 43975107Sfenner return (0); 44075107Sfenner error = VOP_GETATTR(vp, &vap, cred); 44175107Sfenner if (error) 44275107Sfenner return (error); 44375107Sfenner return (ugidfw_check(cred, vp, &vap, acc_mode)); 44475107Sfenner} 44526175Sfenner 44675107Sfenner/* 447127664Sbms * Object-specific entry point implementations are sorted alphabetically by 44875107Sfenner * object type and then by operation. 44975107Sfenner */ 45075107Sfennerstatic int 45175107Sfennerugidfw_system_check_acct(struct ucred *cred, struct vnode *vp, 45275107Sfenner struct label *vplabel) 45375107Sfenner{ 45498530Sfenner 45575107Sfenner if (vp != NULL) 45675107Sfenner return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 45775107Sfenner else 45875107Sfenner return (0); 45975107Sfenner} 46075107Sfenner 46175107Sfennerstatic int 46275107Sfennerugidfw_system_check_auditctl(struct ucred *cred, struct vnode *vp, 46375107Sfenner struct label *vplabel) 46475107Sfenner{ 46526175Sfenner 46675107Sfenner if (vp != NULL) 46775107Sfenner return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 46875107Sfenner else 46975107Sfenner return (0); 47075107Sfenner} 47175107Sfenner 47275107Sfennerstatic int 47375107Sfennerugidfw_system_check_swapon(struct ucred *cred, struct vnode *vp, 47475107Sfenner struct label *vplabel) 47575107Sfenner{ 47675107Sfenner 47775107Sfenner return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 47875107Sfenner} 47975107Sfenner 48075107Sfennerstatic int 48175107Sfennerugidfw_vnode_check_access(struct ucred *cred, struct vnode *vp, 48275107Sfenner struct label *vplabel, int acc_mode) 48375107Sfenner{ 48475107Sfenner 48598530Sfenner return (ugidfw_check_vp(cred, vp, acc_mode)); 48626175Sfenner} 487127664Sbms 488127664Sbmsstatic int 489127664Sbmsugidfw_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, 490127664Sbms struct label *dvplabel) 491127664Sbms{ 492127664Sbms 493127664Sbms return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 494127664Sbms} 495127664Sbms 496127664Sbmsstatic int 497127664Sbmsugidfw_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, 498127664Sbms struct label *dvplabel) 49926175Sfenner{ 500127664Sbms 50198530Sfenner return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 502127664Sbms} 50375107Sfenner 50475107Sfennerstatic int 50526175Sfennerugidfw_check_create_vnode(struct ucred *cred, struct vnode *dvp, 50675107Sfenner struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 50726175Sfenner{ 50875107Sfenner 50975107Sfenner return (ugidfw_check_vp(cred, dvp, MBI_WRITE)); 51075107Sfenner} 51175107Sfenner 51275107Sfennerstatic int 51375107Sfennerugidfw_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 51475107Sfenner struct label *vplabel, acl_type_t type) 51526175Sfenner{ 51675107Sfenner 51726175Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 51875107Sfenner} 519147894Ssam 520147894Ssamstatic int 521147894Ssamugidfw_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 522147894Ssam struct label *vplabel, int attrnamespace, const char *name) 523147894Ssam{ 524147894Ssam 525147894Ssam return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 526147894Ssam} 527147894Ssam 528147894Ssamstatic int 529147894Ssamugidfw_vnode_check_exec(struct ucred *cred, struct vnode *vp, 530147894Ssam struct label *vplabel, struct image_params *imgp, 531147894Ssam struct label *execlabel) 532147894Ssam{ 533147894Ssam 534147894Ssam return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC)); 535147894Ssam} 536147894Ssam 537147894Ssamstatic int 538147894Ssamugidfw_vnode_check_getacl(struct ucred *cred, struct vnode *vp, 539147894Ssam struct label *vplabel, acl_type_t type) 540147894Ssam{ 541147894Ssam 542147894Ssam return (ugidfw_check_vp(cred, vp, MBI_STAT)); 543147894Ssam} 544147894Ssam 545147894Ssamstatic int 546147894Ssamugidfw_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 547147894Ssam struct label *vplabel, int attrnamespace, const char *name, 548147894Ssam struct uio *uio) 549147894Ssam{ 55075107Sfenner 55126175Sfenner return (ugidfw_check_vp(cred, vp, MBI_READ)); 55275107Sfenner} 55375107Sfenner 55475107Sfennerstatic int 55575107Sfennerugidfw_vnode_check_link(struct ucred *cred, struct vnode *dvp, 55675107Sfenner struct label *dvplabel, struct vnode *vp, struct label *label, 55775107Sfenner struct componentname *cnp) 55875107Sfenner{ 55975107Sfenner int error; 56075107Sfenner 56175107Sfenner error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 56226175Sfenner if (error) 56398530Sfenner return (error); 56426175Sfenner error = ugidfw_check_vp(cred, vp, MBI_WRITE); 56575107Sfenner if (error) 56675107Sfenner return (error); 56775107Sfenner return (0); 56875107Sfenner} 56975107Sfenner 57075107Sfennerstatic int 57175107Sfennerugidfw_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 57275107Sfenner struct label *vplabel, int attrnamespace) 57375107Sfenner{ 57426175Sfenner 57575107Sfenner return (ugidfw_check_vp(cred, vp, MBI_READ)); 57675107Sfenner} 57775107Sfenner 57826175Sfennerstatic int 57975107Sfennerugidfw_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, 58075107Sfenner struct label *dvplabel, struct componentname *cnp) 58175107Sfenner{ 58275107Sfenner 58375107Sfenner return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); 58475107Sfenner} 58575107Sfenner 58675107Sfennerstatic int 58775107Sfennerugidfw_vnode_check_open(struct ucred *cred, struct vnode *vp, 58875107Sfenner struct label *vplabel, int acc_mode) 58975107Sfenner{ 59075107Sfenner 59175107Sfenner return (ugidfw_check_vp(cred, vp, acc_mode)); 59275107Sfenner} 59375107Sfenner 59475107Sfennerstatic int 59575107Sfennerugidfw_vnode_check_readdir(struct ucred *cred, struct vnode *dvp, 59675107Sfenner struct label *dvplabel) 59775107Sfenner{ 59826175Sfenner 59975107Sfenner return (ugidfw_check_vp(cred, dvp, MBI_READ)); 60075107Sfenner} 60175107Sfenner 60275107Sfennerstatic int 60375107Sfennerugidfw_vnode_check_readdlink(struct ucred *cred, struct vnode *vp, 60475107Sfenner struct label *vplabel) 60575107Sfenner{ 60675107Sfenner 60726175Sfenner return (ugidfw_check_vp(cred, vp, MBI_READ)); 60875107Sfenner} 60975107Sfenner 61075107Sfennerstatic int 611127664Sbmsugidfw_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 612127664Sbms struct label *dvplabel, struct vnode *vp, struct label *vplabel, 61375107Sfenner struct componentname *cnp) 614127664Sbms{ 61575107Sfenner int error; 61675107Sfenner 61775107Sfenner error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 618127664Sbms if (error) 61975107Sfenner return (error); 620127664Sbms return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 62175107Sfenner} 62275107Sfenner 62375107Sfennerstatic int 62475107Sfennerugidfw_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 62575107Sfenner struct label *dvplabel, struct vnode *vp, struct label *vplabel, 62675107Sfenner int samedir, struct componentname *cnp) 62775107Sfenner{ 62875107Sfenner int error; 62975107Sfenner 630127664Sbms error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 63175107Sfenner if (error) 632127664Sbms return (error); 633127664Sbms if (vp != NULL) 63475107Sfenner error = ugidfw_check_vp(cred, vp, MBI_WRITE); 63575107Sfenner return (error); 63675107Sfenner} 63775107Sfenner 63875107Sfennerstatic int 63975107Sfennerugidfw_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 64075107Sfenner struct label *vplabel) 64175107Sfenner{ 64275107Sfenner 64375107Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 64475107Sfenner} 64575107Sfenner 64675107Sfennerstatic int 64775107Sfennerugidfw_check_setacl_vnode(struct ucred *cred, struct vnode *vp, 64898530Sfenner struct label *vplabel, acl_type_t type, struct acl *acl) 64975107Sfenner{ 65075107Sfenner 65175107Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 65275107Sfenner} 65375107Sfenner 65475107Sfennerstatic int 65575107Sfennerugidfw_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 65675107Sfenner struct label *vplabel, int attrnamespace, const char *name, 65775107Sfenner struct uio *uio) 65875107Sfenner{ 65975107Sfenner 66075107Sfenner return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 66175107Sfenner} 66275107Sfenner 66375107Sfennerstatic int 66475107Sfennerugidfw_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 66575107Sfenner struct label *vplabel, u_long flags) 66698530Sfenner{ 66798530Sfenner 66898530Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 66998530Sfenner} 67098530Sfenner 67198530Sfennerstatic int 67298530Sfennerugidfw_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 67398530Sfenner struct label *vplabel, mode_t mode) 67498530Sfenner{ 67598530Sfenner 67698530Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 67798530Sfenner} 67898530Sfenner 67998530Sfennerstatic int 68098530Sfennerugidfw_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 68198530Sfenner struct label *vplabel, uid_t uid, gid_t gid) 68298530Sfenner{ 68398530Sfenner 68498530Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 68598530Sfenner} 68698530Sfenner 68798530Sfennerstatic int 68898530Sfennerugidfw_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 68998530Sfenner struct label *vplabel, struct timespec atime, struct timespec utime) 69098530Sfenner{ 69198530Sfenner 69298530Sfenner return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); 69398530Sfenner} 69498530Sfenner 69598530Sfennerstatic int 69698530Sfennerugidfw_vnode_check_stat(struct ucred *active_cred, 69798530Sfenner struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 69898530Sfenner{ 69975107Sfenner 70075107Sfenner return (ugidfw_check_vp(active_cred, vp, MBI_STAT)); 70198530Sfenner} 70298530Sfenner 70398530Sfennerstatic int 70475107Sfennerugidfw_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 70526175Sfenner struct label *dvplabel, struct vnode *vp, struct label *vplabel, 70626175Sfenner struct componentname *cnp) 707146768Ssam{ 708146768Ssam int error; 709146768Ssam 710146768Ssam error = ugidfw_check_vp(cred, dvp, MBI_WRITE); 711146768Ssam if (error) 712146768Ssam return (error); 713146768Ssam return (ugidfw_check_vp(cred, vp, MBI_WRITE)); 714146768Ssam} 715146768Ssam 716146768Ssamstatic struct mac_policy_ops ugidfw_ops = 717146768Ssam{ 718146768Ssam .mpo_destroy = ugidfw_destroy, 719146768Ssam .mpo_init = ugidfw_init, 720146768Ssam .mpo_system_check_acct = ugidfw_system_check_acct, 721146768Ssam .mpo_system_check_auditctl = ugidfw_system_check_auditctl, 722146768Ssam .mpo_system_check_swapon = ugidfw_system_check_swapon, 723146768Ssam .mpo_vnode_check_access = ugidfw_vnode_check_access, 724146768Ssam .mpo_vnode_check_chdir = ugidfw_vnode_check_chdir, 725146768Ssam .mpo_vnode_check_chroot = ugidfw_vnode_check_chroot, 726146768Ssam .mpo_vnode_check_create = ugidfw_check_create_vnode, 727146768Ssam .mpo_vnode_check_deleteacl = ugidfw_vnode_check_deleteacl, 728146768Ssam .mpo_vnode_check_deleteextattr = ugidfw_vnode_check_deleteextattr, 729146768Ssam .mpo_vnode_check_exec = ugidfw_vnode_check_exec, 730146768Ssam .mpo_vnode_check_getacl = ugidfw_vnode_check_getacl, 731146768Ssam .mpo_vnode_check_getextattr = ugidfw_vnode_check_getextattr, 732146768Ssam .mpo_vnode_check_link = ugidfw_vnode_check_link, 733146768Ssam .mpo_vnode_check_listextattr = ugidfw_vnode_check_listextattr, 734146768Ssam .mpo_vnode_check_lookup = ugidfw_vnode_check_lookup, 735146768Ssam .mpo_vnode_check_open = ugidfw_vnode_check_open, 736146768Ssam .mpo_vnode_check_readdir = ugidfw_vnode_check_readdir, 737146768Ssam .mpo_vnode_check_readlink = ugidfw_vnode_check_readdlink, 738146768Ssam .mpo_vnode_check_rename_from = ugidfw_vnode_check_rename_from, 739146768Ssam .mpo_vnode_check_rename_to = ugidfw_vnode_check_rename_to, 740146768Ssam .mpo_vnode_check_revoke = ugidfw_vnode_check_revoke, 741146768Ssam .mpo_vnode_check_setacl = ugidfw_check_setacl_vnode, 742146768Ssam .mpo_vnode_check_setextattr = ugidfw_vnode_check_setextattr, 743146768Ssam .mpo_vnode_check_setflags = ugidfw_vnode_check_setflags, 744146768Ssam .mpo_vnode_check_setmode = ugidfw_vnode_check_setmode, 745146768Ssam .mpo_vnode_check_setowner = ugidfw_vnode_check_setowner, 746146768Ssam .mpo_vnode_check_setutimes = ugidfw_vnode_check_setutimes, 747146768Ssam .mpo_vnode_check_stat = ugidfw_vnode_check_stat, 748146768Ssam .mpo_vnode_check_unlink = ugidfw_vnode_check_unlink, 749146768Ssam}; 75075107Sfenner 75175107SfennerMAC_POLICY_SET(&ugidfw_ops, mac_bsdextended, "TrustedBSD MAC/BSD Extended", 75298530Sfenner MPC_LOADTIME_FLAG_UNLOADOK, NULL, 0); 75398530Sfenner