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