144 lines
4.7 KiB
Diff
144 lines
4.7 KiB
Diff
|
From: Andreas Gruenbacher <agruen@suse.de>
|
||
|
Date: Fri, 11 Jun 2010 16:12:52 +0530
|
||
|
Subject: [PATCH 12/16] richacl: Automatic Inheritance
|
||
|
Patch-mainline: not yet
|
||
|
|
||
|
Automatic Inheritance (AI) allows changes to the acl of a directory to
|
||
|
recursively propagate down to files and directories in the directory.
|
||
|
|
||
|
To implement this, the kernel keeps track of which permissions have been
|
||
|
inherited, and makes sure that permission propagation is turned off when
|
||
|
the file permission bits of a file are changed (upon create or chmod).
|
||
|
|
||
|
The actual permission propagation is implemented in user space.
|
||
|
|
||
|
AI works as follows:
|
||
|
|
||
|
- When the ACL4_AUTO_INHERIT flag in the acl of a file is cleared, the
|
||
|
file is not affected by AI.
|
||
|
|
||
|
- When the ACL4_AUTO_INHERIT flag in the acl of a directory is set and
|
||
|
a file or subdirectory is created in that directory, files created in
|
||
|
the directory will have the ACL4_AUTO_INHERIT flag set, and all
|
||
|
inherited aces will have the ACE4_INHERITED_ACE flag set. This
|
||
|
allows user space to distinguish between aces which have been
|
||
|
inherited, and aces which have been explicitly added.
|
||
|
|
||
|
- When the ACL4_PROTECTED acl flag in the acl of a file is set, AI will
|
||
|
not modify the acl of the file. This does not affect propagation of
|
||
|
permissions from the file to its children (if the file is a
|
||
|
directory).
|
||
|
|
||
|
Linux does not have a way of creating files without setting the file
|
||
|
permission bits, so all files created inside a directory with
|
||
|
ACL4_AUTO_INHERIT set will also have the ACL4_PROTECTED flag set. This
|
||
|
effectively disables AI.
|
||
|
|
||
|
Protocols which support creating files without specifying permissions
|
||
|
can explicitly clear the ACL4_PROTECTED flag after creating a file (and
|
||
|
reset the file masks to "undo" applying the create mode; see
|
||
|
richacl_compute_max_masks()). This is a workaround; a per-create or
|
||
|
per-process flag indicating to ignore the create mode when AI is in
|
||
|
effect would fix this problem.
|
||
|
|
||
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||
|
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||
|
---
|
||
|
fs/richacl_base.c | 15 ++++++++++++++-
|
||
|
include/linux/richacl.h | 25 ++++++++++++++++++++++++-
|
||
|
2 files changed, 38 insertions(+), 2 deletions(-)
|
||
|
|
||
|
--- a/fs/richacl_base.c
|
||
|
+++ b/fs/richacl_base.c
|
||
|
@@ -352,7 +352,8 @@ richacl_chmod(struct richacl *acl, mode_
|
||
|
|
||
|
if (acl->a_owner_mask == owner_mask &&
|
||
|
acl->a_group_mask == group_mask &&
|
||
|
- acl->a_other_mask == other_mask)
|
||
|
+ acl->a_other_mask == other_mask &&
|
||
|
+ (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl)))
|
||
|
return acl;
|
||
|
|
||
|
clone = richacl_clone(acl);
|
||
|
@@ -363,6 +364,8 @@ richacl_chmod(struct richacl *acl, mode_
|
||
|
clone->a_owner_mask = owner_mask;
|
||
|
clone->a_group_mask = group_mask;
|
||
|
clone->a_other_mask = other_mask;
|
||
|
+ if (richacl_is_auto_inherit(clone))
|
||
|
+ clone->a_flags |= ACL4_PROTECTED;
|
||
|
|
||
|
return clone;
|
||
|
}
|
||
|
@@ -539,6 +542,16 @@ richacl_inherit(const struct richacl *di
|
||
|
acl->a_other_mask &= richacl_mode_to_mask(inode->i_mode);
|
||
|
mask = ~S_IRWXUGO | richacl_masks_to_mode(acl);
|
||
|
|
||
|
+ if (richacl_is_auto_inherit(dir_acl)) {
|
||
|
+ /*
|
||
|
+ * We need to set ACL4_PROTECTED because we are
|
||
|
+ * doing an implicit chmod
|
||
|
+ */
|
||
|
+ acl->a_flags = ACL4_AUTO_INHERIT | ACL4_PROTECTED;
|
||
|
+ richacl_for_each_entry(ace, acl)
|
||
|
+ ace->e_flags |= ACE4_INHERITED_ACE;
|
||
|
+ }
|
||
|
+
|
||
|
mask:
|
||
|
inode->i_mode &= mask;
|
||
|
return acl;
|
||
|
--- a/include/linux/richacl.h
|
||
|
+++ b/include/linux/richacl.h
|
||
|
@@ -47,6 +47,15 @@ struct richacl {
|
||
|
_ace != _acl->a_entries - 1; \
|
||
|
_ace--)
|
||
|
|
||
|
+/* a_flags values */
|
||
|
+#define ACL4_AUTO_INHERIT 0x01
|
||
|
+#define ACL4_PROTECTED 0x02
|
||
|
+/*#define ACL4_DEFAULTED 0x04*/
|
||
|
+
|
||
|
+#define ACL4_VALID_FLAGS ( \
|
||
|
+ ACL4_AUTO_INHERIT | \
|
||
|
+ ACL4_PROTECTED)
|
||
|
+
|
||
|
/* e_type values */
|
||
|
#define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x0000
|
||
|
#define ACE4_ACCESS_DENIED_ACE_TYPE 0x0001
|
||
|
@@ -61,6 +70,7 @@ struct richacl {
|
||
|
/*#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x0010*/
|
||
|
/*#define ACE4_FAILED_ACCESS_ACE_FLAG 0x0020*/
|
||
|
#define ACE4_IDENTIFIER_GROUP 0x0040
|
||
|
+#define ACE4_INHERITED_ACE 0x0080
|
||
|
/* in-memory representation only */
|
||
|
#define ACE4_SPECIAL_WHO 0x4000
|
||
|
|
||
|
@@ -69,7 +79,8 @@ struct richacl {
|
||
|
ACE4_DIRECTORY_INHERIT_ACE | \
|
||
|
ACE4_NO_PROPAGATE_INHERIT_ACE | \
|
||
|
ACE4_INHERIT_ONLY_ACE | \
|
||
|
- ACE4_IDENTIFIER_GROUP)
|
||
|
+ ACE4_IDENTIFIER_GROUP | \
|
||
|
+ ACE4_INHERITED_ACE)
|
||
|
|
||
|
/* e_mask bitflags */
|
||
|
#define ACE4_READ_DATA 0x00000001
|
||
|
@@ -162,6 +173,18 @@ richacl_put(struct richacl *acl)
|
||
|
kfree(acl);
|
||
|
}
|
||
|
|
||
|
+static inline int
|
||
|
+richacl_is_auto_inherit(const struct richacl *acl)
|
||
|
+{
|
||
|
+ return acl->a_flags & ACL4_AUTO_INHERIT;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int
|
||
|
+richacl_is_protected(const struct richacl *acl)
|
||
|
+{
|
||
|
+ return acl->a_flags & ACL4_PROTECTED;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Special e_who identifiers: we use these pointer values in comparisons
|
||
|
* instead of doing a strcmp.
|