80 lines
2.7 KiB
Diff
80 lines
2.7 KiB
Diff
From: Andreas Gruenbacher <agruen@suse.de>
|
|
Date: Fri, 11 Jun 2010 16:12:47 +0530
|
|
Subject: [PATCH 07/16] richacl: Update the file masks in chmod()
|
|
Patch-mainline: not yet
|
|
|
|
Doing a chmod() sets the file mode, which includes the file permission
|
|
bits. When a file has a richacl, the permissions that the richacl
|
|
grants need to be limited to what the new file permission bits allow.
|
|
|
|
This is done by setting the file masks in the richacl to what the file
|
|
permission bits map to. The richacl access check algorithm takes the
|
|
file masks into account, which ensures that the richacl cannot grant too
|
|
many permissions.
|
|
|
|
It is possible to explicitly add permissions to the file masks which go
|
|
beyond what the file permission bits can grant (like the ACE4_WRITE_ACL
|
|
permission). The POSIX.1 standard calls this an alternate file access
|
|
control mechanism. A subsequent chmod() would ensure that those
|
|
permissions are disabled again.
|
|
|
|
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 | 37 +++++++++++++++++++++++++++++++++++++
|
|
include/linux/richacl.h | 1 +
|
|
2 files changed, 38 insertions(+)
|
|
|
|
--- a/fs/richacl_base.c
|
|
+++ b/fs/richacl_base.c
|
|
@@ -330,3 +330,40 @@ restart:
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(richacl_compute_max_masks);
|
|
+
|
|
+/**
|
|
+ * richacl_chmod - update the file masks to reflect the new mode
|
|
+ * @mode: new file permission bits
|
|
+ *
|
|
+ * Return a copy of @acl where the file masks have been replaced by the file
|
|
+ * masks corresponding to the file permission bits in @mode, or returns @acl
|
|
+ * itself if the file masks are already up to date. Takes over a reference
|
|
+ * to @acl.
|
|
+ */
|
|
+struct richacl *
|
|
+richacl_chmod(struct richacl *acl, mode_t mode)
|
|
+{
|
|
+ unsigned int owner_mask, group_mask, other_mask;
|
|
+ struct richacl *clone;
|
|
+
|
|
+ owner_mask = richacl_mode_to_mask(mode >> 6);
|
|
+ group_mask = richacl_mode_to_mask(mode >> 3);
|
|
+ other_mask = richacl_mode_to_mask(mode);
|
|
+
|
|
+ if (acl->a_owner_mask == owner_mask &&
|
|
+ acl->a_group_mask == group_mask &&
|
|
+ acl->a_other_mask == other_mask)
|
|
+ return acl;
|
|
+
|
|
+ clone = richacl_clone(acl);
|
|
+ richacl_put(acl);
|
|
+ if (!clone)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+
|
|
+ clone->a_owner_mask = owner_mask;
|
|
+ clone->a_group_mask = group_mask;
|
|
+ clone->a_other_mask = other_mask;
|
|
+
|
|
+ return clone;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(richacl_chmod);
|
|
--- a/include/linux/richacl.h
|
|
+++ b/include/linux/richacl.h
|
|
@@ -269,5 +269,6 @@ extern int richacl_masks_to_mode(const s
|
|
extern unsigned int richacl_mode_to_mask(mode_t);
|
|
extern unsigned int richacl_want_to_mask(int);
|
|
extern void richacl_compute_max_masks(struct richacl *);
|
|
+extern struct richacl *richacl_chmod(struct richacl *, mode_t);
|
|
|
|
#endif /* __RICHACL_H */
|