hfsplus: integrate POSIX ACLs support into driver
authorVyacheslav Dubeyko <slava@dubeyko.com>
Wed, 11 Sep 2013 21:24:30 +0000 (14:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Sep 2013 22:59:01 +0000 (15:59 -0700)
Integrate implemented POSIX ACLs support into hfsplus driver.

Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/hfsplus/Makefile
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/hfsplus/xattr.c
fs/hfsplus/xattr.h
fs/hfsplus/xattr_security.c

index 09d278bb7b91f57d2061f66c1ffed63d45ff3ea3..683fca2e5e65a479b89be09ee3be3d289a4ee358 100644 (file)
@@ -7,3 +7,5 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
 hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
                bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
                attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
+
+hfsplus-$(CONFIG_HFSPLUS_FS_POSIX_ACL) += posix_acl.o
index d8ce4bd17fc5f43058eaae416532b2e4019cc870..4a4fea0026735c8fb365d031c57165888e9bb079 100644 (file)
@@ -16,6 +16,7 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
+#include "acl.h"
 
 static inline void hfsplus_instantiate(struct dentry *dentry,
                                       struct inode *inode, u32 cnid)
@@ -529,6 +530,9 @@ const struct inode_operations hfsplus_dir_inode_operations = {
        .getxattr               = generic_getxattr,
        .listxattr              = hfsplus_listxattr,
        .removexattr            = hfsplus_removexattr,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+       .get_acl                = hfsplus_get_posix_acl,
+#endif
 };
 
 const struct file_operations hfsplus_dir_operations = {
index f833d35630abbd4d98c4ca322e32704d792cf9e9..4d2edaea891c164586686c1577c87d4d14fc2f3f 100644 (file)
@@ -19,6 +19,7 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
+#include "acl.h"
 
 static int hfsplus_readpage(struct file *file, struct page *page)
 {
@@ -316,6 +317,13 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
 
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
+
+       if (attr->ia_valid & ATTR_MODE) {
+               error = hfsplus_posix_acl_chmod(inode);
+               if (unlikely(error))
+                       return error;
+       }
+
        return 0;
 }
 
@@ -383,6 +391,9 @@ static const struct inode_operations hfsplus_file_inode_operations = {
        .getxattr       = generic_getxattr,
        .listxattr      = hfsplus_listxattr,
        .removexattr    = hfsplus_removexattr,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+       .get_acl        = hfsplus_get_posix_acl,
+#endif
 };
 
 static const struct file_operations hfsplus_file_operations = {
index f66346155df5cc17f5189760c6ad4d17ee08e979..bd8471fb9a6a80fdf74abdbd673714931c0b7867 100644 (file)
@@ -8,11 +8,16 @@
 
 #include "hfsplus_fs.h"
 #include "xattr.h"
+#include "acl.h"
 
 const struct xattr_handler *hfsplus_xattr_handlers[] = {
        &hfsplus_xattr_osx_handler,
        &hfsplus_xattr_user_handler,
        &hfsplus_xattr_trusted_handler,
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+       &hfsplus_xattr_acl_access_handler,
+       &hfsplus_xattr_acl_default_handler,
+#endif
        &hfsplus_xattr_security_handler,
        NULL
 };
@@ -46,11 +51,58 @@ static inline int is_known_namespace(const char *name)
        return true;
 }
 
+static int can_set_system_xattr(struct inode *inode, const char *name,
+                               const void *value, size_t size)
+{
+#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
+       struct posix_acl *acl;
+       int err;
+
+       if (!inode_owner_or_capable(inode))
+               return -EPERM;
+
+       /*
+        * POSIX_ACL_XATTR_ACCESS is tied to i_mode
+        */
+       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (acl) {
+                       err = posix_acl_equiv_mode(acl, &inode->i_mode);
+                       posix_acl_release(acl);
+                       if (err < 0)
+                               return err;
+                       mark_inode_dirty(inode);
+               }
+               /*
+                * We're changing the ACL.  Get rid of the cached one
+                */
+               forget_cached_acl(inode, ACL_TYPE_ACCESS);
+
+               return 0;
+       } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               posix_acl_release(acl);
+
+               /*
+                * We're changing the default ACL.  Get rid of the cached one
+                */
+               forget_cached_acl(inode, ACL_TYPE_DEFAULT);
+
+               return 0;
+       }
+#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */
+       return -EOPNOTSUPP;
+}
+
 static int can_set_xattr(struct inode *inode, const char *name,
                                const void *value, size_t value_len)
 {
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-               return -EOPNOTSUPP; /* TODO: implement ACL support */
+               return can_set_system_xattr(inode, name, value, value_len);
 
        if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
                /*
@@ -253,11 +305,10 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
        return len;
 }
 
-static ssize_t hfsplus_getxattr_finder_info(struct dentry *dentry,
+static ssize_t hfsplus_getxattr_finder_info(struct inode *inode,
                                                void *value, size_t size)
 {
        ssize_t res = 0;
-       struct inode *inode = dentry->d_inode;
        struct hfs_find_data fd;
        u16 entry_type;
        u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo);
@@ -304,10 +355,9 @@ end_getxattr_finder_info:
        return res;
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
                         void *value, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
        struct hfs_find_data fd;
        hfsplus_attr_entry *entry;
        __be32 xattr_record_type;
@@ -333,7 +383,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
        }
 
        if (!strcmp_xattr_finder_info(name))
-               return hfsplus_getxattr_finder_info(dentry, value, size);
+               return hfsplus_getxattr_finder_info(inode, value, size);
 
        if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
                return -EOPNOTSUPP;
index 847b695b984dfe22148cfb61a4708ac844221d66..841b5698c0fc4b5375c8d5e153fea62bdc931da9 100644 (file)
@@ -14,8 +14,8 @@
 extern const struct xattr_handler hfsplus_xattr_osx_handler;
 extern const struct xattr_handler hfsplus_xattr_user_handler;
 extern const struct xattr_handler hfsplus_xattr_trusted_handler;
-/*extern const struct xattr_handler hfsplus_xattr_acl_access_handler;*/
-/*extern const struct xattr_handler hfsplus_xattr_acl_default_handler;*/
+extern const struct xattr_handler hfsplus_xattr_acl_access_handler;
+extern const struct xattr_handler hfsplus_xattr_acl_default_handler;
 extern const struct xattr_handler hfsplus_xattr_security_handler;
 
 extern const struct xattr_handler *hfsplus_xattr_handlers[];
@@ -29,9 +29,17 @@ static inline int hfsplus_setxattr(struct dentry *dentry, const char *name,
        return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags);
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
                        void *value, size_t size);
 
+static inline ssize_t hfsplus_getxattr(struct dentry *dentry,
+                                       const char *name,
+                                       void *value,
+                                       size_t size)
+{
+       return __hfsplus_getxattr(dentry->d_inode, name, value, size);
+}
+
 ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 int hfsplus_removexattr(struct dentry *dentry, const char *name);
@@ -39,22 +47,7 @@ int hfsplus_removexattr(struct dentry *dentry, const char *name);
 int hfsplus_init_security(struct inode *inode, struct inode *dir,
                                const struct qstr *qstr);
 
-static inline int hfsplus_init_acl(struct inode *inode, struct inode *dir)
-{
-       /*TODO: implement*/
-       return 0;
-}
-
-static inline int hfsplus_init_inode_security(struct inode *inode,
-                                               struct inode *dir,
-                                               const struct qstr *qstr)
-{
-       int err;
-
-       err = hfsplus_init_acl(inode, dir);
-       if (!err)
-               err = hfsplus_init_security(inode, dir, qstr);
-       return err;
-}
+int hfsplus_init_inode_security(struct inode *inode, struct inode *dir,
+                               const struct qstr *qstr);
 
 #endif
index 83b842f113c5924ccaf91607ae9158695eb6a273..00722765ea79b9a689b889623fab0e6213c05570 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/security.h>
 #include "hfsplus_fs.h"
 #include "xattr.h"
+#include "acl.h"
 
 static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
                                        void *buffer, size_t size, int type)
@@ -96,6 +97,18 @@ int hfsplus_init_security(struct inode *inode, struct inode *dir,
                                        &hfsplus_initxattrs, NULL);
 }
 
+int hfsplus_init_inode_security(struct inode *inode,
+                                               struct inode *dir,
+                                               const struct qstr *qstr)
+{
+       int err;
+
+       err = hfsplus_init_posix_acl(inode, dir);
+       if (!err)
+               err = hfsplus_init_security(inode, dir, qstr);
+       return err;
+}
+
 const struct xattr_handler hfsplus_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = hfsplus_security_listxattr,