diff options
author | Christoph Hellwig <hch@lst.de> | 2014-06-18 05:07:03 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-07-08 14:36:08 -0400 |
commit | 74adf83f5d7720925499b4938f930591f947b660 (patch) | |
tree | 2665f7e14615eb3e0d882603f24710c05b0d522a | |
parent | 66b068604903849c5dee3842eb72564064c64c72 (diff) |
nfs: only show Posix ACLs in listxattr if actually present
The big ACL switched nfs to use generic_listxattr, which calls all existing
->list handlers. Add a custom .listxattr implementation that only lists
the ACLs if they actually are present on the given inode.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reported-by: Philippe Troin <phil@fifi.org>
Tested-by: Philippe Troin <phil@fifi.org>
Fixes: 013cdf1088d7 (nfs: use generic posix ACL infrastructure ...)
Cc: stable@vger.kernel.org # 3.14+
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/nfs3acl.c | 43 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 4 |
2 files changed, 45 insertions, 2 deletions
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 871d6eda8dba..8f854dde4150 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -247,3 +247,46 @@ const struct xattr_handler *nfs3_xattr_handlers[] = { | |||
247 | &posix_acl_default_xattr_handler, | 247 | &posix_acl_default_xattr_handler, |
248 | NULL, | 248 | NULL, |
249 | }; | 249 | }; |
250 | |||
251 | static int | ||
252 | nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data, | ||
253 | size_t size, ssize_t *result) | ||
254 | { | ||
255 | struct posix_acl *acl; | ||
256 | char *p = data + *result; | ||
257 | |||
258 | acl = get_acl(inode, type); | ||
259 | if (!acl) | ||
260 | return 0; | ||
261 | |||
262 | posix_acl_release(acl); | ||
263 | |||
264 | *result += strlen(name); | ||
265 | *result += 1; | ||
266 | if (!size) | ||
267 | return 0; | ||
268 | if (*result > size) | ||
269 | return -ERANGE; | ||
270 | |||
271 | strcpy(p, name); | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | ssize_t | ||
276 | nfs3_listxattr(struct dentry *dentry, char *data, size_t size) | ||
277 | { | ||
278 | struct inode *inode = dentry->d_inode; | ||
279 | ssize_t result = 0; | ||
280 | int error; | ||
281 | |||
282 | error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, | ||
283 | POSIX_ACL_XATTR_ACCESS, data, size, &result); | ||
284 | if (error) | ||
285 | return error; | ||
286 | |||
287 | error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, | ||
288 | POSIX_ACL_XATTR_DEFAULT, data, size, &result); | ||
289 | if (error) | ||
290 | return error; | ||
291 | return result; | ||
292 | } | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index e7daa42bbc86..f0afa291fd58 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -885,7 +885,7 @@ static const struct inode_operations nfs3_dir_inode_operations = { | |||
885 | .getattr = nfs_getattr, | 885 | .getattr = nfs_getattr, |
886 | .setattr = nfs_setattr, | 886 | .setattr = nfs_setattr, |
887 | #ifdef CONFIG_NFS_V3_ACL | 887 | #ifdef CONFIG_NFS_V3_ACL |
888 | .listxattr = generic_listxattr, | 888 | .listxattr = nfs3_listxattr, |
889 | .getxattr = generic_getxattr, | 889 | .getxattr = generic_getxattr, |
890 | .setxattr = generic_setxattr, | 890 | .setxattr = generic_setxattr, |
891 | .removexattr = generic_removexattr, | 891 | .removexattr = generic_removexattr, |
@@ -899,7 +899,7 @@ static const struct inode_operations nfs3_file_inode_operations = { | |||
899 | .getattr = nfs_getattr, | 899 | .getattr = nfs_getattr, |
900 | .setattr = nfs_setattr, | 900 | .setattr = nfs_setattr, |
901 | #ifdef CONFIG_NFS_V3_ACL | 901 | #ifdef CONFIG_NFS_V3_ACL |
902 | .listxattr = generic_listxattr, | 902 | .listxattr = nfs3_listxattr, |
903 | .getxattr = generic_getxattr, | 903 | .getxattr = generic_getxattr, |
904 | .setxattr = generic_setxattr, | 904 | .setxattr = generic_setxattr, |
905 | .removexattr = generic_removexattr, | 905 | .removexattr = generic_removexattr, |