On Mon, Sep 05, 2011 at 10:55:42PM +0530, Aneesh Kumar K.V wrote: > From: Andreas Gruenbacher <agruen@xxxxxxxxxx> > > 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; and sort of racy, I guess. > a per-create or > per-process flag indicating to ignore the create mode when AI is in > effect would fix this problem. Hm. OK. --b. > > Signed-off-by: Andreas Gruenbacher <agruen@xxxxxxxxxx> > Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> > --- > fs/richacl_base.c | 10 +++++++++- > fs/richacl_inode.c | 7 ++++++- > include/linux/richacl.h | 25 +++++++++++++++++++++++-- > 3 files changed, 38 insertions(+), 4 deletions(-) > > diff --git a/fs/richacl_base.c b/fs/richacl_base.c > index 9d61c34..2cdc244 100644 > --- a/fs/richacl_base.c > +++ b/fs/richacl_base.c > @@ -377,7 +377,8 @@ richacl_chmod(struct richacl *acl, mode_t mode) > if (acl->a_owner_mask == owner_mask && > acl->a_group_mask == group_mask && > acl->a_other_mask == other_mask && > - (acl->a_flags & ACL4_MASKED)) > + (acl->a_flags & ACL4_MASKED) && > + (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl))) > return acl; > > clone = richacl_clone(acl); > @@ -389,6 +390,8 @@ richacl_chmod(struct richacl *acl, mode_t 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; > } > @@ -558,6 +561,11 @@ richacl_inherit(const struct richacl *dir_acl, int isdir) > ace++; > } > } > + if (richacl_is_auto_inherit(dir_acl)) { > + acl->a_flags = ACL4_AUTO_INHERIT; > + richacl_for_each_entry(ace, acl) > + ace->e_flags |= ACE4_INHERITED_ACE; > + } > > return acl; > } > diff --git a/fs/richacl_inode.c b/fs/richacl_inode.c > index a8d2beb..be6c3eb 100644 > --- a/fs/richacl_inode.c > +++ b/fs/richacl_inode.c > @@ -37,9 +37,14 @@ richacl_inherit_inode(const struct richacl *dir_acl, struct inode *inode) > > acl = richacl_inherit(dir_acl, S_ISDIR(inode->i_mode)); > if (acl) { > + /* > + * We need to set ACL4_PROTECTED because we are > + * doing an implicit chmod > + */ > + if (richacl_is_auto_inherit(acl)) > + acl->a_flags |= ACL4_PROTECTED; > > richacl_compute_max_masks(acl); > - > /* > * Ensure that the acl will not grant any permissions beyond > * the create mode. > diff --git a/include/linux/richacl.h b/include/linux/richacl.h > index d18c4a6..ca07209 100644 > --- a/include/linux/richacl.h > +++ b/include/linux/richacl.h > @@ -47,10 +47,16 @@ struct richacl { > _ace != _acl->a_entries - 1; \ > _ace--) > > +/* a_flags values */ > +#define ACL4_AUTO_INHERIT 0x01 > +#define ACL4_PROTECTED 0x02 > +/* #define ACL4_DEFAULTED 0x04 */ > /* Flag values defined by rich-acl */ > #define ACL4_MASKED 0x80 > > #define ACL4_VALID_FLAGS ( \ > + ACL4_AUTO_INHERIT | \ > + ACL4_PROTECTED | \ > ACL4_MASKED) > > /* e_type values */ > @@ -67,6 +73,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 > > @@ -75,7 +82,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 > @@ -181,6 +189,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. > @@ -259,7 +279,8 @@ richace_clear_inheritance_flags(struct richace *ace) > ace->e_flags &= ~(ACE4_FILE_INHERIT_ACE | > ACE4_DIRECTORY_INHERIT_ACE | > ACE4_NO_PROPAGATE_INHERIT_ACE | > - ACE4_INHERIT_ONLY_ACE); > + ACE4_INHERIT_ONLY_ACE | > + ACE4_INHERITED_ACE); > } > > /** > -- > 1.7.4.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html