aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:40 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:17 -0500
commit2aeccbe957d0d2b9fbb2a236e53a955097e2a9ce (patch)
treeb07768d451a0d4b4be65096f9462660e856e6798
parent893d46e443346370cd4ea81d9d35f72952c62a37 (diff)
fs: add generic xattr_acl handlers
With the ->set_acl inode operation we can implement the Posix ACL xattr handlers in generic code instead of duplicating them all over the tree. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/posix_acl.c102
-rw-r--r--include/linux/posix_acl_xattr.h3
2 files changed, 105 insertions, 0 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 30524de49a6b..e699b076cdd8 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -17,6 +17,7 @@
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/posix_acl.h> 18#include <linux/posix_acl.h>
19#include <linux/posix_acl_xattr.h> 19#include <linux/posix_acl_xattr.h>
20#include <linux/xattr.h>
20#include <linux/export.h> 21#include <linux/export.h>
21#include <linux/user_namespace.h> 22#include <linux/user_namespace.h>
22 23
@@ -611,3 +612,104 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
611 return real_size; 612 return real_size;
612} 613}
613EXPORT_SYMBOL (posix_acl_to_xattr); 614EXPORT_SYMBOL (posix_acl_to_xattr);
615
616static int
617posix_acl_xattr_get(struct dentry *dentry, const char *name,
618 void *value, size_t size, int type)
619{
620 struct posix_acl *acl;
621 int error;
622
623 if (!IS_POSIXACL(dentry->d_inode))
624 return -EOPNOTSUPP;
625 if (S_ISLNK(dentry->d_inode->i_mode))
626 return -EOPNOTSUPP;
627
628 acl = get_acl(dentry->d_inode, type);
629 if (IS_ERR(acl))
630 return PTR_ERR(acl);
631 if (acl == NULL)
632 return -ENODATA;
633
634 error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
635 posix_acl_release(acl);
636
637 return error;
638}
639
640static int
641posix_acl_xattr_set(struct dentry *dentry, const char *name,
642 const void *value, size_t size, int flags, int type)
643{
644 struct inode *inode = dentry->d_inode;
645 struct posix_acl *acl = NULL;
646 int ret;
647
648 if (!IS_POSIXACL(inode))
649 return -EOPNOTSUPP;
650 if (!inode->i_op->set_acl)
651 return -EOPNOTSUPP;
652
653 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
654 return value ? -EACCES : 0;
655 if (!inode_owner_or_capable(inode))
656 return -EPERM;
657
658 if (value) {
659 acl = posix_acl_from_xattr(&init_user_ns, value, size);
660 if (IS_ERR(acl))
661 return PTR_ERR(acl);
662
663 if (acl) {
664 ret = posix_acl_valid(acl);
665 if (ret)
666 goto out;
667 }
668 }
669
670 ret = inode->i_op->set_acl(inode, acl, type);
671out:
672 posix_acl_release(acl);
673 return ret;
674}
675
676static size_t
677posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
678 const char *name, size_t name_len, int type)
679{
680 const char *xname;
681 size_t size;
682
683 if (!IS_POSIXACL(dentry->d_inode))
684 return -EOPNOTSUPP;
685 if (S_ISLNK(dentry->d_inode->i_mode))
686 return -EOPNOTSUPP;
687
688 if (type == ACL_TYPE_ACCESS)
689 xname = POSIX_ACL_XATTR_ACCESS;
690 else
691 xname = POSIX_ACL_XATTR_DEFAULT;
692
693 size = strlen(xname) + 1;
694 if (list && size <= list_size)
695 memcpy(list, xname, size);
696 return size;
697}
698
699const struct xattr_handler posix_acl_access_xattr_handler = {
700 .prefix = POSIX_ACL_XATTR_ACCESS,
701 .flags = ACL_TYPE_ACCESS,
702 .list = posix_acl_xattr_list,
703 .get = posix_acl_xattr_get,
704 .set = posix_acl_xattr_set,
705};
706EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
707
708const struct xattr_handler posix_acl_default_xattr_handler = {
709 .prefix = POSIX_ACL_XATTR_DEFAULT,
710 .flags = ACL_TYPE_DEFAULT,
711 .list = posix_acl_xattr_list,
712 .get = posix_acl_xattr_get,
713 .set = posix_acl_xattr_set,
714};
715EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
diff --git a/include/linux/posix_acl_xattr.h b/include/linux/posix_acl_xattr.h
index ad93ad0f1db0..6f14ee295822 100644
--- a/include/linux/posix_acl_xattr.h
+++ b/include/linux/posix_acl_xattr.h
@@ -69,4 +69,7 @@ struct posix_acl *posix_acl_from_xattr(struct user_namespace *user_ns,
69int posix_acl_to_xattr(struct user_namespace *user_ns, 69int posix_acl_to_xattr(struct user_namespace *user_ns,
70 const struct posix_acl *acl, void *buffer, size_t size); 70 const struct posix_acl *acl, void *buffer, size_t size);
71 71
72extern const struct xattr_handler posix_acl_access_xattr_handler;
73extern const struct xattr_handler posix_acl_default_xattr_handler;
74
72#endif /* _POSIX_ACL_XATTR_H */ 75#endif /* _POSIX_ACL_XATTR_H */