diff options
author | rwatson <rwatson@FreeBSD.org> | 2003-08-04 02:13:05 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2003-08-04 02:13:05 +0000 |
commit | 543a0376198dff1ddab776667470525600f2e0b7 (patch) | |
tree | 0fff626afb370057db475fbd154ed2df8043303f /sys | |
parent | 0a1cb2dc0dfb51be6c7c68742d54c60e6dfed5ac (diff) | |
download | FreeBSD-src-543a0376198dff1ddab776667470525600f2e0b7.zip FreeBSD-src-543a0376198dff1ddab776667470525600f2e0b7.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_acl.c | 85 | ||||
-rw-r--r-- | sys/kern/subr_acl_posix1e.c | 85 | ||||
-rw-r--r-- | sys/kern/vfs_acl.c | 85 | ||||
-rw-r--r-- | sys/sys/acl.h | 32 |
4 files changed, 279 insertions, 8 deletions
diff --git a/sys/kern/kern_acl.c b/sys/kern/kern_acl.c index 5a60f78..c0bd1eb 100644 --- a/sys/kern/kern_acl.c +++ b/sys/kern/kern_acl.c @@ -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. @@ -473,6 +473,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry, } /* + * 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 * rely on the POSIX.1e ACL properties. @@ -560,6 +618,31 @@ acl_posix1e_check(struct acl *acl) } /* + * 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 * descriptor to a vnode (unlocked). The aclp pointer is assumed diff --git a/sys/kern/subr_acl_posix1e.c b/sys/kern/subr_acl_posix1e.c index 5a60f78..c0bd1eb 100644 --- a/sys/kern/subr_acl_posix1e.c +++ b/sys/kern/subr_acl_posix1e.c @@ -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. @@ -473,6 +473,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry, } /* + * 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 * rely on the POSIX.1e ACL properties. @@ -560,6 +618,31 @@ acl_posix1e_check(struct acl *acl) } /* + * 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 * descriptor to a vnode (unlocked). The aclp pointer is assumed diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c index 5a60f78..c0bd1eb 100644 --- a/sys/kern/vfs_acl.c +++ b/sys/kern/vfs_acl.c @@ -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. @@ -473,6 +473,64 @@ acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry, } /* + * 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 * rely on the POSIX.1e ACL properties. @@ -560,6 +618,31 @@ acl_posix1e_check(struct acl *acl) } /* + * 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 * descriptor to a vnode (unlocked). The aclp pointer is assumed diff --git a/sys/sys/acl.h b/sys/sys/acl.h index 1e7fe68..64ae294 100644 --- a/sys/sys/acl.h +++ b/sys/sys/acl.h @@ -117,18 +117,40 @@ 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. */ #ifdef MALLOC_DECLARE 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 */ |