Push most UFS ACL behavior behind a check for MNT_ACLS, permitting ACLs

to be administratively disabled as needed on UFS/UFS2 file systems.  This
also has the effect of preventing the slightly more expensive ACL code
from running on non-ACL file systems, avoiding storage allocation for
ACLs that may be read from disk.  MNT_ACLS may be set at mount-time
using mount -o acls, or implicitly by setting the FS_ACLS flag using
tunefs.  On UFS1, you may also have to configure ACL store.

Obtained from:	TrustedBSD Project
Sponsored by:	DARPA, Network Associates Laboratories
This commit is contained in:
Robert Watson 2002-10-15 21:28:24 +00:00
parent 77e4f5d146
commit 9e3bf94fd7
2 changed files with 129 additions and 101 deletions

View File

@ -225,6 +225,12 @@ ufs_getacl(ap)
struct inode *ip = VTOI(ap->a_vp);
int error, len;
/*
* XXX: If ufs_getacl() should work on file systems not supporting
* ACLs, remove this check.
*/
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
return (EOPNOTSUPP);
/*
* Attempt to retrieve the ACL based on the ACL type.
@ -362,6 +368,9 @@ ufs_setacl(ap)
mode_t old_mode, preserve_mask;
int error;
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
return (EOPNOTSUPP);
/*
* If this is a set operation rather than a delete operation,
* invoke VOP_ACLCHECK() on the passed ACL to determine if it is
@ -475,6 +484,9 @@ ufs_aclcheck(ap)
} */ *ap;
{
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
return (EOPNOTSUPP);
/*
* Verify we understand this type of ACL, and that it applies
* to this kind of object.

View File

@ -367,33 +367,37 @@ ufs_access(ap)
return (EPERM);
#ifdef UFS_ACL
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
len = sizeof(*acl);
error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred, ap->a_td);
switch (error) {
case EOPNOTSUPP:
if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0) {
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
len = sizeof(*acl);
error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred,
ap->a_td);
switch (error) {
case EOPNOTSUPP:
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
ip->i_gid, ap->a_mode, ap->a_cred, NULL);
break;
case 0:
error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
ip->i_gid, acl, ap->a_mode, ap->a_cred, NULL);
break;
default:
printf(
"ufs_access(): Error retrieving ACL on object (%d).\n",
error);
/*
* XXX: Fall back until debugged. Should
* eventually possibly log an error, and return
* EPERM for safety.
*/
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
ip->i_gid, ap->a_mode, ap->a_cred, NULL);
}
FREE(acl, M_ACL);
} else
#endif /* !UFS_ACL */
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
ap->a_mode, ap->a_cred, NULL);
break;
case 0:
error = vaccess_acl_posix1e(vp->v_type, ip->i_uid, ip->i_gid,
acl, ap->a_mode, ap->a_cred, NULL);
break;
default:
printf("ufs_access(): Error retrieving ACL on object (%d).\n",
error);
/*
* XXX: Fall back until debugged. Should eventually
* possibly log an error, and return EPERM for safety.
*/
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
ap->a_mode, ap->a_cred, NULL);
}
FREE(acl, M_ACL);
#else
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
ap->a_mode, ap->a_cred, NULL);
#endif
return (error);
}
@ -1436,58 +1440,63 @@ ufs_mkdir(ap)
#endif /* !SUIDDIR */
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
#ifdef UFS_ACL
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
MALLOC(dacl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
acl = dacl = NULL;
if ((dvp->v_mount->mnt_flag & MNT_ACLS) != 0) {
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
MALLOC(dacl, struct acl *, sizeof(*dacl), M_ACL, M_WAITOK);
/*
* Retrieve default ACL from parent, if any.
*/
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
cnp->cn_thread);
switch (error) {
case 0:
/*
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
* Retrieve default ACL from parent, if any.
*/
if (acl->acl_cnt != 0) {
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
cnp->cn_thread);
switch (error) {
case 0:
/*
* Two possible ways for default ACL to not be
* present. First, the EA can be undefined,
* or second, the default ACL can be blank.
* If it's blank, fall through to the it's
* not defined case.
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
*/
if (acl->acl_cnt != 0) {
/*
* Two possible ways for default ACL to not
* be present. First, the EA can be
* undefined, or second, the default ACL can
* be blank. If it's blank, fall through to
* the it's not defined case.
*/
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
*dacl = *acl;
ufs_sync_acl_from_inode(ip, acl);
break;
}
/* FALLTHROUGH */
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
*dacl = *acl;
ufs_sync_acl_from_inode(ip, acl);
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
dacl = acl = NULL;
break;
default:
UFS_VFREE(tvp, ip->i_number, dmode);
vput(tvp);
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
return (error);
}
/* FALLTHROUGH */
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
} else {
#endif /* !UFS_ACL */
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
dacl = acl = NULL;
break;
default:
UFS_VFREE(tvp, ip->i_number, dmode);
vput(tvp);
FREE(acl, M_ACL);
FREE(dacl, M_ACL);
return (error);
#ifdef UFS_ACL
}
#else /* !UFS_ACL */
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
#endif /* !UFS_ACL */
#endif
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 2;
ip->i_nlink = 2;
@ -2342,53 +2351,60 @@ ufs_makeinode(mode, dvp, vpp, cnp)
#endif /* !SUIDDIR */
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
#ifdef UFS_ACL
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
/*
* Retrieve default ACL for parent, if any.
*/
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
cnp->cn_thread);
switch (error) {
case 0:
acl = NULL;
if ((dvp->v_mount->mnt_flag & MNT_ACLS) != 0) {
MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
/*
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
* Retrieve default ACL for parent, if any.
*/
if (acl->acl_cnt != 0) {
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
cnp->cn_thread);
switch (error) {
case 0:
/*
* Two possible ways for default ACL to not be
* present. First, the EA can be undefined,
* or second, the default ACL can be blank.
* If it's blank, fall through to the it's
* not defined case.
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
*/
if (acl->acl_cnt != 0) {
/*
* Two possible ways for default ACL to not
* be present. First, the EA can be
* undefined, or second, the default ACL can
* be blank. If it's blank, fall through to
* the it's not defined case.
*/
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
ufs_sync_acl_from_inode(ip, acl);
break;
}
/* FALLTHROUGH */
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
ufs_sync_acl_from_inode(ip, acl);
FREE(acl, M_ACL);
acl = NULL;
break;
default:
UFS_VFREE(tvp, ip->i_number, mode);
vput(tvp);
FREE(acl, M_ACL);
acl = NULL;
return (error);
}
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
} else {
#endif
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
FREE(acl, M_ACL);
acl = NULL;
break;
default:
UFS_VFREE(tvp, ip->i_number, mode);
vput(tvp);
FREE(acl, M_ACL);
acl = NULL;
return (error);
#ifdef UFS_ACL
}
#else /* !UFS_ACL */
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
#endif /* !UFS_ACL */
#endif
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;