diff options
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/Makefile | 2 | ||||
-rw-r--r-- | fs/hfsplus/dir.c | 4 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 11 | ||||
-rw-r--r-- | fs/hfsplus/xattr.c | 62 | ||||
-rw-r--r-- | fs/hfsplus/xattr.h | 33 | ||||
-rw-r--r-- | fs/hfsplus/xattr_security.c | 13 |
6 files changed, 99 insertions, 26 deletions
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile index 09d278bb7b9..683fca2e5e6 100644 --- a/fs/hfsplus/Makefile +++ b/fs/hfsplus/Makefile @@ -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 diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index d8ce4bd17fc..4a4fea00267 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -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 = { diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f833d35630a..4d2edaea891 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -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 = { diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index f66346155df..bd8471fb9a6 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -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; diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h index 847b695b984..841b5698c0f 100644 --- a/fs/hfsplus/xattr.h +++ b/fs/hfsplus/xattr.h @@ -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 diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c index 83b842f113c..00722765ea7 100644 --- a/fs/hfsplus/xattr_security.c +++ b/fs/hfsplus/xattr_security.c @@ -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, |