|
24 | 24 | #include <linux/key.h>
|
25 | 25 | #include <linux/verification.h>
|
26 | 26 | #include <linux/namei.h>
|
| 27 | +#include <linux/fileattr.h> |
27 | 28 |
|
28 | 29 | #include <net/bpf_sk_storage.h>
|
29 | 30 |
|
@@ -1431,6 +1432,72 @@ static int __init bpf_key_sig_kfuncs_init(void)
|
1431 | 1432 | late_initcall(bpf_key_sig_kfuncs_init);
|
1432 | 1433 | #endif /* CONFIG_KEYS */
|
1433 | 1434 |
|
| 1435 | +/* filesystem kfuncs */ |
| 1436 | +__bpf_kfunc_start_defs(); |
| 1437 | + |
| 1438 | +/** |
| 1439 | + * bpf_get_file_xattr - get xattr of a file |
| 1440 | + * @file: file to get xattr from |
| 1441 | + * @name__str: name of the xattr |
| 1442 | + * @value_ptr: output buffer of the xattr value |
| 1443 | + * |
| 1444 | + * Get xattr *name__str* of *file* and store the output in *value_ptr*. |
| 1445 | + * |
| 1446 | + * For security reasons, only *name__str* with prefix "user." is allowed. |
| 1447 | + * |
| 1448 | + * Return: 0 on success, a negative value on error. |
| 1449 | + */ |
| 1450 | +__bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str, |
| 1451 | + struct bpf_dynptr_kern *value_ptr) |
| 1452 | +{ |
| 1453 | + struct dentry *dentry; |
| 1454 | + u32 value_len; |
| 1455 | + void *value; |
| 1456 | + int ret; |
| 1457 | + |
| 1458 | + if (strncmp(name__str, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) |
| 1459 | + return -EPERM; |
| 1460 | + |
| 1461 | + value_len = __bpf_dynptr_size(value_ptr); |
| 1462 | + value = __bpf_dynptr_data_rw(value_ptr, value_len); |
| 1463 | + if (!value) |
| 1464 | + return -EINVAL; |
| 1465 | + |
| 1466 | + dentry = file_dentry(file); |
| 1467 | + ret = inode_permission(&nop_mnt_idmap, dentry->d_inode, MAY_READ); |
| 1468 | + if (ret) |
| 1469 | + return ret; |
| 1470 | + return __vfs_getxattr(dentry, dentry->d_inode, name__str, value, value_len); |
| 1471 | +} |
| 1472 | + |
| 1473 | +__bpf_kfunc_end_defs(); |
| 1474 | + |
| 1475 | +BTF_SET8_START(fs_kfunc_set_ids) |
| 1476 | +BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) |
| 1477 | +BTF_SET8_END(fs_kfunc_set_ids) |
| 1478 | + |
| 1479 | +static int bpf_get_file_xattr_filter(const struct bpf_prog *prog, u32 kfunc_id) |
| 1480 | +{ |
| 1481 | + if (!btf_id_set8_contains(&fs_kfunc_set_ids, kfunc_id)) |
| 1482 | + return 0; |
| 1483 | + |
| 1484 | + /* Only allow to attach from LSM hooks, to avoid recursion */ |
| 1485 | + return prog->type != BPF_PROG_TYPE_LSM ? -EACCES : 0; |
| 1486 | +} |
| 1487 | + |
| 1488 | +static const struct btf_kfunc_id_set bpf_fs_kfunc_set = { |
| 1489 | + .owner = THIS_MODULE, |
| 1490 | + .set = &fs_kfunc_set_ids, |
| 1491 | + .filter = bpf_get_file_xattr_filter, |
| 1492 | +}; |
| 1493 | + |
| 1494 | +static int __init bpf_fs_kfuncs_init(void) |
| 1495 | +{ |
| 1496 | + return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set); |
| 1497 | +} |
| 1498 | + |
| 1499 | +late_initcall(bpf_fs_kfuncs_init); |
| 1500 | + |
1434 | 1501 | static const struct bpf_func_proto *
|
1435 | 1502 | bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
1436 | 1503 | {
|
|
0 commit comments