1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-25 16:13:17 +00:00

Move more ACL logic from the UFS code (ufs_acl.c) to the central POSIX.1e

support routines in kern_acl.c:

- Define ACL_OVERRIDE_MASK and ACL_PRESERVE_MASK centrally in acl.h: the
  mode bits that are (and aren't) stored in the ACL.

- Add acl_posix1e_acl_to_mode(): given a POSIX.1e extended ACL, generate
  a compatibility mode (only the bits supported by the POSIX.1e ACL).

- acl_posix1e_newfilemode(): Given a requested creation mode and default
  ACL, calculate the mode for the new file system object (only the bits
  supported by the POSIX.1e ACL).

PR:		50148
Reported by:	Ritz, Bruno <bruno_ritz@gmx.ch>
Obtained from:	TrustedBSD Project
This commit is contained in:
Robert Watson 2003-08-04 02:13:05 +00:00
parent 959174ee6c
commit 60bdc14e90
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=118407
4 changed files with 279 additions and 8 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
* Copyright (c) 1999, 2000, 2001, 2002, 2003 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
@ -472,6 +472,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
return (mode);
}
/*
* Utility function to generate a file mode given a complete POSIX.1e
* access ACL. Note that if the ACL is improperly formed, this may
* result in a panic.
*/
mode_t
acl_posix1e_acl_to_mode(struct acl *acl)
{
struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
int i;
/*
* Find the ACL entries relevant to a POSIX permission mode.
*/
acl_user_obj = acl_group_obj = acl_other = 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("acl_posix1e_acl_to_mode: bad ae_tag");
}
}
if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
panic("acl_posix1e_acl_to_mode: missing base ae_tags");
/*
* POSIX.1e specifies that if there is an ACL_MASK entry, we replace
* the mode "group" bits with its permissions. If there isn't, we
* use the ACL_GROUP_OBJ permissions.
*/
if (acl_mask != NULL)
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
acl_other));
else
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
acl_other));
}
/*
* Perform a syntactic check of the ACL, sufficient to allow an
* implementing filesystem to determine if it should accept this and
@ -559,6 +617,31 @@ acl_posix1e_check(struct acl *acl)
return (0);
}
/*
* Given a requested mode for a new object, and a default ACL, combine
* the two to produce a new mode. Be careful not to clear any bits that
* aren't intended to be affected by the POSIX.1e ACL. Eventually,
* this might also take the cmask as an argument, if we push that down
* into per-filesystem-code.
*/
mode_t
acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
{
mode_t mode;
mode = cmode;
/*
* The current composition policy is that a permission bit must
* be set in *both* the ACL and the requested creation mode for
* it to appear in the resulting mode/ACL. First clear any
* possibly effected bits, then reconstruct.
*/
mode &= ACL_PRESERVE_MASK;
mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
return (mode);
}
/*
* These calls wrap the real vnode operations, and are called by the
* syscall code once the syscall has converted the path or file

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
* Copyright (c) 1999, 2000, 2001, 2002, 2003 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
@ -472,6 +472,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
return (mode);
}
/*
* Utility function to generate a file mode given a complete POSIX.1e
* access ACL. Note that if the ACL is improperly formed, this may
* result in a panic.
*/
mode_t
acl_posix1e_acl_to_mode(struct acl *acl)
{
struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
int i;
/*
* Find the ACL entries relevant to a POSIX permission mode.
*/
acl_user_obj = acl_group_obj = acl_other = 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("acl_posix1e_acl_to_mode: bad ae_tag");
}
}
if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
panic("acl_posix1e_acl_to_mode: missing base ae_tags");
/*
* POSIX.1e specifies that if there is an ACL_MASK entry, we replace
* the mode "group" bits with its permissions. If there isn't, we
* use the ACL_GROUP_OBJ permissions.
*/
if (acl_mask != NULL)
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
acl_other));
else
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
acl_other));
}
/*
* Perform a syntactic check of the ACL, sufficient to allow an
* implementing filesystem to determine if it should accept this and
@ -559,6 +617,31 @@ acl_posix1e_check(struct acl *acl)
return (0);
}
/*
* Given a requested mode for a new object, and a default ACL, combine
* the two to produce a new mode. Be careful not to clear any bits that
* aren't intended to be affected by the POSIX.1e ACL. Eventually,
* this might also take the cmask as an argument, if we push that down
* into per-filesystem-code.
*/
mode_t
acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
{
mode_t mode;
mode = cmode;
/*
* The current composition policy is that a permission bit must
* be set in *both* the ACL and the requested creation mode for
* it to appear in the resulting mode/ACL. First clear any
* possibly effected bits, then reconstruct.
*/
mode &= ACL_PRESERVE_MASK;
mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
return (mode);
}
/*
* These calls wrap the real vnode operations, and are called by the
* syscall code once the syscall has converted the path or file

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
* Copyright (c) 1999, 2000, 2001, 2002, 2003 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
@ -472,6 +472,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
return (mode);
}
/*
* Utility function to generate a file mode given a complete POSIX.1e
* access ACL. Note that if the ACL is improperly formed, this may
* result in a panic.
*/
mode_t
acl_posix1e_acl_to_mode(struct acl *acl)
{
struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
int i;
/*
* Find the ACL entries relevant to a POSIX permission mode.
*/
acl_user_obj = acl_group_obj = acl_other = 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("acl_posix1e_acl_to_mode: bad ae_tag");
}
}
if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
panic("acl_posix1e_acl_to_mode: missing base ae_tags");
/*
* POSIX.1e specifies that if there is an ACL_MASK entry, we replace
* the mode "group" bits with its permissions. If there isn't, we
* use the ACL_GROUP_OBJ permissions.
*/
if (acl_mask != NULL)
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
acl_other));
else
return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
acl_other));
}
/*
* Perform a syntactic check of the ACL, sufficient to allow an
* implementing filesystem to determine if it should accept this and
@ -559,6 +617,31 @@ acl_posix1e_check(struct acl *acl)
return (0);
}
/*
* Given a requested mode for a new object, and a default ACL, combine
* the two to produce a new mode. Be careful not to clear any bits that
* aren't intended to be affected by the POSIX.1e ACL. Eventually,
* this might also take the cmask as an argument, if we push that down
* into per-filesystem-code.
*/
mode_t
acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
{
mode_t mode;
mode = cmode;
/*
* The current composition policy is that a permission bit must
* be set in *both* the ACL and the requested creation mode for
* it to appear in the resulting mode/ACL. First clear any
* possibly effected bits, then reconstruct.
*/
mode &= ACL_PRESERVE_MASK;
mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
return (mode);
}
/*
* These calls wrap the real vnode operations, and are called by the
* syscall code once the syscall has converted the path or file

View File

@ -116,6 +116,15 @@ typedef struct acl_t_struct *acl_t;
#ifdef _KERNEL
/*
* POSIX.1e ACLs are capable of expressing the read, write, and execute
* bits of the POSIX mode field. We provide two masks: one that defines
* the bits the ACL will replace in the mode, and the other that defines
* the bits that must be preseved when an ACL is updating a mode.
*/
#define ACL_OVERRIDE_MASK (S_IRWXU | S_IRWXG | S_IRWXO)
#define ACL_PRESERVE_MASK (~ACL_OVERRIDE_MASK)
/*
* Storage for ACLs and support structures.
*/
@ -123,12 +132,25 @@ typedef struct acl_t_struct *acl_t;
MALLOC_DECLARE(M_ACL);
#endif
acl_perm_t acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode);
/*
* File system independent code to move back and forth between POSIX mode
* and POSIX.1e ACL representations.
*/
acl_perm_t acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode);
struct acl_entry acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid,
gid_t gid, mode_t mode);
mode_t acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
struct acl_entry *acl_group_obj_entry, struct acl_entry *acl_other_entry);
int acl_posix1e_check(struct acl *acl);
gid_t gid, mode_t mode);
mode_t acl_posix1e_perms_to_mode(
struct acl_entry *acl_user_obj_entry,
struct acl_entry *acl_group_obj_entry,
struct acl_entry *acl_other_entry);
mode_t acl_posix1e_acl_to_mode(struct acl *acl);
mode_t acl_posix1e_newfilemode(mode_t cmode,
struct acl *dacl);
/*
* File system independent syntax check for a POSIX.1e ACL.
*/
int acl_posix1e_check(struct acl *acl);
#else /* !_KERNEL */