summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_acl.c85
-rw-r--r--sys/kern/subr_acl_posix1e.c85
-rw-r--r--sys/kern/vfs_acl.c85
-rw-r--r--sys/sys/acl.h32
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 */
OpenPOWER on IntegriCloud