mac_vfs.c revision 162467
1112918Sjeff/*- 2112918Sjeff * Copyright (c) 1999-2002 Robert N. M. Watson 3112918Sjeff * Copyright (c) 2001 Ilmar S. Habibulin 4112918Sjeff * Copyright (c) 2001-2005 McAfee, Inc. 5112918Sjeff * Copyright (c) 2005 SPARTA, Inc. 6112918Sjeff * All rights reserved. 7112918Sjeff * 8112918Sjeff * This software was developed by Robert Watson and Ilmar Habibulin for the 9112918Sjeff * TrustedBSD Project. 10112918Sjeff * 11112918Sjeff * This software was developed for the FreeBSD Project in part by McAfee 12112918Sjeff * Research, the Security Research Division of McAfee, Inc. under 13112918Sjeff * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 14112918Sjeff * CHATS research program. 15112918Sjeff * 16112918Sjeff * This software was enhanced by SPARTA ISSO under SPAWAR contract 17112918Sjeff * N66001-04-C-6019 ("SEFOS"). 18112918Sjeff * 19112918Sjeff * Redistribution and use in source and binary forms, with or without 20112918Sjeff * modification, are permitted provided that the following conditions 21112918Sjeff * are met: 22112918Sjeff * 1. Redistributions of source code must retain the above copyright 23112918Sjeff * notice, this list of conditions and the following disclaimer. 24112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 25112918Sjeff * notice, this list of conditions and the following disclaimer in the 26112918Sjeff * documentation and/or other materials provided with the distribution. 27112918Sjeff * 28112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31112918Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38112918Sjeff * SUCH DAMAGE. 39112918Sjeff */ 40112918Sjeff 41112918Sjeff#include <sys/cdefs.h> 42112918Sjeff__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 162467 2006-09-20 13:33:41Z rwatson $"); 43112918Sjeff 44112918Sjeff#include "opt_mac.h" 45112918Sjeff 46112918Sjeff#include <sys/param.h> 47112918Sjeff#include <sys/condvar.h> 48112918Sjeff#include <sys/extattr.h> 49112918Sjeff#include <sys/imgact.h> 50112918Sjeff#include <sys/kernel.h> 51112918Sjeff#include <sys/lock.h> 52112918Sjeff#include <sys/malloc.h> 53112918Sjeff#include <sys/mutex.h> 54112918Sjeff#include <sys/mac.h> 55112918Sjeff#include <sys/proc.h> 56112918Sjeff#include <sys/sbuf.h> 57112918Sjeff#include <sys/systm.h> 58112918Sjeff#include <sys/vnode.h> 59112918Sjeff#include <sys/mount.h> 60112918Sjeff#include <sys/file.h> 61112918Sjeff#include <sys/namei.h> 62112918Sjeff#include <sys/sysctl.h> 63112918Sjeff 64112918Sjeff#include <vm/vm.h> 65112918Sjeff#include <vm/pmap.h> 66112918Sjeff#include <vm/vm_map.h> 67112918Sjeff#include <vm/vm_object.h> 68112918Sjeff 69112918Sjeff#include <sys/mac_policy.h> 70112918Sjeff 71112918Sjeff#include <fs/devfs/devfs.h> 72135301Smtm 73112918Sjeff#include <security/mac/mac_internal.h> 74112918Sjeff 75112918Sjeff/* 76112918Sjeff * Warn about EA transactions only the first time they happen. 77112918Sjeff * Weak coherency, no locking. 78112918Sjeff */ 79112918Sjeffstatic int ea_warn_once = 0; 80112918Sjeff 81112918Sjeffstatic int mac_enforce_fs = 1; 82112918SjeffSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 83112918Sjeff &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 84135301SmtmTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 85112918Sjeff 86112918Sjeffstatic int mac_setlabel_vnode_extattr(struct ucred *cred, 87112918Sjeff struct vnode *vp, struct label *intlabel); 88112918Sjeff 89112918Sjeffstatic struct label * 90112918Sjeffmac_devfsdirent_label_alloc(void) 91112918Sjeff{ 92112918Sjeff struct label *label; 93112918Sjeff 94112918Sjeff label = mac_labelzone_alloc(M_WAITOK); 95131181Smtm MAC_PERFORM(init_devfsdirent_label, label); 96131181Smtm return (label); 97115260Smtm} 98115260Smtm 99115260Smtmvoid 100115260Smtmmac_init_devfsdirent(struct devfs_dirent *de) 101123348Smtm{ 102115260Smtm 103115260Smtm de->de_label = mac_devfsdirent_label_alloc(); 104115260Smtm} 105123347Smtm 106115260Smtmstatic struct label * 107115260Smtmmac_mount_label_alloc(void) 108135301Smtm{ 109135301Smtm struct label *label; 110135301Smtm 111135301Smtm label = mac_labelzone_alloc(M_WAITOK); 112135301Smtm MAC_PERFORM(init_mount_label, label); 113135301Smtm return (label); 114135301Smtm} 115135301Smtm 116135301Smtmstatic struct label * 117135301Smtmmac_mount_fs_label_alloc(void) 118135301Smtm{ 119135301Smtm struct label *label; 120135301Smtm 121112918Sjeff label = mac_labelzone_alloc(M_WAITOK); 122112918Sjeff MAC_PERFORM(init_mount_fs_label, label); 123112918Sjeff return (label); 124112918Sjeff} 125112918Sjeff 126112918Sjeffvoid 127112918Sjeffmac_init_mount(struct mount *mp) 128112918Sjeff{ 129112918Sjeff 130112918Sjeff mp->mnt_mntlabel = mac_mount_label_alloc(); 131112918Sjeff mp->mnt_fslabel = mac_mount_fs_label_alloc(); 132112918Sjeff} 133112918Sjeff 134112918Sjeffstruct label * 135112918Sjeffmac_vnode_label_alloc(void) 136123347Smtm{ 137112918Sjeff struct label *label; 138112918Sjeff 139123347Smtm label = mac_labelzone_alloc(M_WAITOK); 140112918Sjeff MAC_PERFORM(init_vnode_label, label); 141112918Sjeff return (label); 142112918Sjeff} 143112918Sjeff 144112918Sjeffvoid 145112918Sjeffmac_init_vnode(struct vnode *vp) 146112918Sjeff{ 147112918Sjeff 148112918Sjeff vp->v_label = mac_vnode_label_alloc(); 149135301Smtm} 150135301Smtm 151135301Smtmstatic void 152135301Smtmmac_devfsdirent_label_free(struct label *label) 153135301Smtm{ 154135301Smtm 155135301Smtm MAC_PERFORM(destroy_devfsdirent_label, label); 156135301Smtm mac_labelzone_free(label); 157135301Smtm} 158135301Smtm 159135301Smtmvoid 160135301Smtmmac_destroy_devfsdirent(struct devfs_dirent *de) 161135301Smtm{ 162135301Smtm 163123347Smtm mac_devfsdirent_label_free(de->de_label); 164112918Sjeff de->de_label = NULL; 165112918Sjeff} 166123347Smtm 167112918Sjeffstatic void 168112918Sjeffmac_mount_label_free(struct label *label) 169112918Sjeff{ 170112918Sjeff 171112918Sjeff MAC_PERFORM(destroy_mount_label, label); 172112918Sjeff mac_labelzone_free(label); 173112918Sjeff} 174112918Sjeff 175112918Sjeffstatic void 176112918Sjeffmac_mount_fs_label_free(struct label *label) 177123347Smtm{ 178112918Sjeff 179112918Sjeff MAC_PERFORM(destroy_mount_fs_label, label); 180123347Smtm mac_labelzone_free(label); 181112918Sjeff} 182112918Sjeff 183112918Sjeffvoid 184112918Sjeffmac_destroy_mount(struct mount *mp) 185112918Sjeff{ 186112918Sjeff 187112918Sjeff mac_mount_fs_label_free(mp->mnt_fslabel); 188112918Sjeff mp->mnt_fslabel = NULL; 189112918Sjeff mac_mount_label_free(mp->mnt_mntlabel); 190112918Sjeff mp->mnt_mntlabel = NULL; 191112918Sjeff} 192112918Sjeff 193112918Sjeffvoid 194112918Sjeffmac_vnode_label_free(struct label *label) 195112918Sjeff{ 196112918Sjeff 197112918Sjeff MAC_PERFORM(destroy_vnode_label, label); 198112918Sjeff mac_labelzone_free(label); 199112918Sjeff} 200112918Sjeff 201112918Sjeffvoid 202112918Sjeffmac_destroy_vnode(struct vnode *vp) 203112918Sjeff{ 204112918Sjeff 205112918Sjeff mac_vnode_label_free(vp->v_label); 206112918Sjeff vp->v_label = NULL; 207112918Sjeff} 208131181Smtm 209131181Smtmvoid 210131181Smtmmac_copy_vnode_label(struct label *src, struct label *dest) 211131181Smtm{ 212131181Smtm 213131181Smtm MAC_PERFORM(copy_vnode_label, src, dest); 214131181Smtm} 215131181Smtm 216131181Smtmint 217131181Smtmmac_externalize_vnode_label(struct label *label, char *elements, 218131181Smtm char *outbuf, size_t outbuflen) 219131181Smtm{ 220131181Smtm int error; 221131181Smtm 222131181Smtm MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); 223131181Smtm 224131181Smtm return (error); 225131181Smtm} 226131181Smtm 227131181Smtmint 228131181Smtmmac_internalize_vnode_label(struct label *label, char *string) 229131181Smtm{ 230131181Smtm int error; 231131181Smtm 232131181Smtm MAC_INTERNALIZE(vnode, label, string); 233131181Smtm 234131181Smtm return (error); 235131181Smtm} 236131181Smtm 237131181Smtmvoid 238131181Smtmmac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 239131181Smtm struct vnode *vp) 240131181Smtm{ 241131181Smtm 242131181Smtm MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp, 243131181Smtm vp->v_label); 244131181Smtm} 245131181Smtm 246131181Smtmvoid 247131181Smtmmac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 248131181Smtm struct vnode *vp) 249131181Smtm{ 250131181Smtm 251131181Smtm MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de, 252131181Smtm de->de_label, vp, vp->v_label); 253131181Smtm} 254131181Smtm 255131181Smtmint 256131181Smtmmac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 257131181Smtm{ 258131181Smtm int error; 259131181Smtm 260131181Smtm ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 261131181Smtm 262131181Smtm MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp, 263131181Smtm vp->v_label); 264123347Smtm 265112918Sjeff return (error); 266112918Sjeff} 267123347Smtm 268112918Sjeffvoid 269112918Sjeffmac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 270112918Sjeff{ 271112918Sjeff 272112918Sjeff MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp, 273112918Sjeff vp->v_label); 274112918Sjeff} 275112918Sjeff 276112918Sjeffint 277112918Sjeffmac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 278135301Smtm struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 279135301Smtm{ 280135301Smtm int error; 281135301Smtm 282135301Smtm ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 283135301Smtm ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 284135301Smtm 285135301Smtm error = VOP_OPENEXTATTR(vp, cred, curthread); 286135301Smtm if (error == EOPNOTSUPP) { 287135301Smtm /* XXX: Optionally abort if transactions not supported. */ 288135301Smtm if (ea_warn_once == 0) { 289135301Smtm printf("Warning: transactions not supported " 290135301Smtm "in EA write.\n"); 291135301Smtm ea_warn_once = 1; 292135301Smtm } 293135301Smtm } else if (error) 294135301Smtm return (error); 295135301Smtm 296135301Smtm MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel, 297135301Smtm dvp, dvp->v_label, vp, vp->v_label, cnp); 298135301Smtm 299135301Smtm if (error) { 300135301Smtm VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 301135301Smtm return (error); 302135301Smtm } 303135301Smtm 304123347Smtm error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 305112918Sjeff 306112918Sjeff if (error == EOPNOTSUPP) 307123347Smtm error = 0; /* XXX */ 308112918Sjeff 309112918Sjeff return (error); 310112918Sjeff} 311112918Sjeff 312112918Sjeffstatic int 313112918Sjeffmac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 314112918Sjeff struct label *intlabel) 315112918Sjeff{ 316112918Sjeff int error; 317112918Sjeff 318112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 319112918Sjeff 320112918Sjeff error = VOP_OPENEXTATTR(vp, cred, curthread); 321112918Sjeff if (error == EOPNOTSUPP) { 322112918Sjeff /* XXX: Optionally abort if transactions not supported. */ 323112918Sjeff if (ea_warn_once == 0) { 324112918Sjeff printf("Warning: transactions not supported " 325112918Sjeff "in EA write.\n"); 326112918Sjeff ea_warn_once = 1; 327112918Sjeff } 328112918Sjeff } else if (error) 329112918Sjeff return (error); 330112918Sjeff 331112918Sjeff MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel); 332112918Sjeff 333123347Smtm if (error) { 334112918Sjeff VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 335112918Sjeff return (error); 336123347Smtm } 337112918Sjeff 338112918Sjeff error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 339112918Sjeff 340112918Sjeff if (error == EOPNOTSUPP) 341112918Sjeff error = 0; /* XXX */ 342112918Sjeff 343112918Sjeff return (error); 344112918Sjeff} 345112918Sjeff 346112918Sjeffvoid 347112918Sjeffmac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 348112918Sjeff struct label *interpvnodelabel, struct image_params *imgp) 349112918Sjeff{ 350112918Sjeff 351112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 352112918Sjeff 353112918Sjeff if (!mac_enforce_process && !mac_enforce_fs) 354112918Sjeff return; 355112918Sjeff 356112918Sjeff MAC_PERFORM(execve_transition, old, new, vp, vp->v_label, 357112918Sjeff interpvnodelabel, imgp, imgp->execlabel); 358135301Smtm} 359135301Smtm 360135301Smtmint 361135301Smtmmac_execve_will_transition(struct ucred *old, struct vnode *vp, 362135301Smtm struct label *interpvnodelabel, struct image_params *imgp) 363135301Smtm{ 364135301Smtm int result; 365135301Smtm 366135301Smtm ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 367135301Smtm 368135301Smtm if (!mac_enforce_process && !mac_enforce_fs) 369135301Smtm return (0); 370135301Smtm 371135301Smtm result = 0; 372135301Smtm MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label, 373135301Smtm interpvnodelabel, imgp, imgp->execlabel); 374123347Smtm 375112918Sjeff return (result); 376112918Sjeff} 377123347Smtm 378112918Sjeffint 379112918Sjeffmac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 380112918Sjeff{ 381112918Sjeff int error; 382112918Sjeff 383112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 384112918Sjeff 385112918Sjeff if (!mac_enforce_fs) 386112918Sjeff return (0); 387112918Sjeff 388135301Smtm MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode); 389135301Smtm return (error); 390135301Smtm} 391135301Smtm 392135301Smtmint 393135301Smtmmac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 394135301Smtm{ 395135301Smtm int error; 396135301Smtm 397135301Smtm ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 398135301Smtm 399135301Smtm if (!mac_enforce_fs) 400135301Smtm return (0); 401135301Smtm 402135301Smtm MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label); 403135301Smtm return (error); 404135301Smtm} 405135301Smtm 406112918Sjeffint 407112918Sjeffmac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 408112918Sjeff{ 409112918Sjeff int error; 410112918Sjeff 411112918Sjeff ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 412112918Sjeff 413112918Sjeff if (!mac_enforce_fs) 414112918Sjeff return (0); 415112918Sjeff 416112918Sjeff MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label); 417112918Sjeff return (error); 418112918Sjeff} 419112918Sjeff 420112918Sjeffint 421135301Smtmmac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 422112918Sjeff struct componentname *cnp, struct vattr *vap) 423135301Smtm{ 424135301Smtm int error; 425135301Smtm 426135301Smtm ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 427135301Smtm 428135301Smtm if (!mac_enforce_fs) 429135301Smtm return (0); 430135301Smtm 431135301Smtm MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap); 432135301Smtm return (error); 433135301Smtm} 434135301Smtm 435135301Smtmint 436135301Smtmmac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 437135301Smtm struct componentname *cnp) 438135301Smtm{ 439127486Smtm int error; 440127486Smtm 441127486Smtm ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 442127486Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 443127486Smtm 444127486Smtm if (!mac_enforce_fs) 445127486Smtm return (0); 446127486Smtm 447127486Smtm MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp, 448127486Smtm vp->v_label, cnp); 449127486Smtm return (error); 450127486Smtm} 451127486Smtm 452127486Smtmint 453127486Smtmmac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 454123347Smtm acl_type_t type) 455112918Sjeff{ 456112918Sjeff int error; 457123347Smtm 458112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 459112918Sjeff 460112918Sjeff if (!mac_enforce_fs) 461112918Sjeff return (0); 462112918Sjeff 463112918Sjeff MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type); 464112918Sjeff return (error); 465112918Sjeff} 466112918Sjeff 467112918Sjeffint 468123347Smtmmac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 469112918Sjeff int attrnamespace, const char *name) 470112918Sjeff{ 471123347Smtm int error; 472112918Sjeff 473112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr"); 474112918Sjeff 475112918Sjeff if (!mac_enforce_fs) 476112918Sjeff return (0); 477112918Sjeff 478112918Sjeff MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label, 479112918Sjeff attrnamespace, name); 480112918Sjeff return (error); 481112918Sjeff} 482135301Smtm 483135301Smtmint 484135301Smtmmac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 485135301Smtm struct image_params *imgp) 486135301Smtm{ 487135301Smtm int error; 488135301Smtm 489135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 490135301Smtm 491135301Smtm if (!mac_enforce_process && !mac_enforce_fs) 492135301Smtm return (0); 493135301Smtm 494135301Smtm MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp, 495135301Smtm imgp->execlabel); 496135301Smtm 497135301Smtm return (error); 498135301Smtm} 499135301Smtm 500135301Smtmint 501135301Smtmmac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 502135301Smtm{ 503135301Smtm int error; 504135301Smtm 505135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 506135301Smtm 507135301Smtm if (!mac_enforce_fs) 508135301Smtm return (0); 509135301Smtm 510135301Smtm MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type); 511135301Smtm return (error); 512135301Smtm} 513135301Smtm 514135301Smtmint 515135301Smtmmac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 516135301Smtm int attrnamespace, const char *name, struct uio *uio) 517135301Smtm{ 518135301Smtm int error; 519135301Smtm 520135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 521135301Smtm 522135301Smtm if (!mac_enforce_fs) 523135301Smtm return (0); 524135301Smtm 525135301Smtm MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label, 526135301Smtm attrnamespace, name, uio); 527135301Smtm return (error); 528123347Smtm} 529112918Sjeff 530112918Sjeffint 531123347Smtmmac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 532112918Sjeff struct vnode *vp, struct componentname *cnp) 533112918Sjeff{ 534112918Sjeff int error; 535112918Sjeff 536112918Sjeff ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 537112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 538112918Sjeff 539112918Sjeff if (!mac_enforce_fs) 540112918Sjeff return (0); 541112918Sjeff 542112918Sjeff MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp, 543135301Smtm vp->v_label, cnp); 544135301Smtm return (error); 545135301Smtm} 546135301Smtm 547135301Smtmint 548135301Smtmmac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 549135301Smtm int attrnamespace) 550135301Smtm{ 551135301Smtm int error; 552135301Smtm 553135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr"); 554135301Smtm 555135301Smtm if (!mac_enforce_fs) 556135301Smtm return (0); 557135301Smtm 558135301Smtm MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label, 559135301Smtm attrnamespace); 560135301Smtm return (error); 561135301Smtm} 562135301Smtm 563135301Smtmint 564135301Smtmmac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 565135301Smtm struct componentname *cnp) 566135301Smtm{ 567135301Smtm int error; 568135301Smtm 569135301Smtm ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 570135301Smtm 571135301Smtm if (!mac_enforce_fs) 572135301Smtm return (0); 573135301Smtm 574135301Smtm MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp); 575135301Smtm return (error); 576135301Smtm} 577135301Smtm 578135301Smtmint 579135301Smtmmac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, 580135301Smtm int prot, int flags) 581135301Smtm{ 582135301Smtm int error; 583135301Smtm 584135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 585135301Smtm 586135301Smtm if (!mac_enforce_fs || !mac_enforce_vm) 587135301Smtm return (0); 588135301Smtm 589135301Smtm MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags); 590135301Smtm return (error); 591135301Smtm} 592135301Smtm 593135301Smtmvoid 594135301Smtmmac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 595135301Smtm{ 596135301Smtm int result = *prot; 597135301Smtm 598135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 599135301Smtm 600135301Smtm if (!mac_enforce_fs || !mac_enforce_vm) 601135301Smtm return; 602135301Smtm 603135301Smtm MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label, 604135301Smtm &result); 605135301Smtm 606135301Smtm *prot = result; 607135301Smtm} 608135301Smtm 609135301Smtmint 610135301Smtmmac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 611135301Smtm{ 612135301Smtm int error; 613135301Smtm 614135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 615135301Smtm 616135301Smtm if (!mac_enforce_fs || !mac_enforce_vm) 617135301Smtm return (0); 618135301Smtm 619135301Smtm MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot); 620135301Smtm return (error); 621135301Smtm} 622135301Smtm 623135301Smtmint 624135301Smtmmac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 625135301Smtm{ 626135301Smtm int error; 627135301Smtm 628135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 629135301Smtm 630135301Smtm if (!mac_enforce_fs) 631135301Smtm return (0); 632135301Smtm 633135301Smtm MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode); 634135301Smtm return (error); 635135301Smtm} 636135301Smtm 637135301Smtmint 638135301Smtmmac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 639135301Smtm struct vnode *vp) 640135301Smtm{ 641135301Smtm int error; 642135301Smtm 643135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 644135301Smtm 645135301Smtm if (!mac_enforce_fs) 646135301Smtm return (0); 647135301Smtm 648135301Smtm MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 649135301Smtm vp->v_label); 650135301Smtm 651135301Smtm return (error); 652135301Smtm} 653135301Smtm 654135301Smtmint 655135301Smtmmac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 656135301Smtm struct vnode *vp) 657135301Smtm{ 658135301Smtm int error; 659135301Smtm 660112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 661112918Sjeff 662112918Sjeff if (!mac_enforce_fs) 663112918Sjeff return (0); 664112918Sjeff 665112918Sjeff MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 666112918Sjeff vp->v_label); 667112918Sjeff 668112918Sjeff return (error); 669112918Sjeff} 670112918Sjeff 671112918Sjeffint 672112918Sjeffmac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 673112918Sjeff{ 674112918Sjeff int error; 675112918Sjeff 676112918Sjeff ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 677112918Sjeff 678112918Sjeff if (!mac_enforce_fs) 679112918Sjeff return (0); 680112918Sjeff 681112918Sjeff MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label); 682112918Sjeff return (error); 683112918Sjeff} 684112918Sjeff 685112918Sjeffint 686112918Sjeffmac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 687112918Sjeff{ 688112918Sjeff int error; 689112918Sjeff 690112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 691112918Sjeff 692112918Sjeff if (!mac_enforce_fs) 693112918Sjeff return (0); 694112918Sjeff 695112918Sjeff MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label); 696112918Sjeff return (error); 697112918Sjeff} 698112918Sjeff 699112918Sjeffstatic int 700112918Sjeffmac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 701112918Sjeff struct label *newlabel) 702112918Sjeff{ 703135301Smtm int error; 704135301Smtm 705135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 706135301Smtm 707135301Smtm MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel); 708135301Smtm 709135301Smtm return (error); 710135301Smtm} 711135301Smtm 712135301Smtmint 713135301Smtmmac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 714135301Smtm struct vnode *vp, struct componentname *cnp) 715135301Smtm{ 716135301Smtm int error; 717135301Smtm 718135301Smtm ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 719135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 720135301Smtm 721135301Smtm if (!mac_enforce_fs) 722112918Sjeff return (0); 723112918Sjeff 724112918Sjeff MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp, 725112918Sjeff vp->v_label, cnp); 726112918Sjeff return (error); 727112918Sjeff} 728112918Sjeff 729112918Sjeffint 730112918Sjeffmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 731112918Sjeff struct vnode *vp, int samedir, struct componentname *cnp) 732112918Sjeff{ 733112918Sjeff int error; 734112918Sjeff 735112918Sjeff ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 736123347Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 737112918Sjeff 738112918Sjeff if (!mac_enforce_fs) 739123347Smtm return (0); 740112918Sjeff 741112918Sjeff MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp, 742112918Sjeff vp != NULL ? vp->v_label : NULL, samedir, cnp); 743112918Sjeff return (error); 744123347Smtm} 745112918Sjeff 746112918Sjeffint 747112918Sjeffmac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 748112918Sjeff{ 749112918Sjeff int error; 750135301Smtm 751135301Smtm ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 752135301Smtm 753135301Smtm if (!mac_enforce_fs) 754112918Sjeff return (0); 755112918Sjeff 756112918Sjeff MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label); 757112918Sjeff return (error); 758112918Sjeff} 759112918Sjeff 760112918Sjeffint 761112918Sjeffmac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 762112918Sjeff struct acl *acl) 763112918Sjeff{ 764112918Sjeff int error; 765112918Sjeff 766112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 767135301Smtm 768112918Sjeff if (!mac_enforce_fs) 769123347Smtm return (0); 770112918Sjeff 771112918Sjeff MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl); 772123347Smtm return (error); 773112918Sjeff} 774112918Sjeff 775112918Sjeffint 776112918Sjeffmac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 777112918Sjeff int attrnamespace, const char *name, struct uio *uio) 778112918Sjeff{ 779112918Sjeff int error; 780112918Sjeff 781112918Sjeff ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 782112918Sjeff 783123347Smtm if (!mac_enforce_fs) 784112918Sjeff return (0); 785112918Sjeff 786123347Smtm MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label, 787112918Sjeff attrnamespace, name, uio); 788112918Sjeff return (error); 789112918Sjeff} 790112918Sjeff 791112918Sjeffint 792112918Sjeffmac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 793112918Sjeff{ 794112918Sjeff int error; 795112918Sjeff 796 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 797 798 if (!mac_enforce_fs) 799 return (0); 800 801 MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags); 802 return (error); 803} 804 805int 806mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 807{ 808 int error; 809 810 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 811 812 if (!mac_enforce_fs) 813 return (0); 814 815 MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode); 816 return (error); 817} 818 819int 820mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 821 gid_t gid) 822{ 823 int error; 824 825 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 826 827 if (!mac_enforce_fs) 828 return (0); 829 830 MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid); 831 return (error); 832} 833 834int 835mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 836 struct timespec atime, struct timespec mtime) 837{ 838 int error; 839 840 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 841 842 if (!mac_enforce_fs) 843 return (0); 844 845 MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime, 846 mtime); 847 return (error); 848} 849 850int 851mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 852 struct vnode *vp) 853{ 854 int error; 855 856 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 857 858 if (!mac_enforce_fs) 859 return (0); 860 861 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 862 vp->v_label); 863 return (error); 864} 865 866int 867mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 868 struct vnode *vp) 869{ 870 int error; 871 872 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 873 874 if (!mac_enforce_fs) 875 return (0); 876 877 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 878 vp->v_label); 879 880 return (error); 881} 882 883void 884mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 885{ 886 887 MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel); 888} 889 890void 891mac_create_mount(struct ucred *cred, struct mount *mp) 892{ 893 894 MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel, 895 mp->mnt_fslabel); 896} 897 898int 899mac_check_mount_stat(struct ucred *cred, struct mount *mount) 900{ 901 int error; 902 903 if (!mac_enforce_fs) 904 return (0); 905 906 MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel); 907 908 return (error); 909} 910 911void 912mac_create_devfs_device(struct ucred *cred, struct mount *mp, 913 struct cdev *dev, struct devfs_dirent *de) 914{ 915 916 MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label); 917} 918 919void 920mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 921 struct devfs_dirent *dd, struct devfs_dirent *de) 922{ 923 924 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de, 925 de->de_label); 926} 927 928void 929mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 930 struct devfs_dirent *de) 931{ 932 933 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 934 de->de_label); 935} 936 937/* 938 * Implementation of VOP_SETLABEL() that relies on extended attributes 939 * to store label data. Can be referenced by filesystems supporting 940 * extended attributes. 941 */ 942int 943vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 944{ 945 struct vnode *vp = ap->a_vp; 946 struct label *intlabel = ap->a_label; 947 int error; 948 949 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 950 951 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 952 return (EOPNOTSUPP); 953 954 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 955 if (error) 956 return (error); 957 958 mac_relabel_vnode(ap->a_cred, vp, intlabel); 959 960 return (0); 961} 962 963int 964vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 965{ 966 int error; 967 968 if (vp->v_mount == NULL) { 969 /* printf("vn_setlabel: null v_mount\n"); */ 970 if (vp->v_type != VNON) 971 printf("vn_setlabel: null v_mount with non-VNON\n"); 972 return (EBADF); 973 } 974 975 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 976 return (EOPNOTSUPP); 977 978 /* 979 * Multi-phase commit. First check the policies to confirm the 980 * change is OK. Then commit via the filesystem. Finally, 981 * update the actual vnode label. Question: maybe the filesystem 982 * should update the vnode at the end as part of VOP_SETLABEL()? 983 */ 984 error = mac_check_vnode_relabel(cred, vp, intlabel); 985 if (error) 986 return (error); 987 988 /* 989 * VADMIN provides the opportunity for the filesystem to make 990 * decisions about who is and is not able to modify labels 991 * and protections on files. This might not be right. We can't 992 * assume VOP_SETLABEL() will do it, because we might implement 993 * that as part of vop_stdsetlabel_ea(). 994 */ 995 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 996 if (error) 997 return (error); 998 999 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 1000 if (error) 1001 return (error); 1002 1003 return (0); 1004} 1005 1006void 1007mac_associate_nfsd_label(struct ucred *cred) 1008{ 1009 1010 MAC_PERFORM(associate_nfsd_label, cred); 1011} 1012