diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2015-11-02 20:56:17 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-11-02 20:56:17 -0500 |
commit | 47e1bf640558237b79d3009fb7dfe157f12f4f7a (patch) | |
tree | 8fbbf691d4618d7e484eb11242b1343f88cdaa67 | |
parent | 09cb22d2a57b51d7d052dfe508f260abc67b69b6 (diff) |
xfs: invalidate cached acl if set via ioctl
Setting or removing the "SGI_ACL_[FILE|DEFAULT]" attributes via the
XFS_IOC_ATTRMULTI_BY_HANDLE ioctl completely bypasses the POSIX ACL
infrastructure, like setting the "trusted.SGI_ACL_[FILE|DEFAULT]" xattrs
did until commit 6caa1056. Similar to that commit, invalidate cached
acls when setting/removing them via the ioctl as well.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/xfs_acl.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_xattr.c | 38 |
3 files changed, 36 insertions, 15 deletions
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 3841b07f27bf..75af0a4d9028 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h | |||
@@ -36,4 +36,7 @@ static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) | |||
36 | # define posix_acl_access_exists(inode) 0 | 36 | # define posix_acl_access_exists(inode) 0 |
37 | # define posix_acl_default_exists(inode) 0 | 37 | # define posix_acl_default_exists(inode) 0 |
38 | #endif /* CONFIG_XFS_POSIX_ACL */ | 38 | #endif /* CONFIG_XFS_POSIX_ACL */ |
39 | |||
40 | extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); | ||
41 | |||
39 | #endif /* __XFS_ACL_H__ */ | 42 | #endif /* __XFS_ACL_H__ */ |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index e939c20cb4de..67bb2983c036 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "xfs_symlink.h" | 40 | #include "xfs_symlink.h" |
41 | #include "xfs_trans.h" | 41 | #include "xfs_trans.h" |
42 | #include "xfs_pnfs.h" | 42 | #include "xfs_pnfs.h" |
43 | #include "xfs_acl.h" | ||
43 | 44 | ||
44 | #include <linux/capability.h> | 45 | #include <linux/capability.h> |
45 | #include <linux/dcache.h> | 46 | #include <linux/dcache.h> |
@@ -494,6 +495,8 @@ xfs_attrmulti_attr_set( | |||
494 | return PTR_ERR(kbuf); | 495 | return PTR_ERR(kbuf); |
495 | 496 | ||
496 | error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); | 497 | error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); |
498 | if (!error) | ||
499 | xfs_forget_acl(inode, name, flags); | ||
497 | kfree(kbuf); | 500 | kfree(kbuf); |
498 | return error; | 501 | return error; |
499 | } | 502 | } |
@@ -504,9 +507,14 @@ xfs_attrmulti_attr_remove( | |||
504 | unsigned char *name, | 507 | unsigned char *name, |
505 | __uint32_t flags) | 508 | __uint32_t flags) |
506 | { | 509 | { |
510 | int error; | ||
511 | |||
507 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 512 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
508 | return -EPERM; | 513 | return -EPERM; |
509 | return xfs_attr_remove(XFS_I(inode), name, flags); | 514 | error = xfs_attr_remove(XFS_I(inode), name, flags); |
515 | if (!error) | ||
516 | xfs_forget_acl(inode, name, flags); | ||
517 | return error; | ||
510 | } | 518 | } |
511 | 519 | ||
512 | STATIC int | 520 | STATIC int |
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 1e08d3e85cd0..8294f86441bf 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c | |||
@@ -53,6 +53,28 @@ xfs_xattr_get(struct dentry *dentry, const char *name, | |||
53 | return asize; | 53 | return asize; |
54 | } | 54 | } |
55 | 55 | ||
56 | void | ||
57 | xfs_forget_acl( | ||
58 | struct inode *inode, | ||
59 | const char *name, | ||
60 | int xflags) | ||
61 | { | ||
62 | /* | ||
63 | * Invalidate any cached ACLs if the user has bypassed the ACL | ||
64 | * interface. We don't validate the content whatsoever so it is caller | ||
65 | * responsibility to provide data in valid format and ensure i_mode is | ||
66 | * consistent. | ||
67 | */ | ||
68 | if (xflags & ATTR_ROOT) { | ||
69 | #ifdef CONFIG_XFS_POSIX_ACL | ||
70 | if (!strcmp(name, SGI_ACL_FILE)) | ||
71 | forget_cached_acl(inode, ACL_TYPE_ACCESS); | ||
72 | else if (!strcmp(name, SGI_ACL_DEFAULT)) | ||
73 | forget_cached_acl(inode, ACL_TYPE_DEFAULT); | ||
74 | #endif | ||
75 | } | ||
76 | } | ||
77 | |||
56 | static int | 78 | static int |
57 | xfs_xattr_set(struct dentry *dentry, const char *name, const void *value, | 79 | xfs_xattr_set(struct dentry *dentry, const char *name, const void *value, |
58 | size_t size, int flags, int xflags) | 80 | size_t size, int flags, int xflags) |
@@ -73,20 +95,8 @@ xfs_xattr_set(struct dentry *dentry, const char *name, const void *value, | |||
73 | return xfs_attr_remove(ip, (unsigned char *)name, xflags); | 95 | return xfs_attr_remove(ip, (unsigned char *)name, xflags); |
74 | error = xfs_attr_set(ip, (unsigned char *)name, | 96 | error = xfs_attr_set(ip, (unsigned char *)name, |
75 | (void *)value, size, xflags); | 97 | (void *)value, size, xflags); |
76 | /* | 98 | if (!error) |
77 | * Invalidate any cached ACLs if the user has bypassed the ACL | 99 | xfs_forget_acl(d_inode(dentry), name, xflags); |
78 | * interface. We don't validate the content whatsoever so it is caller | ||
79 | * responsibility to provide data in valid format and ensure i_mode is | ||
80 | * consistent. | ||
81 | */ | ||
82 | #ifdef CONFIG_XFS_POSIX_ACL | ||
83 | if (!error && (xflags & ATTR_ROOT)) { | ||
84 | if (!strcmp(name, SGI_ACL_FILE)) | ||
85 | forget_cached_acl(VFS_I(ip), ACL_TYPE_ACCESS); | ||
86 | else if (!strcmp(name, SGI_ACL_DEFAULT)) | ||
87 | forget_cached_acl(VFS_I(ip), ACL_TYPE_DEFAULT); | ||
88 | } | ||
89 | #endif | ||
90 | 100 | ||
91 | return error; | 101 | return error; |
92 | } | 102 | } |