Message ID | 20131223143706.GA8235@infradead.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, 2013-12-23 at 06:37 -0800, Christoph Hellwig wrote: > On Mon, Dec 23, 2013 at 10:40:09AM +0400, Vyacheslav Dubeyko wrote: > > Maybe I missed something, but I can see that this check is removed only. > > Could you point out the code in your patch that it checks and forbids > > such combination as "osx.security.*", "osx.trusted.*" and so on? > > @@ -941,6 +857,9 @@ static int hfsplus_osx_setxattr(struct dentry > *dentry, const char *name, > if (len > HFSPLUS_ATTR_MAX_STRLEN) > return -EOPNOTSUPP; > > + if (is_known_namespace(name)) > + return -EOPNOTSUPP; > + > Yes, now I've realized your approach. You are right. It's my misunderstanding. So, comments are really necessary for describing the goal of this check. Thank you for adding it in the last version of reworked patch. > > > So, if it needs to use xattr handler only for removing then it needs to > > make some refactoring of using __hfsplus_setxattr() and > > hfsplus_removexattr() or merging these two functions into one. And I > > think that merging is better idea. > > I've not done the full merge, but below is an updated patch to make > sure hfsplus uses the handlers for the remove case, and making sure > the adding/striping of the prefix for the osv handlers is more > transparent: > As far as I can judge, changing from hfsplus_removexattr() to generic_removexattr() is made correctly. > diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c > index 9ee6298..bdec665 100644 > --- a/fs/hfsplus/dir.c > +++ b/fs/hfsplus/dir.c > @@ -529,7 +529,7 @@ const struct inode_operations hfsplus_dir_inode_operations = { > .setxattr = generic_setxattr, > .getxattr = generic_getxattr, > .listxattr = hfsplus_listxattr, > - .removexattr = hfsplus_removexattr, > + .removexattr = generic_removexattr, > #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL > .get_acl = hfsplus_get_posix_acl, > .set_acl = hfsplus_set_posix_acl, > diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c > index 2e10993..83c9166 100644 > --- a/fs/hfsplus/inode.c > +++ b/fs/hfsplus/inode.c > @@ -390,7 +390,7 @@ static const struct inode_operations hfsplus_file_inode_operations = { > .setxattr = generic_setxattr, > .getxattr = generic_getxattr, > .listxattr = hfsplus_listxattr, > - .removexattr = hfsplus_removexattr, > + .removexattr = generic_removexattr, > #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL > .get_acl = hfsplus_get_posix_acl, > .set_acl = hfsplus_set_posix_acl, > diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c > index bf88baa..c838b84 100644 > --- a/fs/hfsplus/xattr.c > +++ b/fs/hfsplus/xattr.c > @@ -11,6 +11,8 @@ > #include "xattr.h" > #include "acl.h" > > +static int hfsplus_removexattr(struct inode *inode, const char *name); > + > const struct xattr_handler *hfsplus_xattr_handlers[] = { > &hfsplus_xattr_osx_handler, > &hfsplus_xattr_user_handler, > @@ -52,82 +54,6 @@ 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 can_set_system_xattr(inode, name, value, value_len); > - > - if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) { > - /* > - * This makes sure that we aren't trying to set an > - * attribute in a different namespace by prefixing it > - * with "osx." > - */ > - if (is_known_namespace(name + XATTR_MAC_OSX_PREFIX_LEN)) > - return -EOPNOTSUPP; > - > - return 0; > - } > - > - /* > - * Don't allow setting an attribute in an unknown namespace. > - */ > - if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) && > - strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && > - strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) > - return -EOPNOTSUPP; > - > - return 0; > -} > - > static void hfsplus_init_header_node(struct inode *attr_file, > u32 clump_size, > char *buf, u16 node_size) > @@ -350,18 +276,8 @@ int __hfsplus_setxattr(struct inode *inode, const char *name, > HFSPLUS_IS_RSRC(inode)) > return -EOPNOTSUPP; > > - err = can_set_xattr(inode, name, value, size); > - if (err) > - return err; > - > - if (strncmp(name, XATTR_MAC_OSX_PREFIX, > - XATTR_MAC_OSX_PREFIX_LEN) == 0) > - name += XATTR_MAC_OSX_PREFIX_LEN; Removing this skipping of virtual "osx." prefix means that you save it on volume. But such action means volume corruption really. Because HFS+ volume hasn't such prefixes for xattrs in AttributesFile. Usually, special xattrs has prefix "com.apple.*" but others haven't any prefix and can be named as you want. So, I think that it is not correct modification. > - > - if (value == NULL) { > - value = ""; > - size = 0; > - } > + if (value == NULL) > + return hfsplus_removexattr(inode, name); > > err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd); > if (err) { > @@ -577,18 +493,6 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, > HFSPLUS_IS_RSRC(inode)) > return -EOPNOTSUPP; > > - if (strncmp(name, XATTR_MAC_OSX_PREFIX, > - XATTR_MAC_OSX_PREFIX_LEN) == 0) { > - /* skip "osx." prefix */ > - name += XATTR_MAC_OSX_PREFIX_LEN; Ditto. This skipping is made because virtual prefix was added by user or on listxattr phase. But we should use for searching on a volume the name without "osx." prefix. Otherwise, how do you get "com.apple.system.Security" xattr from volume, for example? You will search "osx.com.apple.system.Security" that doesn't exist on HFS+ volume. Thanks, Vyacheslav Dubeyko. -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 9ee6298..bdec665 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -529,7 +529,7 @@ const struct inode_operations hfsplus_dir_inode_operations = { .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = hfsplus_listxattr, - .removexattr = hfsplus_removexattr, + .removexattr = generic_removexattr, #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL .get_acl = hfsplus_get_posix_acl, .set_acl = hfsplus_set_posix_acl, diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 2e10993..83c9166 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -390,7 +390,7 @@ static const struct inode_operations hfsplus_file_inode_operations = { .setxattr = generic_setxattr, .getxattr = generic_getxattr, .listxattr = hfsplus_listxattr, - .removexattr = hfsplus_removexattr, + .removexattr = generic_removexattr, #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL .get_acl = hfsplus_get_posix_acl, .set_acl = hfsplus_set_posix_acl, diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index bf88baa..c838b84 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -11,6 +11,8 @@ #include "xattr.h" #include "acl.h" +static int hfsplus_removexattr(struct inode *inode, const char *name); + const struct xattr_handler *hfsplus_xattr_handlers[] = { &hfsplus_xattr_osx_handler, &hfsplus_xattr_user_handler, @@ -52,82 +54,6 @@ 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 can_set_system_xattr(inode, name, value, value_len); - - if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) { - /* - * This makes sure that we aren't trying to set an - * attribute in a different namespace by prefixing it - * with "osx." - */ - if (is_known_namespace(name + XATTR_MAC_OSX_PREFIX_LEN)) - return -EOPNOTSUPP; - - return 0; - } - - /* - * Don't allow setting an attribute in an unknown namespace. - */ - if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) && - strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) && - strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) - return -EOPNOTSUPP; - - return 0; -} - static void hfsplus_init_header_node(struct inode *attr_file, u32 clump_size, char *buf, u16 node_size) @@ -350,18 +276,8 @@ int __hfsplus_setxattr(struct inode *inode, const char *name, HFSPLUS_IS_RSRC(inode)) return -EOPNOTSUPP; - err = can_set_xattr(inode, name, value, size); - if (err) - return err; - - if (strncmp(name, XATTR_MAC_OSX_PREFIX, - XATTR_MAC_OSX_PREFIX_LEN) == 0) - name += XATTR_MAC_OSX_PREFIX_LEN; - - if (value == NULL) { - value = ""; - size = 0; - } + if (value == NULL) + return hfsplus_removexattr(inode, name); err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd); if (err) { @@ -577,18 +493,6 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, HFSPLUS_IS_RSRC(inode)) return -EOPNOTSUPP; - if (strncmp(name, XATTR_MAC_OSX_PREFIX, - XATTR_MAC_OSX_PREFIX_LEN) == 0) { - /* skip "osx." prefix */ - name += XATTR_MAC_OSX_PREFIX_LEN; - /* - * Don't allow retrieving properly prefixed attributes - * by prepending them with "osx." - */ - if (is_known_namespace(name)) - return -EOPNOTSUPP; - } - if (!strcmp_xattr_finder_info(name)) return hfsplus_getxattr_finder_info(inode, value, size); @@ -823,32 +727,18 @@ end_listxattr: return res; } -int hfsplus_removexattr(struct dentry *dentry, const char *name) +static int hfsplus_removexattr(struct inode *inode, const char *name) { int err = 0; - struct inode *inode = dentry->d_inode; struct hfs_find_data cat_fd; u16 flags; u16 cat_entry_type; int is_xattr_acl_deleted = 0; int is_all_xattrs_deleted = 0; - if ((!S_ISREG(inode->i_mode) && - !S_ISDIR(inode->i_mode)) || - HFSPLUS_IS_RSRC(inode)) - return -EOPNOTSUPP; - if (!HFSPLUS_SB(inode->i_sb)->attr_tree) return -EOPNOTSUPP; - err = can_set_xattr(inode, name, NULL, 0); - if (err) - return err; - - if (strncmp(name, XATTR_MAC_OSX_PREFIX, - XATTR_MAC_OSX_PREFIX_LEN) == 0) - name += XATTR_MAC_OSX_PREFIX_LEN; - if (!strcmp_xattr_finder_info(name)) return -EOPNOTSUPP; @@ -922,8 +812,12 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name, if (len > HFSPLUS_ATTR_MAX_STRLEN) return -EOPNOTSUPP; - strcpy(xattr_name, XATTR_MAC_OSX_PREFIX); - strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name); + /* + * Don't allow retrieving properly prefixed attributes + * by prepending them with "osx." + */ + if (is_known_namespace(name)) + return -EOPNOTSUPP; return hfsplus_getxattr(dentry, xattr_name, buffer, size); } @@ -941,8 +835,12 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name, if (len > HFSPLUS_ATTR_MAX_STRLEN) return -EOPNOTSUPP; - strcpy(xattr_name, XATTR_MAC_OSX_PREFIX); - strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name); + /* + * Don't allow setting properly prefixed attributes + * by prepending them with "osx." + */ + if (is_known_namespace(name)) + return -EOPNOTSUPP; return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags); } diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h index 9e21449..288530c 100644 --- a/fs/hfsplus/xattr.h +++ b/fs/hfsplus/xattr.h @@ -40,8 +40,6 @@ static inline ssize_t hfsplus_getxattr(struct dentry *dentry, ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size); -int hfsplus_removexattr(struct dentry *dentry, const char *name); - int hfsplus_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr);