ufs_acl.c revision 105179
174822Srwatson/*- 285845Srwatson * Copyright (c) 1999-2001 Robert N. M. Watson 374822Srwatson * All rights reserved. 474822Srwatson * 585845Srwatson * This software was developed by Robert Watson for the TrustedBSD Project. 685845Srwatson * 774822Srwatson * Redistribution and use in source and binary forms, with or without 874822Srwatson * modification, are permitted provided that the following conditions 974822Srwatson * are met: 1074822Srwatson * 1. Redistributions of source code must retain the above copyright 1174822Srwatson * notice, this list of conditions and the following disclaimer. 1274822Srwatson * 2. Redistributions in binary form must reproduce the above copyright 1374822Srwatson * notice, this list of conditions and the following disclaimer in the 1474822Srwatson * documentation and/or other materials provided with the distribution. 1574822Srwatson * 1674822Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1774822Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1874822Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1974822Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2074822Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2174822Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2274822Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2374822Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2474822Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2574822Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2674822Srwatson * SUCH DAMAGE. 2774822Srwatson * 2874822Srwatson * $FreeBSD: head/sys/ufs/ufs/ufs_acl.c 105179 2002-10-15 21:28:24Z rwatson $ 2974822Srwatson */ 3074822Srwatson/* 3174822Srwatson * Developed by the TrustedBSD Project. 3274822Srwatson * Support for POSIX.1e access control lists: UFS-specific support functions. 3374822Srwatson */ 3474822Srwatson 3574822Srwatson#include "opt_ufs.h" 3674822Srwatson#include "opt_quota.h" 3774822Srwatson 3874822Srwatson#include <sys/param.h> 3974822Srwatson#include <sys/systm.h> 4074822Srwatson#include <sys/stat.h> 4174822Srwatson#include <sys/mount.h> 4274822Srwatson#include <sys/vnode.h> 4374822Srwatson#include <sys/types.h> 4474822Srwatson#include <sys/acl.h> 4574822Srwatson#include <sys/event.h> 4674822Srwatson#include <sys/extattr.h> 4774822Srwatson 4874822Srwatson#include <ufs/ufs/quota.h> 4974822Srwatson#include <ufs/ufs/inode.h> 5074822Srwatson#include <ufs/ufs/acl.h> 5174822Srwatson#include <ufs/ufs/extattr.h> 5274822Srwatson#include <ufs/ufs/dir.h> 5374822Srwatson#include <ufs/ufs/ufsmount.h> 5474822Srwatson#include <ufs/ufs/ufs_extern.h> 5574822Srwatson 5674822Srwatson#ifdef UFS_ACL 5774822Srwatson 5874822Srwatson/* 5974822Srwatson * Synchronize an ACL and an inode by copying over appropriate inode fields 6074822Srwatson * to the passed ACL. Assumes an ACL that would satisfy acl_posix1e_check(), 6174822Srwatson * and may panic if not. 6274822Srwatson */ 6374822Srwatsonvoid 6474822Srwatsonufs_sync_acl_from_inode(struct inode *ip, struct acl *acl) 6574822Srwatson{ 6674822Srwatson struct acl_entry *acl_mask, *acl_group_obj; 6774822Srwatson int i; 6874822Srwatson 6974822Srwatson /* 7074822Srwatson * Update ACL_USER_OBJ, ACL_OTHER, but simply identify ACL_MASK 7174822Srwatson * and ACL_GROUP_OBJ for use after we know whether ACL_MASK is 7274822Srwatson * present. 7374822Srwatson */ 7474822Srwatson acl_mask = NULL; 7574822Srwatson acl_group_obj = NULL; 7674822Srwatson for (i = 0; i < acl->acl_cnt; i++) { 7774822Srwatson switch (acl->acl_entry[i].ae_tag) { 7874822Srwatson case ACL_USER_OBJ: 7974822Srwatson acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( 8074822Srwatson ACL_USER_OBJ, ip->i_mode); 8175571Srwatson acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 8274822Srwatson break; 8374822Srwatson 8474822Srwatson case ACL_GROUP_OBJ: 8574822Srwatson acl_group_obj = &acl->acl_entry[i]; 8675571Srwatson acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 8774822Srwatson break; 8874822Srwatson 8974822Srwatson case ACL_OTHER: 9074822Srwatson acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm( 9174822Srwatson ACL_OTHER, ip->i_mode); 9275571Srwatson acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 9374822Srwatson break; 9474822Srwatson 9574822Srwatson case ACL_MASK: 9674822Srwatson acl_mask = &acl->acl_entry[i]; 9775571Srwatson acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; 9874822Srwatson break; 9974822Srwatson 10074822Srwatson case ACL_USER: 10174822Srwatson case ACL_GROUP: 10274822Srwatson break; 10374822Srwatson 10474822Srwatson default: 10574822Srwatson panic("ufs_sync_acl_from_inode(): bad ae_tag"); 10674822Srwatson } 10774822Srwatson } 10874822Srwatson 10974822Srwatson if (acl_group_obj == NULL) 11074822Srwatson panic("ufs_sync_acl_from_inode(): no ACL_GROUP_OBJ"); 11174822Srwatson 11274822Srwatson if (acl_mask == NULL) { 11374822Srwatson /* 11474822Srwatson * There is no ACL_MASK, so update ACL_GROUP_OBJ. 11574822Srwatson */ 11674822Srwatson acl_group_obj->ae_perm = acl_posix1e_mode_to_perm( 11774822Srwatson ACL_GROUP_OBJ, ip->i_mode); 11874822Srwatson } else { 11974822Srwatson /* 12074822Srwatson * Update the ACL_MASK entry instead of ACL_GROUP_OBJ. 12174822Srwatson */ 12274822Srwatson acl_mask->ae_perm = acl_posix1e_mode_to_perm(ACL_GROUP_OBJ, 12374822Srwatson ip->i_mode); 12474822Srwatson } 12574822Srwatson} 12674822Srwatson 12774822Srwatson/* 12874822Srwatson * Synchronize an inode and an ACL by copying over appropriate ACL fields to 12974822Srwatson * the passed inode. Assumes an ACL that would satisfy acl_posix1e_check(), 13074822Srwatson * and may panic if not. This code will preserve existing use of the 13174822Srwatson * sticky, setugid, and non-permission bits in the mode field. It may 13274822Srwatson * be that the caller wishes to have previously authorized these changes, 13374822Srwatson * and may also want to clear the setugid bits in some situations. 13474822Srwatson */ 13574822Srwatsonvoid 13674822Srwatsonufs_sync_inode_from_acl(struct acl *acl, struct inode *ip, 13774822Srwatson mode_t preserve_mask) 13874822Srwatson{ 13974822Srwatson struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj; 14074822Srwatson struct acl_entry *acl_other; 14174822Srwatson mode_t preserve_mode; 14274822Srwatson int i; 14374822Srwatson 14474822Srwatson /* 14574822Srwatson * Preserve old mode so we can restore appropriate bits of it. 14674822Srwatson */ 14774822Srwatson preserve_mode = (ip->i_mode & preserve_mask); 14874822Srwatson 14974822Srwatson /* 15074822Srwatson * Identify the ACL_MASK and all other entries appearing in the 15174822Srwatson * inode mode. 15274822Srwatson */ 15374822Srwatson acl_user_obj = NULL; 15474822Srwatson acl_group_obj = NULL; 15574822Srwatson acl_other = NULL; 15674822Srwatson acl_mask = NULL; 15774822Srwatson for (i = 0; i < acl->acl_cnt; i++) { 15874822Srwatson switch (acl->acl_entry[i].ae_tag) { 15974822Srwatson case ACL_USER_OBJ: 16074822Srwatson acl_user_obj = &acl->acl_entry[i]; 16174822Srwatson break; 16274822Srwatson 16374822Srwatson case ACL_GROUP_OBJ: 16474822Srwatson acl_group_obj = &acl->acl_entry[i]; 16574822Srwatson break; 16674822Srwatson 16774822Srwatson case ACL_OTHER: 16874822Srwatson acl_other = &acl->acl_entry[i]; 16974822Srwatson break; 17074822Srwatson 17174822Srwatson case ACL_MASK: 17274822Srwatson acl_mask = &acl->acl_entry[i]; 17374822Srwatson break; 17474822Srwatson 17574822Srwatson case ACL_USER: 17674822Srwatson case ACL_GROUP: 17774822Srwatson break; 17874822Srwatson 17974822Srwatson default: 18074822Srwatson panic("ufs_sync_inode_from_acl(): bad ae_tag"); 18174822Srwatson } 18274822Srwatson } 18374822Srwatson 18474822Srwatson if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL) 18574822Srwatson panic("ufs_sync_inode_from_acl(): missing ae_tags"); 18674822Srwatson 18774822Srwatson if (acl_mask == NULL) { 18874822Srwatson /* 18974822Srwatson * There is no ACL_MASK, so use the ACL_GROUP_OBJ entry. 19074822Srwatson */ 19175571Srwatson ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); 19274822Srwatson ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj, 19374822Srwatson acl_group_obj, acl_other); 19498542Smckusick DIP(ip, i_mode) = ip->i_mode; 19574822Srwatson } else { 19674822Srwatson /* 19774822Srwatson * Use the ACL_MASK entry. 19874822Srwatson */ 19975571Srwatson ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); 20074822Srwatson ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj, 20174822Srwatson acl_mask, acl_other); 20298542Smckusick DIP(ip, i_mode) = ip->i_mode; 20374822Srwatson } 20474822Srwatson ip->i_mode |= preserve_mode; 20598542Smckusick DIP(ip, i_mode) = ip->i_mode; 20674822Srwatson} 20774822Srwatson 20874822Srwatson/* 20974822Srwatson * Retrieve the ACL on a file. 21074822Srwatson * 21174822Srwatson * As part of the ACL is stored in the inode, and the rest in an EA, 21274822Srwatson * assemble both into a final ACL product. Right now this is not done 21374822Srwatson * very efficiently. 21474822Srwatson */ 21574822Srwatsonint 21674822Srwatsonufs_getacl(ap) 21774822Srwatson struct vop_getacl_args /* { 21874822Srwatson struct vnode *vp; 21974822Srwatson struct acl_type_t type; 22074822Srwatson struct acl *aclp; 22174822Srwatson struct ucred *cred; 22283366Sjulian struct thread *td; 22374822Srwatson } */ *ap; 22474822Srwatson{ 22574822Srwatson struct inode *ip = VTOI(ap->a_vp); 22674822Srwatson int error, len; 22774822Srwatson 228105179Srwatson /* 229105179Srwatson * XXX: If ufs_getacl() should work on file systems not supporting 230105179Srwatson * ACLs, remove this check. 231105179Srwatson */ 232105179Srwatson if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 233105179Srwatson return (EOPNOTSUPP); 23474822Srwatson 23574822Srwatson /* 23674822Srwatson * Attempt to retrieve the ACL based on the ACL type. 23774822Srwatson */ 23874822Srwatson bzero(ap->a_aclp, sizeof(*ap->a_aclp)); 23975077Srwatson len = sizeof(*ap->a_aclp); 24074822Srwatson switch(ap->a_type) { 24174822Srwatson case ACL_TYPE_ACCESS: 24274822Srwatson /* 24374822Srwatson * ACL_TYPE_ACCESS ACLs may or may not be stored in the 24474822Srwatson * EA, as they are in fact a combination of the inode 24574822Srwatson * ownership/permissions and the EA contents. If the 24674822Srwatson * EA is present, merge the two in a temporary ACL 24774822Srwatson * storage, otherwise just return the inode contents. 24874822Srwatson */ 24974822Srwatson error = vn_extattr_get(ap->a_vp, IO_NODELOCKED, 25074822Srwatson POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE, 25174822Srwatson POSIX1E_ACL_ACCESS_EXTATTR_NAME, &len, (char *) ap->a_aclp, 25283366Sjulian ap->a_td); 25374822Srwatson switch (error) { 25496755Strhodes /* XXX: If ufs_getacl() should work on filesystems without 25574822Srwatson * the EA configured, add case EOPNOTSUPP here. */ 25691814Sgreen case ENOATTR: 25774822Srwatson /* 25874822Srwatson * Legitimately no ACL set on object, purely 25974822Srwatson * emulate it through the inode. These fields will 26074822Srwatson * be updated when the ACL is synchronized with 26174822Srwatson * the inode later. 26274822Srwatson */ 26374822Srwatson ap->a_aclp->acl_cnt = 3; 26474822Srwatson ap->a_aclp->acl_entry[0].ae_tag = ACL_USER_OBJ; 26575571Srwatson ap->a_aclp->acl_entry[0].ae_id = ACL_UNDEFINED_ID; 26682770Sjedgar ap->a_aclp->acl_entry[0].ae_perm = ACL_PERM_NONE; 26774822Srwatson ap->a_aclp->acl_entry[1].ae_tag = ACL_GROUP_OBJ; 26875571Srwatson ap->a_aclp->acl_entry[1].ae_id = ACL_UNDEFINED_ID; 26982770Sjedgar ap->a_aclp->acl_entry[1].ae_perm = ACL_PERM_NONE; 27074822Srwatson ap->a_aclp->acl_entry[2].ae_tag = ACL_OTHER; 27175571Srwatson ap->a_aclp->acl_entry[2].ae_id = ACL_UNDEFINED_ID; 27282770Sjedgar ap->a_aclp->acl_entry[2].ae_perm = ACL_PERM_NONE; 27374822Srwatson ufs_sync_acl_from_inode(ip, ap->a_aclp); 27474822Srwatson error = 0; 27574822Srwatson break; 27674822Srwatson 27774822Srwatson case 0: 27874822Srwatson if (len != sizeof(*ap->a_aclp)) { 27974822Srwatson /* 28074822Srwatson * A short (or long) read, meaning that for 28174822Srwatson * some reason the ACL is corrupted. Return 28274822Srwatson * EPERM since the object DAC protections 28374822Srwatson * are unsafe. 28474822Srwatson */ 28574822Srwatson printf("ufs_getacl(): Loaded invalid ACL (" 28674822Srwatson "%d bytes)\n", len); 28774822Srwatson return (EPERM); 28874822Srwatson } 28974822Srwatson ufs_sync_acl_from_inode(ip, ap->a_aclp); 29074822Srwatson break; 29174822Srwatson 29297724Salfred default: 29397724Salfred break; 29474822Srwatson } 29574822Srwatson break; 29674822Srwatson 29774822Srwatson case ACL_TYPE_DEFAULT: 29874822Srwatson if (ap->a_vp->v_type != VDIR) { 29974822Srwatson error = EINVAL; 30074822Srwatson break; 30174822Srwatson } 30274822Srwatson error = vn_extattr_get(ap->a_vp, IO_NODELOCKED, 30374822Srwatson POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 30474822Srwatson POSIX1E_ACL_DEFAULT_EXTATTR_NAME, &len, 30583366Sjulian (char *) ap->a_aclp, ap->a_td); 30674822Srwatson /* 30774822Srwatson * Unlike ACL_TYPE_ACCESS, there is no relationship between 30874822Srwatson * the inode contents and the ACL, and it is therefore 30974822Srwatson * possible for the request for the ACL to fail since the 31074822Srwatson * ACL is undefined. In this situation, return success 31174822Srwatson * and an empty ACL, as required by POSIX.1e. 31274822Srwatson */ 31374822Srwatson switch (error) { 31496755Strhodes /* XXX: If ufs_getacl() should work on filesystems without 31574822Srwatson * the EA configured, add case EOPNOTSUPP here. */ 31691814Sgreen case ENOATTR: 31774822Srwatson bzero(ap->a_aclp, sizeof(*ap->a_aclp)); 31874822Srwatson ap->a_aclp->acl_cnt = 0; 31974822Srwatson error = 0; 32074822Srwatson break; 32174822Srwatson 32274822Srwatson case 0: 32375077Srwatson if (len != sizeof(*ap->a_aclp)) { 32475077Srwatson /* 32575077Srwatson * A short (or long) read, meaning that for 32675077Srwatson * some reason the ACL is corrupted. Return 32775077Srwatson * EPERM since the object default DAC 32875077Srwatson * protections are unsafe. 32975077Srwatson */ 33075077Srwatson printf("ufs_getacl(): Loaded invalid ACL (" 33175077Srwatson "%d bytes)\n", len); 33275077Srwatson return (EPERM); 33375077Srwatson } 33474822Srwatson break; 33574822Srwatson 33697724Salfred default: 33797724Salfred break; 33874822Srwatson } 33974822Srwatson break; 34074822Srwatson 34174822Srwatson default: 34274822Srwatson error = EINVAL; 34374822Srwatson } 34474822Srwatson 34574822Srwatson return (error); 34674822Srwatson} 34774822Srwatson 34874822Srwatson/* 34974822Srwatson * Set the ACL on a file. 35074822Srwatson * 35174822Srwatson * As part of the ACL is stored in the inode, and the rest in an EA, 35274822Srwatson * this is necessarily non-atomic, and has complex authorization. 35374822Srwatson * As ufs_setacl() includes elements of ufs_chown() and ufs_chmod(), 35474822Srwatson * a fair number of different access checks may be required to go ahead 35574822Srwatson * with the operation at all. 35674822Srwatson */ 35774822Srwatsonint 35874822Srwatsonufs_setacl(ap) 35974822Srwatson struct vop_setacl_args /* { 36074822Srwatson struct vnode *vp; 36174822Srwatson acl_type_t type; 36274822Srwatson struct acl *aclp; 36374822Srwatson struct ucred *cred; 36474822Srwatson struct proc *p; 36574822Srwatson } */ *ap; 36674822Srwatson{ 36774822Srwatson struct inode *ip = VTOI(ap->a_vp); 36874822Srwatson mode_t old_mode, preserve_mask; 36975571Srwatson int error; 37074822Srwatson 371105179Srwatson if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 372105179Srwatson return (EOPNOTSUPP); 373105179Srwatson 37474822Srwatson /* 37574822Srwatson * If this is a set operation rather than a delete operation, 37674822Srwatson * invoke VOP_ACLCHECK() on the passed ACL to determine if it is 37774822Srwatson * valid for the target. This will include a check on ap->a_type. 37874822Srwatson */ 37974822Srwatson if (ap->a_aclp != NULL) { 38074822Srwatson /* 38174822Srwatson * Set operation. 38274822Srwatson */ 38374822Srwatson error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp, 38483366Sjulian ap->a_cred, ap->a_td); 38574822Srwatson if (error != 0) 38674822Srwatson return (error); 38774822Srwatson } else { 38874822Srwatson /* 38974822Srwatson * Delete operation. 39074822Srwatson * POSIX.1e allows only deletion of the default ACL on a 39174822Srwatson * directory (ACL_TYPE_DEFAULT). 39274822Srwatson */ 39374822Srwatson if (ap->a_type != ACL_TYPE_DEFAULT) 39474822Srwatson return (EINVAL); 39574822Srwatson if (ap->a_vp->v_type != VDIR) 39674822Srwatson return (ENOTDIR); 39774822Srwatson } 39874822Srwatson 39974822Srwatson if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) 40074822Srwatson return (EROFS); 40174822Srwatson 40274822Srwatson /* 40374822Srwatson * Authorize the ACL operation. 40474822Srwatson */ 40574822Srwatson if (ip->i_flags & (IMMUTABLE | APPEND)) 40674822Srwatson return (EPERM); 40774822Srwatson 40874822Srwatson /* 40974822Srwatson * Must hold VADMIN (be file owner) or have appropriate privilege. 41074822Srwatson */ 41183366Sjulian if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td))) 41274822Srwatson return (error); 41374822Srwatson 41474822Srwatson switch(ap->a_type) { 41574822Srwatson case ACL_TYPE_ACCESS: 41674822Srwatson error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, 41774822Srwatson POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE, 41874822Srwatson POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*ap->a_aclp), 41983366Sjulian (char *) ap->a_aclp, ap->a_td); 42074822Srwatson break; 42174822Srwatson 42274822Srwatson case ACL_TYPE_DEFAULT: 42374822Srwatson if (ap->a_aclp == NULL) { 42474822Srwatson error = vn_extattr_rm(ap->a_vp, IO_NODELOCKED, 42574822Srwatson POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 42683366Sjulian POSIX1E_ACL_DEFAULT_EXTATTR_NAME, ap->a_td); 42774822Srwatson /* 42874822Srwatson * Attempting to delete a non-present default ACL 42974822Srwatson * will return success for portability purposes. 43074822Srwatson * (TRIX) 43185581Srwatson * 43285581Srwatson * XXX: Note that since we can't distinguish 43385581Srwatson * "that EA is not supported" from "that EA is not 43485581Srwatson * defined", the success case here overlaps the 43591814Sgreen * the ENOATTR->EOPNOTSUPP case below. 43674822Srwatson */ 43791814Sgreen if (error == ENOATTR) 43874822Srwatson error = 0; 43974822Srwatson } else 44074822Srwatson error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, 44174822Srwatson POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE, 44274822Srwatson POSIX1E_ACL_DEFAULT_EXTATTR_NAME, 44383366Sjulian sizeof(*ap->a_aclp), (char *) ap->a_aclp, ap->a_td); 44474822Srwatson break; 44574822Srwatson 44674822Srwatson default: 44774822Srwatson error = EINVAL; 44874822Srwatson } 44974822Srwatson /* 45074822Srwatson * Map lack of attribute definition in UFS_EXTATTR into lack of 45196755Strhodes * support for ACLs on the filesystem. 45274822Srwatson */ 45391814Sgreen if (error == ENOATTR) 45474822Srwatson return (EOPNOTSUPP); 45574822Srwatson if (error != 0) 45674822Srwatson return (error); 45774822Srwatson 45874822Srwatson if (ap->a_type == ACL_TYPE_ACCESS) { 45974822Srwatson /* 46074822Srwatson * Now that the EA is successfully updated, update the 46174822Srwatson * inode and mark it as changed. 46274822Srwatson */ 46374822Srwatson old_mode = ip->i_mode; 46474822Srwatson preserve_mask = ISVTX | ISGID | ISUID; 46574822Srwatson ufs_sync_inode_from_acl(ap->a_aclp, ip, preserve_mask); 46674822Srwatson ip->i_flag |= IN_CHANGE; 46774822Srwatson } 46874822Srwatson 46974822Srwatson VN_KNOTE(ap->a_vp, NOTE_ATTRIB); 47074822Srwatson return (0); 47174822Srwatson} 47274822Srwatson 47374822Srwatson/* 47474822Srwatson * Check the validity of an ACL for a file. 47574822Srwatson */ 47674822Srwatsonint 47774822Srwatsonufs_aclcheck(ap) 47874822Srwatson struct vop_aclcheck_args /* { 47974822Srwatson struct vnode *vp; 48074822Srwatson acl_type_t type; 48174822Srwatson struct acl *aclp; 48274822Srwatson struct ucred *cred; 48383366Sjulian struct thread *td; 48474822Srwatson } */ *ap; 48574822Srwatson{ 48674822Srwatson 487105179Srwatson if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) 488105179Srwatson return (EOPNOTSUPP); 489105179Srwatson 49074822Srwatson /* 49174822Srwatson * Verify we understand this type of ACL, and that it applies 49274822Srwatson * to this kind of object. 49374822Srwatson * Rely on the acl_posix1e_check() routine to verify the contents. 49474822Srwatson */ 49574822Srwatson switch(ap->a_type) { 49674822Srwatson case ACL_TYPE_ACCESS: 49774822Srwatson break; 49874822Srwatson 49974822Srwatson case ACL_TYPE_DEFAULT: 50074822Srwatson if (ap->a_vp->v_type != VDIR) 50174822Srwatson return (EINVAL); 50274822Srwatson break; 50374822Srwatson 50474822Srwatson default: 50574822Srwatson return (EINVAL); 50674822Srwatson } 50774822Srwatson return (acl_posix1e_check(ap->a_aclp)); 50874822Srwatson} 50974822Srwatson 51074822Srwatson#endif /* !UFS_ACL */ 511