diff options
Diffstat (limited to 'fs/jfs/xattr.c')
| -rw-r--r-- | fs/jfs/xattr.c | 184 | 
1 files changed, 82 insertions, 102 deletions
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 2d7f165d0f1..46325d5c34f 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -382,7 +382,7 @@ static int ea_read(struct inode *ip, struct jfs_ea_list *ealist)  	nbytes = sizeDXD(&ji->ea);  	if (!nbytes) { -		jfs_error(sb, "ea_read: nbytes is 0"); +		jfs_error(sb, "nbytes is 0\n");  		return -EIO;  	} @@ -482,7 +482,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)  		current_blocks = 0;  	} else {  		if (!(ji->ea.flag & DXD_EXTENT)) { -			jfs_error(sb, "ea_get: invalid ea.flag)"); +			jfs_error(sb, "invalid ea.flag\n");  			return -EIO;  		}  		current_blocks = (ea_size + sb->s_blocksize - 1) >> @@ -666,83 +666,12 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,  }  /* - * can_set_system_xattr - * - * This code is specific to the system.* namespace.  It contains policy - * which doesn't belong in the main xattr codepath. - */ -static int can_set_system_xattr(struct inode *inode, const char *name, -				const void *value, size_t value_len) -{ -#ifdef CONFIG_JFS_POSIX_ACL -	struct posix_acl *acl; -	int rc; - -	if (!is_owner_or_cap(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(value, value_len); -		if (IS_ERR(acl)) { -			rc = PTR_ERR(acl); -			printk(KERN_ERR "posix_acl_from_xattr returned %d\n", -			       rc); -			return rc; -		} -		if (acl) { -			mode_t mode = inode->i_mode; -			rc = posix_acl_equiv_mode(acl, &mode); -			posix_acl_release(acl); -			if (rc < 0) { -				printk(KERN_ERR -				       "posix_acl_equiv_mode returned %d\n", -				       rc); -				return rc; -			} -			inode->i_mode = mode; -			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(value, value_len); -		if (IS_ERR(acl)) { -			rc = PTR_ERR(acl); -			printk(KERN_ERR "posix_acl_from_xattr returned %d\n", -			       rc); -			return rc; -		} -		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_JFS_POSIX_ACL */ -	return -EOPNOTSUPP; -} - -/*   * Most of the permission checking is done by xattr_permission in the vfs. - * The local file system is responsible for handling the system.* namespace.   * We also need to verify that this is a namespace that we recognize.   */  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_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {  		/*  		 * This makes sure that we aren't trying to set an @@ -750,7 +679,7 @@ static int can_set_xattr(struct inode *inode, const char *name,  		 * with "os2."  		 */  		if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN)) -				return -EOPNOTSUPP; +			return -EOPNOTSUPP;  		return 0;  	} @@ -862,6 +791,19 @@ int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,  			/* Completely new ea list */  			xattr_size = sizeof (struct jfs_ea_list); +		/* +		 * The size of EA value is limitted by on-disk format up to +		 *  __le16, there would be an overflow if the size is equal +		 * to XATTR_SIZE_MAX (65536).  In order to avoid this issue, +		 * we can pre-checkup the value size against USHRT_MAX, and +		 * return -E2BIG in this case, which is consistent with the +		 * VFS setxattr interface. +		 */ +		if (value_len >= USHRT_MAX) { +			rc = -E2BIG; +			goto release; +		} +  		ea = (struct jfs_ea *) ((char *) ealist + xattr_size);  		ea->flag = 0;  		ea->namelen = namelen; @@ -876,7 +818,7 @@ int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,  	/* DEBUG - If we did this right, these number match */  	if (xattr_size != new_size) {  		printk(KERN_ERR -		       "jfs_xsetattr: xattr_size = %d, new_size = %d\n", +		       "__jfs_setxattr: xattr_size = %d, new_size = %d\n",  		       xattr_size, new_size);  		rc = -EINVAL; @@ -912,6 +854,14 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,  	int rc;  	tid_t tid; +	/* +	 * If this is a request for a synthetic attribute in the system.* +	 * namespace use the generic infrastructure to resolve a handler +	 * for it via sb->s_xattr. +	 */ +	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) +		return generic_setxattr(dentry, name, value, value_len, flags); +  	if ((rc = can_set_xattr(inode, name, value, value_len)))  		return rc; @@ -988,6 +938,14 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,  {  	int err; +	/* +	 * If this is a request for a synthetic attribute in the system.* +	 * namespace use the generic infrastructure to resolve a handler +	 * for it via sb->s_xattr. +	 */ +	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) +		return generic_getxattr(dentry, name, data, buf_size); +  	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {  		/*  		 * skip past "os2." prefix @@ -1076,6 +1034,14 @@ int jfs_removexattr(struct dentry *dentry, const char *name)  	int rc;  	tid_t tid; +	/* +	 * If this is a request for a synthetic attribute in the system.* +	 * namespace use the generic infrastructure to resolve a handler +	 * for it via sb->s_xattr. +	 */ +	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) +		return generic_removexattr(dentry, name); +  	if ((rc = can_set_xattr(inode, name, NULL, 0)))  		return rc; @@ -1090,37 +1056,51 @@ int jfs_removexattr(struct dentry *dentry, const char *name)  	return rc;  } +/* + * List of handlers for synthetic system.* attributes.  All real ondisk + * attributes are handled directly. + */ +const struct xattr_handler *jfs_xattr_handlers[] = { +#ifdef CONFIG_JFS_POSIX_ACL +	&posix_acl_access_xattr_handler, +	&posix_acl_default_xattr_handler, +#endif +	NULL, +}; + +  #ifdef CONFIG_JFS_SECURITY -int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) +static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, +			  void *fs_info)  { -	int rc; -	size_t len; -	void *value; -	char *suffix; +	const struct xattr *xattr; +	tid_t *tid = fs_info;  	char *name; - -	rc = security_inode_init_security(inode, dir, &suffix, &value, &len); -	if (rc) { -		if (rc == -EOPNOTSUPP) -			return 0; -		return rc; -	} -	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix), -		       GFP_NOFS); -	if (!name) { -		rc = -ENOMEM; -		goto kmalloc_failed; +	int err = 0; + +	for (xattr = xattr_array; xattr->name != NULL; xattr++) { +		name = kmalloc(XATTR_SECURITY_PREFIX_LEN + +			       strlen(xattr->name) + 1, GFP_NOFS); +		if (!name) { +			err = -ENOMEM; +			break; +		} +		strcpy(name, XATTR_SECURITY_PREFIX); +		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); + +		err = __jfs_setxattr(*tid, inode, name, +				     xattr->value, xattr->value_len, 0); +		kfree(name); +		if (err < 0) +			break;  	} -	strcpy(name, XATTR_SECURITY_PREFIX); -	strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); - -	rc = __jfs_setxattr(tid, inode, name, value, len, 0); - -	kfree(name); -kmalloc_failed: -	kfree(suffix); -	kfree(value); +	return err; +} -	return rc; +int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, +		      const struct qstr *qstr) +{ +	return security_inode_init_security(inode, dir, qstr, +					    &jfs_initxattrs, &tid);  }  #endif  | 
