|
8 | 8 | #include <linux/fs.h> |
9 | 9 | #include <linux/file.h> |
10 | 10 | #include <linux/mm.h> |
| 11 | +#include <linux/xattr.h> |
11 | 12 |
|
12 | 13 | __bpf_kfunc_start_defs(); |
13 | 14 |
|
@@ -92,13 +93,74 @@ __bpf_kfunc int bpf_path_d_path(struct path *path, char *buf, size_t buf__sz) |
92 | 93 | return len; |
93 | 94 | } |
94 | 95 |
|
| 96 | +/** |
| 97 | + * bpf_get_dentry_xattr - get xattr of a dentry |
| 98 | + * @dentry: dentry to get xattr from |
| 99 | + * @name__str: name of the xattr |
| 100 | + * @value_p: output buffer of the xattr value |
| 101 | + * |
| 102 | + * Get xattr *name__str* of *dentry* and store the output in *value_ptr*. |
| 103 | + * |
| 104 | + * For security reasons, only *name__str* with prefix "user." is allowed. |
| 105 | + * |
| 106 | + * Return: 0 on success, a negative value on error. |
| 107 | + */ |
| 108 | +__bpf_kfunc int bpf_get_dentry_xattr(struct dentry *dentry, const char *name__str, |
| 109 | + struct bpf_dynptr *value_p) |
| 110 | +{ |
| 111 | + struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p; |
| 112 | + struct inode *inode = d_inode(dentry); |
| 113 | + u32 value_len; |
| 114 | + void *value; |
| 115 | + int ret; |
| 116 | + |
| 117 | + if (WARN_ON(!inode)) |
| 118 | + return -EINVAL; |
| 119 | + |
| 120 | + if (strncmp(name__str, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) |
| 121 | + return -EPERM; |
| 122 | + |
| 123 | + value_len = __bpf_dynptr_size(value_ptr); |
| 124 | + value = __bpf_dynptr_data_rw(value_ptr, value_len); |
| 125 | + if (!value) |
| 126 | + return -EINVAL; |
| 127 | + |
| 128 | + ret = inode_permission(&nop_mnt_idmap, inode, MAY_READ); |
| 129 | + if (ret) |
| 130 | + return ret; |
| 131 | + return __vfs_getxattr(dentry, inode, name__str, value, value_len); |
| 132 | +} |
| 133 | + |
| 134 | +/** |
| 135 | + * bpf_get_file_xattr - get xattr of a file |
| 136 | + * @file: file to get xattr from |
| 137 | + * @name__str: name of the xattr |
| 138 | + * @value_p: output buffer of the xattr value |
| 139 | + * |
| 140 | + * Get xattr *name__str* of *file* and store the output in *value_ptr*. |
| 141 | + * |
| 142 | + * For security reasons, only *name__str* with prefix "user." is allowed. |
| 143 | + * |
| 144 | + * Return: 0 on success, a negative value on error. |
| 145 | + */ |
| 146 | +__bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str, |
| 147 | + struct bpf_dynptr *value_p) |
| 148 | +{ |
| 149 | + struct dentry *dentry; |
| 150 | + |
| 151 | + dentry = file_dentry(file); |
| 152 | + return bpf_get_dentry_xattr(dentry, name__str, value_p); |
| 153 | +} |
| 154 | + |
95 | 155 | __bpf_kfunc_end_defs(); |
96 | 156 |
|
97 | 157 | BTF_KFUNCS_START(bpf_fs_kfunc_set_ids) |
98 | 158 | BTF_ID_FLAGS(func, bpf_get_task_exe_file, |
99 | 159 | KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) |
100 | 160 | BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE) |
101 | 161 | BTF_ID_FLAGS(func, bpf_path_d_path, KF_TRUSTED_ARGS) |
| 162 | +BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) |
| 163 | +BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) |
102 | 164 | BTF_KFUNCS_END(bpf_fs_kfunc_set_ids) |
103 | 165 |
|
104 | 166 | static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id) |
|
0 commit comments