Now that the central POSIX.1e ACL code implements functions to

generate the inode mode from a default ACL and creation mask,
implement ufs_sync_inode_from_acl() using acl_posix1e_newfilemode().

Since ACL_OVERRIDE_MASK/ACL_PRESERVE_MASK are defined, we no
longer need to explicitly pass in a "preserve_mask" field: this
is implicit in the use of POSIX.1e semantics.

Note: this change contains a semantic bugfix for new file creation:
we now intersect the ACL-generated mode and the cmode requested by
the user process.  This means permissions on newly created file
objects will now be more conservative.  In the future, we may want
to provide alternative semantics (similar to Solaris and Linux) in
which the ACL mask overrides the umask, permitting ACLs to broaden
the rights beyond the requested umask.

PR:		50148
Reported by:	Ritz, Bruno <bruno_ritz@gmx.ch>
Obtained from:	TrustedBSD Project
This commit is contained in:
rwatson 2003-08-04 03:29:13 +00:00
parent 33d30c1ba8
commit bf98881a21
3 changed files with 13 additions and 88 deletions

View File

@ -38,8 +38,7 @@
#ifdef _KERNEL
void ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl);
void ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
mode_t preserve_mask);
void ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip);
int ufs_getacl(struct vop_getacl_args *);
int ufs_setacl(struct vop_setacl_args *);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1999-2001 Robert N. M. Watson
* Copyright (c) 1999-2001, 2003 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
@ -126,83 +126,16 @@ ufs_sync_acl_from_inode(struct inode *ip, struct acl *acl)
}
/*
* Synchronize an inode and an ACL by copying over appropriate ACL fields to
* the passed inode. Assumes an ACL that would satisfy acl_posix1e_check(),
* and may panic if not. This code will preserve existing use of the
* sticky, setugid, and non-permission bits in the mode field. It may
* be that the caller wishes to have previously authorized these changes,
* and may also want to clear the setugid bits in some situations.
* Calculate what the inode mode should look like based on an authoritative
* ACL for the inode. Replace only the fields in the inode that the ACL
* can represent.
*/
void
ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip,
mode_t preserve_mask)
ufs_sync_inode_from_acl(struct acl *acl, struct inode *ip)
{
struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj;
struct acl_entry *acl_other;
mode_t preserve_mode;
int i;
/*
* Preserve old mode so we can restore appropriate bits of it.
*/
preserve_mode = (ip->i_mode & preserve_mask);
/*
* Identify the ACL_MASK and all other entries appearing in the
* inode mode.
*/
acl_user_obj = NULL;
acl_group_obj = NULL;
acl_other = NULL;
acl_mask = NULL;
for (i = 0; i < acl->acl_cnt; i++) {
switch (acl->acl_entry[i].ae_tag) {
case ACL_USER_OBJ:
acl_user_obj = &acl->acl_entry[i];
break;
case ACL_GROUP_OBJ:
acl_group_obj = &acl->acl_entry[i];
break;
case ACL_OTHER:
acl_other = &acl->acl_entry[i];
break;
case ACL_MASK:
acl_mask = &acl->acl_entry[i];
break;
case ACL_USER:
case ACL_GROUP:
break;
default:
panic("ufs_sync_inode_from_acl(): bad ae_tag");
}
}
if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
panic("ufs_sync_inode_from_acl(): missing ae_tags");
if (acl_mask == NULL) {
/*
* There is no ACL_MASK, so use the ACL_GROUP_OBJ entry.
*/
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_group_obj, acl_other);
DIP(ip, i_mode) = ip->i_mode;
} else {
/*
* Use the ACL_MASK entry.
*/
ip->i_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ip->i_mode |= acl_posix1e_perms_to_mode(acl_user_obj,
acl_mask, acl_other);
DIP(ip, i_mode) = ip->i_mode;
}
ip->i_mode |= preserve_mode;
ip->i_mode &= ACL_PRESERVE_MASK;
ip->i_mode |= acl_posix1e_acl_to_mode(acl);
DIP(ip, i_mode) = ip->i_mode;
}
@ -366,7 +299,6 @@ ufs_setacl(ap)
} */ *ap;
{
struct inode *ip = VTOI(ap->a_vp);
mode_t old_mode, preserve_mask;
int error;
if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
@ -461,9 +393,7 @@ ufs_setacl(ap)
* Now that the EA is successfully updated, update the
* inode and mark it as changed.
*/
old_mode = ip->i_mode;
preserve_mask = ISVTX | ISGID | ISUID;
ufs_sync_inode_from_acl(ap->a_aclp, ip, preserve_mask);
ufs_sync_inode_from_acl(ap->a_aclp, ip);
ip->i_flag |= IN_CHANGE;
}

View File

@ -1458,16 +1458,11 @@ ufs_mkdir(ap)
case 0:
/*
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
* necessary. If the ACL is empty, fall through to
* the "not defined or available" case.
*/
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.
*/
dmode = acl_posix1e_newfilemode(dmode, acl);
ip->i_mode = dmode;
DIP(ip, i_mode) = dmode;
*dacl = *acl;
@ -2449,6 +2444,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* be blank. If it's blank, fall through to
* the it's not defined case.
*/
mode = acl_posix1e_newfilemode(mode, acl);
ip->i_mode = mode;
DIP(ip, i_mode) = mode;
ufs_sync_acl_from_inode(ip, acl);