| .. | .. |
|---|
| 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 | }; |
|---|