| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-only  | 
|---|
| 1 | 2 |  /* | 
|---|
| 2 | 3 |   * fs/kernfs/inode.c - kernfs inode implementation | 
|---|
| 3 | 4 |   * | 
|---|
| 4 | 5 |   * Copyright (c) 2001-3 Patrick Mochel | 
|---|
| 5 | 6 |   * Copyright (c) 2007 SUSE Linux Products GmbH | 
|---|
| 6 | 7 |   * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org> | 
|---|
| 7 |  | - *  | 
|---|
| 8 |  | - * This file is released under the GPLv2.  | 
|---|
| 9 | 8 |   */ | 
|---|
| 10 | 9 |   | 
|---|
| 11 | 10 |  #include <linux/pagemap.h> | 
|---|
| .. | .. | 
|---|
| 31 | 30 |  	.listxattr	= kernfs_iop_listxattr, | 
|---|
| 32 | 31 |  }; | 
|---|
| 33 | 32 |   | 
|---|
| 34 |  | -static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)  | 
|---|
 | 33 | +static struct kernfs_iattrs *__kernfs_iattrs(struct kernfs_node *kn, int alloc)  | 
|---|
| 35 | 34 |  { | 
|---|
| 36 | 35 |  	static DEFINE_MUTEX(iattr_mutex); | 
|---|
| 37 | 36 |  	struct kernfs_iattrs *ret; | 
|---|
| 38 |  | -	struct iattr *iattrs;  | 
|---|
| 39 | 37 |   | 
|---|
| 40 | 38 |  	mutex_lock(&iattr_mutex); | 
|---|
| 41 | 39 |   | 
|---|
| 42 |  | -	if (kn->iattr)  | 
|---|
 | 40 | +	if (kn->iattr || !alloc)  | 
|---|
| 43 | 41 |  		goto out_unlock; | 
|---|
| 44 | 42 |   | 
|---|
| 45 |  | -	kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);  | 
|---|
 | 43 | +	kn->iattr = kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL);  | 
|---|
| 46 | 44 |  	if (!kn->iattr) | 
|---|
| 47 | 45 |  		goto out_unlock; | 
|---|
| 48 |  | -	iattrs = &kn->iattr->ia_iattr;  | 
|---|
| 49 | 46 |   | 
|---|
| 50 | 47 |  	/* assign default attributes */ | 
|---|
| 51 |  | -	iattrs->ia_mode = kn->mode;  | 
|---|
| 52 |  | -	iattrs->ia_uid = GLOBAL_ROOT_UID;  | 
|---|
| 53 |  | -	iattrs->ia_gid = GLOBAL_ROOT_GID;  | 
|---|
 | 48 | +	kn->iattr->ia_uid = GLOBAL_ROOT_UID;  | 
|---|
 | 49 | +	kn->iattr->ia_gid = GLOBAL_ROOT_GID;  | 
|---|
| 54 | 50 |   | 
|---|
| 55 |  | -	ktime_get_real_ts64(&iattrs->ia_atime);  | 
|---|
| 56 |  | -	iattrs->ia_mtime = iattrs->ia_atime;  | 
|---|
| 57 |  | -	iattrs->ia_ctime = iattrs->ia_atime;  | 
|---|
 | 51 | +	ktime_get_real_ts64(&kn->iattr->ia_atime);  | 
|---|
 | 52 | +	kn->iattr->ia_mtime = kn->iattr->ia_atime;  | 
|---|
 | 53 | +	kn->iattr->ia_ctime = kn->iattr->ia_atime;  | 
|---|
| 58 | 54 |   | 
|---|
| 59 | 55 |  	simple_xattrs_init(&kn->iattr->xattrs); | 
|---|
 | 56 | +	atomic_set(&kn->iattr->nr_user_xattrs, 0);  | 
|---|
 | 57 | +	atomic_set(&kn->iattr->user_xattr_size, 0);  | 
|---|
| 60 | 58 |  out_unlock: | 
|---|
| 61 | 59 |  	ret = kn->iattr; | 
|---|
| 62 | 60 |  	mutex_unlock(&iattr_mutex); | 
|---|
| 63 | 61 |  	return ret; | 
|---|
| 64 | 62 |  } | 
|---|
| 65 | 63 |   | 
|---|
 | 64 | +static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)  | 
|---|
 | 65 | +{  | 
|---|
 | 66 | +	return __kernfs_iattrs(kn, 1);  | 
|---|
 | 67 | +}  | 
|---|
 | 68 | +  | 
|---|
 | 69 | +static struct kernfs_iattrs *kernfs_iattrs_noalloc(struct kernfs_node *kn)  | 
|---|
 | 70 | +{  | 
|---|
 | 71 | +	return __kernfs_iattrs(kn, 0);  | 
|---|
 | 72 | +}  | 
|---|
 | 73 | +  | 
|---|
| 66 | 74 |  int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) | 
|---|
| 67 | 75 |  { | 
|---|
| 68 | 76 |  	struct kernfs_iattrs *attrs; | 
|---|
| 69 |  | -	struct iattr *iattrs;  | 
|---|
| 70 | 77 |  	unsigned int ia_valid = iattr->ia_valid; | 
|---|
| 71 | 78 |   | 
|---|
| 72 | 79 |  	attrs = kernfs_iattrs(kn); | 
|---|
| 73 | 80 |  	if (!attrs) | 
|---|
| 74 | 81 |  		return -ENOMEM; | 
|---|
| 75 | 82 |   | 
|---|
| 76 |  | -	iattrs = &attrs->ia_iattr;  | 
|---|
| 77 |  | -  | 
|---|
| 78 | 83 |  	if (ia_valid & ATTR_UID) | 
|---|
| 79 |  | -		iattrs->ia_uid = iattr->ia_uid;  | 
|---|
 | 84 | +		attrs->ia_uid = iattr->ia_uid;  | 
|---|
| 80 | 85 |  	if (ia_valid & ATTR_GID) | 
|---|
| 81 |  | -		iattrs->ia_gid = iattr->ia_gid;  | 
|---|
 | 86 | +		attrs->ia_gid = iattr->ia_gid;  | 
|---|
| 82 | 87 |  	if (ia_valid & ATTR_ATIME) | 
|---|
| 83 |  | -		iattrs->ia_atime = iattr->ia_atime;  | 
|---|
 | 88 | +		attrs->ia_atime = iattr->ia_atime;  | 
|---|
| 84 | 89 |  	if (ia_valid & ATTR_MTIME) | 
|---|
| 85 |  | -		iattrs->ia_mtime = iattr->ia_mtime;  | 
|---|
 | 90 | +		attrs->ia_mtime = iattr->ia_mtime;  | 
|---|
| 86 | 91 |  	if (ia_valid & ATTR_CTIME) | 
|---|
| 87 |  | -		iattrs->ia_ctime = iattr->ia_ctime;  | 
|---|
| 88 |  | -	if (ia_valid & ATTR_MODE) {  | 
|---|
| 89 |  | -		umode_t mode = iattr->ia_mode;  | 
|---|
| 90 |  | -		iattrs->ia_mode = kn->mode = mode;  | 
|---|
| 91 |  | -	}  | 
|---|
 | 92 | +		attrs->ia_ctime = iattr->ia_ctime;  | 
|---|
 | 93 | +	if (ia_valid & ATTR_MODE)  | 
|---|
 | 94 | +		kn->mode = iattr->ia_mode;  | 
|---|
| 92 | 95 |  	return 0; | 
|---|
| 93 | 96 |  } | 
|---|
| 94 | 97 |   | 
|---|
| .. | .. | 
|---|
| 135 | 138 |  	return error; | 
|---|
| 136 | 139 |  } | 
|---|
| 137 | 140 |   | 
|---|
| 138 |  | -static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,  | 
|---|
| 139 |  | -				  u32 *secdata_len)  | 
|---|
| 140 |  | -{  | 
|---|
| 141 |  | -	void *old_secdata;  | 
|---|
| 142 |  | -	size_t old_secdata_len;  | 
|---|
| 143 |  | -  | 
|---|
| 144 |  | -	old_secdata = attrs->ia_secdata;  | 
|---|
| 145 |  | -	old_secdata_len = attrs->ia_secdata_len;  | 
|---|
| 146 |  | -  | 
|---|
| 147 |  | -	attrs->ia_secdata = *secdata;  | 
|---|
| 148 |  | -	attrs->ia_secdata_len = *secdata_len;  | 
|---|
| 149 |  | -  | 
|---|
| 150 |  | -	*secdata = old_secdata;  | 
|---|
| 151 |  | -	*secdata_len = old_secdata_len;  | 
|---|
| 152 |  | -	return 0;  | 
|---|
| 153 |  | -}  | 
|---|
| 154 |  | -  | 
|---|
| 155 | 141 |  ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) | 
|---|
| 156 | 142 |  { | 
|---|
| 157 | 143 |  	struct kernfs_node *kn = kernfs_dentry_node(dentry); | 
|---|
| .. | .. | 
|---|
| 171 | 157 |  		inode->i_ctime = current_time(inode); | 
|---|
| 172 | 158 |  } | 
|---|
| 173 | 159 |   | 
|---|
| 174 |  | -static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)  | 
|---|
 | 160 | +static inline void set_inode_attr(struct inode *inode,  | 
|---|
 | 161 | +				  struct kernfs_iattrs *attrs)  | 
|---|
| 175 | 162 |  { | 
|---|
| 176 |  | -	struct super_block *sb = inode->i_sb;  | 
|---|
| 177 |  | -	inode->i_uid = iattr->ia_uid;  | 
|---|
| 178 |  | -	inode->i_gid = iattr->ia_gid;  | 
|---|
| 179 |  | -	inode->i_atime = timespec64_trunc(iattr->ia_atime, sb->s_time_gran);  | 
|---|
| 180 |  | -	inode->i_mtime = timespec64_trunc(iattr->ia_mtime, sb->s_time_gran);  | 
|---|
| 181 |  | -	inode->i_ctime = timespec64_trunc(iattr->ia_ctime, sb->s_time_gran);  | 
|---|
 | 163 | +	inode->i_uid = attrs->ia_uid;  | 
|---|
 | 164 | +	inode->i_gid = attrs->ia_gid;  | 
|---|
 | 165 | +	inode->i_atime = attrs->ia_atime;  | 
|---|
 | 166 | +	inode->i_mtime = attrs->ia_mtime;  | 
|---|
 | 167 | +	inode->i_ctime = attrs->ia_ctime;  | 
|---|
| 182 | 168 |  } | 
|---|
| 183 | 169 |   | 
|---|
| 184 | 170 |  static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | 
|---|
| .. | .. | 
|---|
| 186 | 172 |  	struct kernfs_iattrs *attrs = kn->iattr; | 
|---|
| 187 | 173 |   | 
|---|
| 188 | 174 |  	inode->i_mode = kn->mode; | 
|---|
| 189 |  | -	if (attrs) {  | 
|---|
 | 175 | +	if (attrs)  | 
|---|
| 190 | 176 |  		/* | 
|---|
| 191 | 177 |  		 * kernfs_node has non-default attributes get them from | 
|---|
| 192 | 178 |  		 * persistent copy in kernfs_node. | 
|---|
| 193 | 179 |  		 */ | 
|---|
| 194 |  | -		set_inode_attr(inode, &attrs->ia_iattr);  | 
|---|
| 195 |  | -		security_inode_notifysecctx(inode, attrs->ia_secdata,  | 
|---|
| 196 |  | -					    attrs->ia_secdata_len);  | 
|---|
| 197 |  | -	}  | 
|---|
 | 180 | +		set_inode_attr(inode, attrs);  | 
|---|
| 198 | 181 |   | 
|---|
| 199 | 182 |  	if (kernfs_type(kn) == KERNFS_DIR) | 
|---|
| 200 | 183 |  		set_nlink(inode, kn->dir.subdirs + 2); | 
|---|
| .. | .. | 
|---|
| 220 | 203 |  	inode->i_private = kn; | 
|---|
| 221 | 204 |  	inode->i_mapping->a_ops = &kernfs_aops; | 
|---|
| 222 | 205 |  	inode->i_op = &kernfs_iops; | 
|---|
| 223 |  | -	inode->i_generation = kn->id.generation;  | 
|---|
 | 206 | +	inode->i_generation = kernfs_gen(kn);  | 
|---|
| 224 | 207 |   | 
|---|
| 225 | 208 |  	set_default_inode_attr(inode, kn->mode); | 
|---|
| 226 | 209 |  	kernfs_refresh_inode(kn, inode); | 
|---|
| .. | .. | 
|---|
| 266 | 249 |  { | 
|---|
| 267 | 250 |  	struct inode *inode; | 
|---|
| 268 | 251 |   | 
|---|
| 269 |  | -	inode = iget_locked(sb, kn->id.ino);  | 
|---|
 | 252 | +	inode = iget_locked(sb, kernfs_ino(kn));  | 
|---|
| 270 | 253 |  	if (inode && (inode->i_state & I_NEW)) | 
|---|
| 271 | 254 |  		kernfs_init_inode(kn, inode); | 
|---|
| 272 | 255 |   | 
|---|
| .. | .. | 
|---|
| 305 | 288 |  	return generic_permission(inode, mask); | 
|---|
| 306 | 289 |  } | 
|---|
| 307 | 290 |   | 
|---|
| 308 |  | -static int kernfs_xattr_get(const struct xattr_handler *handler,  | 
|---|
| 309 |  | -			    struct dentry *unused, struct inode *inode,  | 
|---|
| 310 |  | -			    const char *suffix, void *value, size_t size)  | 
|---|
 | 291 | +int kernfs_xattr_get(struct kernfs_node *kn, const char *name,  | 
|---|
 | 292 | +		     void *value, size_t size)  | 
|---|
| 311 | 293 |  { | 
|---|
| 312 |  | -	const char *name = xattr_full_name(handler, suffix);  | 
|---|
| 313 |  | -	struct kernfs_node *kn = inode->i_private;  | 
|---|
| 314 |  | -	struct kernfs_iattrs *attrs;  | 
|---|
| 315 |  | -  | 
|---|
| 316 |  | -	attrs = kernfs_iattrs(kn);  | 
|---|
 | 294 | +	struct kernfs_iattrs *attrs = kernfs_iattrs_noalloc(kn);  | 
|---|
| 317 | 295 |  	if (!attrs) | 
|---|
| 318 |  | -		return -ENOMEM;  | 
|---|
 | 296 | +		return -ENODATA;  | 
|---|
| 319 | 297 |   | 
|---|
| 320 | 298 |  	return simple_xattr_get(&attrs->xattrs, name, value, size); | 
|---|
| 321 | 299 |  } | 
|---|
| 322 | 300 |   | 
|---|
| 323 |  | -static int kernfs_xattr_set(const struct xattr_handler *handler,  | 
|---|
| 324 |  | -			    struct dentry *unused, struct inode *inode,  | 
|---|
| 325 |  | -			    const char *suffix, const void *value,  | 
|---|
| 326 |  | -			    size_t size, int flags)  | 
|---|
 | 301 | +int kernfs_xattr_set(struct kernfs_node *kn, const char *name,  | 
|---|
 | 302 | +		     const void *value, size_t size, int flags)  | 
|---|
| 327 | 303 |  { | 
|---|
| 328 |  | -	const char *name = xattr_full_name(handler, suffix);  | 
|---|
| 329 |  | -	struct kernfs_node *kn = inode->i_private;  | 
|---|
| 330 |  | -	struct kernfs_iattrs *attrs;  | 
|---|
| 331 |  | -  | 
|---|
| 332 |  | -	attrs = kernfs_iattrs(kn);  | 
|---|
 | 304 | +	struct kernfs_iattrs *attrs = kernfs_iattrs(kn);  | 
|---|
| 333 | 305 |  	if (!attrs) | 
|---|
| 334 | 306 |  		return -ENOMEM; | 
|---|
| 335 | 307 |   | 
|---|
| 336 |  | -	return simple_xattr_set(&attrs->xattrs, name, value, size, flags);  | 
|---|
 | 308 | +	return simple_xattr_set(&attrs->xattrs, name, value, size, flags, NULL);  | 
|---|
| 337 | 309 |  } | 
|---|
| 338 | 310 |   | 
|---|
| 339 |  | -static const struct xattr_handler kernfs_trusted_xattr_handler = {  | 
|---|
| 340 |  | -	.prefix = XATTR_TRUSTED_PREFIX,  | 
|---|
| 341 |  | -	.get = kernfs_xattr_get,  | 
|---|
| 342 |  | -	.set = kernfs_xattr_set,  | 
|---|
| 343 |  | -};  | 
|---|
 | 311 | +static int kernfs_vfs_xattr_get(const struct xattr_handler *handler,  | 
|---|
 | 312 | +				struct dentry *unused, struct inode *inode,  | 
|---|
 | 313 | +				const char *suffix, void *value, size_t size,  | 
|---|
 | 314 | +				int flags)  | 
|---|
 | 315 | +{  | 
|---|
 | 316 | +	const char *name = xattr_full_name(handler, suffix);  | 
|---|
 | 317 | +	struct kernfs_node *kn = inode->i_private;  | 
|---|
| 344 | 318 |   | 
|---|
| 345 |  | -static int kernfs_security_xattr_set(const struct xattr_handler *handler,  | 
|---|
 | 319 | +	return kernfs_xattr_get(kn, name, value, size);  | 
|---|
 | 320 | +}  | 
|---|
 | 321 | +  | 
|---|
 | 322 | +static int kernfs_vfs_xattr_set(const struct xattr_handler *handler,  | 
|---|
 | 323 | +				struct dentry *unused, struct inode *inode,  | 
|---|
 | 324 | +				const char *suffix, const void *value,  | 
|---|
 | 325 | +				size_t size, int flags)  | 
|---|
 | 326 | +{  | 
|---|
 | 327 | +	const char *name = xattr_full_name(handler, suffix);  | 
|---|
 | 328 | +	struct kernfs_node *kn = inode->i_private;  | 
|---|
 | 329 | +  | 
|---|
 | 330 | +	return kernfs_xattr_set(kn, name, value, size, flags);  | 
|---|
 | 331 | +}  | 
|---|
 | 332 | +  | 
|---|
 | 333 | +static int kernfs_vfs_user_xattr_add(struct kernfs_node *kn,  | 
|---|
 | 334 | +				     const char *full_name,  | 
|---|
 | 335 | +				     struct simple_xattrs *xattrs,  | 
|---|
 | 336 | +				     const void *value, size_t size, int flags)  | 
|---|
 | 337 | +{  | 
|---|
 | 338 | +	atomic_t *sz = &kn->iattr->user_xattr_size;  | 
|---|
 | 339 | +	atomic_t *nr = &kn->iattr->nr_user_xattrs;  | 
|---|
 | 340 | +	ssize_t removed_size;  | 
|---|
 | 341 | +	int ret;  | 
|---|
 | 342 | +  | 
|---|
 | 343 | +	if (atomic_inc_return(nr) > KERNFS_MAX_USER_XATTRS) {  | 
|---|
 | 344 | +		ret = -ENOSPC;  | 
|---|
 | 345 | +		goto dec_count_out;  | 
|---|
 | 346 | +	}  | 
|---|
 | 347 | +  | 
|---|
 | 348 | +	if (atomic_add_return(size, sz) > KERNFS_USER_XATTR_SIZE_LIMIT) {  | 
|---|
 | 349 | +		ret = -ENOSPC;  | 
|---|
 | 350 | +		goto dec_size_out;  | 
|---|
 | 351 | +	}  | 
|---|
 | 352 | +  | 
|---|
 | 353 | +	ret = simple_xattr_set(xattrs, full_name, value, size, flags,  | 
|---|
 | 354 | +			       &removed_size);  | 
|---|
 | 355 | +  | 
|---|
 | 356 | +	if (!ret && removed_size >= 0)  | 
|---|
 | 357 | +		size = removed_size;  | 
|---|
 | 358 | +	else if (!ret)  | 
|---|
 | 359 | +		return 0;  | 
|---|
 | 360 | +dec_size_out:  | 
|---|
 | 361 | +	atomic_sub(size, sz);  | 
|---|
 | 362 | +dec_count_out:  | 
|---|
 | 363 | +	atomic_dec(nr);  | 
|---|
 | 364 | +	return ret;  | 
|---|
 | 365 | +}  | 
|---|
 | 366 | +  | 
|---|
 | 367 | +static int kernfs_vfs_user_xattr_rm(struct kernfs_node *kn,  | 
|---|
 | 368 | +				    const char *full_name,  | 
|---|
 | 369 | +				    struct simple_xattrs *xattrs,  | 
|---|
 | 370 | +				    const void *value, size_t size, int flags)  | 
|---|
 | 371 | +{  | 
|---|
 | 372 | +	atomic_t *sz = &kn->iattr->user_xattr_size;  | 
|---|
 | 373 | +	atomic_t *nr = &kn->iattr->nr_user_xattrs;  | 
|---|
 | 374 | +	ssize_t removed_size;  | 
|---|
 | 375 | +	int ret;  | 
|---|
 | 376 | +  | 
|---|
 | 377 | +	ret = simple_xattr_set(xattrs, full_name, value, size, flags,  | 
|---|
 | 378 | +			       &removed_size);  | 
|---|
 | 379 | +  | 
|---|
 | 380 | +	if (removed_size >= 0) {  | 
|---|
 | 381 | +		atomic_sub(removed_size, sz);  | 
|---|
 | 382 | +		atomic_dec(nr);  | 
|---|
 | 383 | +	}  | 
|---|
 | 384 | +  | 
|---|
 | 385 | +	return ret;  | 
|---|
 | 386 | +}  | 
|---|
 | 387 | +  | 
|---|
 | 388 | +static int kernfs_vfs_user_xattr_set(const struct xattr_handler *handler,  | 
|---|
| 346 | 389 |  				     struct dentry *unused, struct inode *inode, | 
|---|
| 347 | 390 |  				     const char *suffix, const void *value, | 
|---|
| 348 | 391 |  				     size_t size, int flags) | 
|---|
| 349 | 392 |  { | 
|---|
 | 393 | +	const char *full_name = xattr_full_name(handler, suffix);  | 
|---|
| 350 | 394 |  	struct kernfs_node *kn = inode->i_private; | 
|---|
| 351 | 395 |  	struct kernfs_iattrs *attrs; | 
|---|
| 352 |  | -	void *secdata;  | 
|---|
| 353 |  | -	u32 secdata_len = 0;  | 
|---|
| 354 |  | -	int error;  | 
|---|
 | 396 | +  | 
|---|
 | 397 | +	if (!(kernfs_root(kn)->flags & KERNFS_ROOT_SUPPORT_USER_XATTR))  | 
|---|
 | 398 | +		return -EOPNOTSUPP;  | 
|---|
| 355 | 399 |   | 
|---|
| 356 | 400 |  	attrs = kernfs_iattrs(kn); | 
|---|
| 357 | 401 |  	if (!attrs) | 
|---|
| 358 | 402 |  		return -ENOMEM; | 
|---|
| 359 | 403 |   | 
|---|
| 360 |  | -	error = security_inode_setsecurity(inode, suffix, value, size, flags);  | 
|---|
| 361 |  | -	if (error)  | 
|---|
| 362 |  | -		return error;  | 
|---|
| 363 |  | -	error = security_inode_getsecctx(inode, &secdata, &secdata_len);  | 
|---|
| 364 |  | -	if (error)  | 
|---|
| 365 |  | -		return error;  | 
|---|
 | 404 | +	if (value)  | 
|---|
 | 405 | +		return kernfs_vfs_user_xattr_add(kn, full_name, &attrs->xattrs,  | 
|---|
 | 406 | +						 value, size, flags);  | 
|---|
 | 407 | +	else  | 
|---|
 | 408 | +		return kernfs_vfs_user_xattr_rm(kn, full_name, &attrs->xattrs,  | 
|---|
 | 409 | +						value, size, flags);  | 
|---|
| 366 | 410 |   | 
|---|
| 367 |  | -	mutex_lock(&kernfs_mutex);  | 
|---|
| 368 |  | -	error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);  | 
|---|
| 369 |  | -	mutex_unlock(&kernfs_mutex);  | 
|---|
| 370 |  | -  | 
|---|
| 371 |  | -	if (secdata)  | 
|---|
| 372 |  | -		security_release_secctx(secdata, secdata_len);  | 
|---|
| 373 |  | -	return error;  | 
|---|
| 374 | 411 |  } | 
|---|
 | 412 | +  | 
|---|
 | 413 | +static const struct xattr_handler kernfs_trusted_xattr_handler = {  | 
|---|
 | 414 | +	.prefix = XATTR_TRUSTED_PREFIX,  | 
|---|
 | 415 | +	.get = kernfs_vfs_xattr_get,  | 
|---|
 | 416 | +	.set = kernfs_vfs_xattr_set,  | 
|---|
 | 417 | +};  | 
|---|
| 375 | 418 |   | 
|---|
| 376 | 419 |  static const struct xattr_handler kernfs_security_xattr_handler = { | 
|---|
| 377 | 420 |  	.prefix = XATTR_SECURITY_PREFIX, | 
|---|
| 378 |  | -	.get = kernfs_xattr_get,  | 
|---|
| 379 |  | -	.set = kernfs_security_xattr_set,  | 
|---|
 | 421 | +	.get = kernfs_vfs_xattr_get,  | 
|---|
 | 422 | +	.set = kernfs_vfs_xattr_set,  | 
|---|
 | 423 | +};  | 
|---|
 | 424 | +  | 
|---|
 | 425 | +static const struct xattr_handler kernfs_user_xattr_handler = {  | 
|---|
 | 426 | +	.prefix = XATTR_USER_PREFIX,  | 
|---|
 | 427 | +	.get = kernfs_vfs_xattr_get,  | 
|---|
 | 428 | +	.set = kernfs_vfs_user_xattr_set,  | 
|---|
| 380 | 429 |  }; | 
|---|
| 381 | 430 |   | 
|---|
| 382 | 431 |  const struct xattr_handler *kernfs_xattr_handlers[] = { | 
|---|
| 383 | 432 |  	&kernfs_trusted_xattr_handler, | 
|---|
| 384 | 433 |  	&kernfs_security_xattr_handler, | 
|---|
 | 434 | +	&kernfs_user_xattr_handler,  | 
|---|
| 385 | 435 |  	NULL | 
|---|
| 386 | 436 |  }; | 
|---|