@@ -358,7 +358,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 & RICHACL_MASKED))
+ (acl->a_flags & RICHACL_MASKED) &&
+ (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl)))
return acl;
clone = richacl_clone(acl, GFP_KERNEL);
@@ -370,6 +371,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 |= RICHACL_PROTECTED;
return clone;
}
@@ -535,6 +538,11 @@ richacl_inherit(const struct richacl *dir_acl, int isdir)
ace++;
}
}
+ if (richacl_is_auto_inherit(dir_acl)) {
+ acl->a_flags = RICHACL_AUTO_INHERIT;
+ richacl_for_each_entry(ace, acl)
+ ace->e_flags |= RICHACE_INHERITED_ACE;
+ }
return acl;
}
@@ -218,6 +218,13 @@ richacl_inherit_inode(const struct richacl *dir_acl, struct inode *inode)
richacl_put(acl);
acl = NULL;
} else {
+ /*
+ * We need to set RICHACL_PROTECTED because we are
+ * doing an implicit chmod
+ */
+ if (richacl_is_auto_inherit(acl))
+ acl->a_flags |= RICHACL_PROTECTED;
+
richacl_compute_max_masks(acl, inode->i_uid);
/*
* Ensure that the acl will not grant any permissions
@@ -53,9 +53,15 @@ struct richacl {
_ace--)
/* a_flag values */
+#define RICHACL_AUTO_INHERIT 0x01
+#define RICHACL_PROTECTED 0x02
+#define RICHACL_DEFAULTED 0x04
#define RICHACL_MASKED 0x80
-#define RICHACL_VALID_FLAGS ( \
+#define RICHACL_VALID_FLAGS ( \
+ RICHACL_AUTO_INHERIT | \
+ RICHACL_PROTECTED | \
+ RICHACL_DEFAULTED | \
RICHACL_MASKED)
/* e_type values */
@@ -68,6 +74,7 @@ struct richacl {
#define RICHACE_NO_PROPAGATE_INHERIT_ACE 0x0004
#define RICHACE_INHERIT_ONLY_ACE 0x0008
#define RICHACE_IDENTIFIER_GROUP 0x0040
+#define RICHACE_INHERITED_ACE 0x0080
#define RICHACE_SPECIAL_WHO 0x4000
#define RICHACE_VALID_FLAGS ( \
@@ -76,6 +83,7 @@ struct richacl {
RICHACE_NO_PROPAGATE_INHERIT_ACE | \
RICHACE_INHERIT_ONLY_ACE | \
RICHACE_IDENTIFIER_GROUP | \
+ RICHACE_INHERITED_ACE | \
RICHACE_SPECIAL_WHO)
/* e_mask bitflags */
@@ -187,6 +195,18 @@ extern void set_cached_richacl(struct inode *, struct richacl *);
extern void forget_cached_richacl(struct inode *);
extern struct richacl *get_richacl(struct inode *);
+static inline int
+richacl_is_auto_inherit(const struct richacl *acl)
+{
+ return acl->a_flags & RICHACL_AUTO_INHERIT;
+}
+
+static inline int
+richacl_is_protected(const struct richacl *acl)
+{
+ return acl->a_flags & RICHACL_PROTECTED;
+}
+
/**
* richace_is_owner - check if @ace is an OWNER@ entry
*/
@@ -268,7 +288,8 @@ richace_clear_inheritance_flags(struct richace *ace)
ace->e_flags &= ~(RICHACE_FILE_INHERIT_ACE |
RICHACE_DIRECTORY_INHERIT_ACE |
RICHACE_NO_PROPAGATE_INHERIT_ACE |
- RICHACE_INHERIT_ONLY_ACE);
+ RICHACE_INHERIT_ONLY_ACE |
+ RICHACE_INHERITED_ACE);
}
/**