2
2
/* Copyright (c) 2024 Google LLC. */
3
3
4
4
#include <linux/bpf.h>
5
+ #include <linux/bpf_lsm.h>
5
6
#include <linux/btf.h>
6
7
#include <linux/btf_ids.h>
7
8
#include <linux/dcache.h>
8
9
#include <linux/fs.h>
10
+ #include <linux/fsnotify.h>
9
11
#include <linux/file.h>
10
12
#include <linux/mm.h>
11
13
#include <linux/xattr.h>
@@ -161,6 +163,164 @@ __bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
161
163
return bpf_get_dentry_xattr (dentry , name__str , value_p );
162
164
}
163
165
166
+ static int bpf_xattr_write_permission (const char * name , struct inode * inode )
167
+ {
168
+ if (WARN_ON (!inode ))
169
+ return - EINVAL ;
170
+
171
+ /* Only allow setting and removing security.bpf. xattrs */
172
+ if (!match_security_bpf_prefix (name ))
173
+ return - EPERM ;
174
+
175
+ return inode_permission (& nop_mnt_idmap , inode , MAY_WRITE );
176
+ }
177
+
178
+ static int __bpf_set_dentry_xattr (struct dentry * dentry , const char * name ,
179
+ const struct bpf_dynptr * value_p , int flags , bool lock_inode )
180
+ {
181
+ struct bpf_dynptr_kern * value_ptr = (struct bpf_dynptr_kern * )value_p ;
182
+ struct inode * inode = d_inode (dentry );
183
+ const void * value ;
184
+ u32 value_len ;
185
+ int ret ;
186
+
187
+ value_len = __bpf_dynptr_size (value_ptr );
188
+ value = __bpf_dynptr_data (value_ptr , value_len );
189
+ if (!value )
190
+ return - EINVAL ;
191
+
192
+ if (lock_inode )
193
+ inode_lock (inode );
194
+
195
+ ret = bpf_xattr_write_permission (name , inode );
196
+ if (ret )
197
+ goto out ;
198
+
199
+ ret = __vfs_setxattr (& nop_mnt_idmap , dentry , inode , name ,
200
+ value , value_len , flags );
201
+ if (!ret ) {
202
+ fsnotify_xattr (dentry );
203
+
204
+ /* This xattr is set by BPF LSM, so we do not call
205
+ * security_inode_post_setxattr. This is the same as
206
+ * security_inode_setsecurity().
207
+ */
208
+ }
209
+ out :
210
+ if (lock_inode )
211
+ inode_unlock (inode );
212
+ return ret ;
213
+ }
214
+
215
+ /**
216
+ * bpf_set_dentry_xattr - set a xattr of a dentry
217
+ * @dentry: dentry to get xattr from
218
+ * @name__str: name of the xattr
219
+ * @value_p: xattr value
220
+ * @flags: flags to pass into filesystem operations
221
+ *
222
+ * Set xattr *name__str* of *dentry* to the value in *value_ptr*.
223
+ *
224
+ * For security reasons, only *name__str* with prefix "security.bpf."
225
+ * is allowed.
226
+ *
227
+ * The caller has not locked dentry->d_inode.
228
+ *
229
+ * Return: 0 on success, a negative value on error.
230
+ */
231
+ __bpf_kfunc int bpf_set_dentry_xattr (struct dentry * dentry , const char * name__str ,
232
+ const struct bpf_dynptr * value_p , int flags )
233
+ {
234
+ return __bpf_set_dentry_xattr (dentry , name__str , value_p , flags , true);
235
+ }
236
+
237
+ /**
238
+ * bpf_set_dentry_xattr_locked - set a xattr of a dentry
239
+ * @dentry: dentry to get xattr from
240
+ * @name__str: name of the xattr
241
+ * @value_p: xattr value
242
+ * @flags: flags to pass into filesystem operations
243
+ *
244
+ * Set xattr *name__str* of *dentry* to the value in *value_ptr*.
245
+ *
246
+ * For security reasons, only *name__str* with prefix "security.bpf."
247
+ * is allowed.
248
+ *
249
+ * The caller already locked dentry->d_inode.
250
+ *
251
+ * Return: 0 on success, a negative value on error.
252
+ */
253
+ __bpf_kfunc int bpf_set_dentry_xattr_locked (struct dentry * dentry , const char * name__str ,
254
+ const struct bpf_dynptr * value_p , int flags )
255
+ {
256
+ return __bpf_set_dentry_xattr (dentry , name__str , value_p , flags , false);
257
+ }
258
+
259
+ static int __bpf_remove_dentry_xattr (struct dentry * dentry , const char * name__str ,
260
+ bool lock_inode )
261
+ {
262
+ struct inode * inode = d_inode (dentry );
263
+ int ret ;
264
+
265
+ if (lock_inode )
266
+ inode_lock (inode );
267
+
268
+ ret = bpf_xattr_write_permission (name__str , inode );
269
+ if (ret )
270
+ goto out ;
271
+
272
+ ret = __vfs_removexattr (& nop_mnt_idmap , dentry , name__str );
273
+ if (!ret ) {
274
+ fsnotify_xattr (dentry );
275
+
276
+ /* This xattr is removed by BPF LSM, so we do not call
277
+ * security_inode_post_removexattr.
278
+ */
279
+ }
280
+ out :
281
+ if (lock_inode )
282
+ inode_unlock (inode );
283
+ return ret ;
284
+ }
285
+
286
+ /**
287
+ * bpf_remove_dentry_xattr - remove a xattr of a dentry
288
+ * @dentry: dentry to get xattr from
289
+ * @name__str: name of the xattr
290
+ *
291
+ * Rmove xattr *name__str* of *dentry*.
292
+ *
293
+ * For security reasons, only *name__str* with prefix "security.bpf."
294
+ * is allowed.
295
+ *
296
+ * The caller has not locked dentry->d_inode.
297
+ *
298
+ * Return: 0 on success, a negative value on error.
299
+ */
300
+ __bpf_kfunc int bpf_remove_dentry_xattr (struct dentry * dentry , const char * name__str )
301
+ {
302
+ return __bpf_remove_dentry_xattr (dentry , name__str , true);
303
+ }
304
+
305
+ /**
306
+ * bpf_remove_dentry_xattr_locked - remove a xattr of a dentry
307
+ * @dentry: dentry to get xattr from
308
+ * @name__str: name of the xattr
309
+ *
310
+ * Rmove xattr *name__str* of *dentry*.
311
+ *
312
+ * For security reasons, only *name__str* with prefix "security.bpf."
313
+ * is allowed.
314
+ *
315
+ * The caller already locked dentry->d_inode.
316
+ *
317
+ * Return: 0 on success, a negative value on error.
318
+ */
319
+ __bpf_kfunc int bpf_remove_dentry_xattr_locked (struct dentry * dentry , const char * name__str )
320
+ {
321
+ return __bpf_remove_dentry_xattr (dentry , name__str , false);
322
+ }
323
+
164
324
__bpf_kfunc_end_defs ();
165
325
166
326
BTF_KFUNCS_START (bpf_fs_kfunc_set_ids )
@@ -170,20 +330,83 @@ BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE)
170
330
BTF_ID_FLAGS (func , bpf_path_d_path , KF_TRUSTED_ARGS )
171
331
BTF_ID_FLAGS (func , bpf_get_dentry_xattr , KF_SLEEPABLE | KF_TRUSTED_ARGS )
172
332
BTF_ID_FLAGS (func , bpf_get_file_xattr , KF_SLEEPABLE | KF_TRUSTED_ARGS )
333
+ BTF_ID_FLAGS (func , bpf_set_dentry_xattr , KF_SLEEPABLE | KF_TRUSTED_ARGS )
334
+ BTF_ID_FLAGS (func , bpf_remove_dentry_xattr , KF_SLEEPABLE | KF_TRUSTED_ARGS )
173
335
BTF_KFUNCS_END (bpf_fs_kfunc_set_ids )
174
336
337
+ BTF_HIDDEN_KFUNCS_START (bpf_fs_kfunc_hidden_set_ids )
338
+ BTF_ID_FLAGS (func , bpf_set_dentry_xattr_locked , KF_SLEEPABLE | KF_TRUSTED_ARGS )
339
+ BTF_ID_FLAGS (func , bpf_remove_dentry_xattr_locked , KF_SLEEPABLE | KF_TRUSTED_ARGS )
340
+ BTF_KFUNCS_END (bpf_fs_kfunc_hidden_set_ids )
341
+
175
342
static int bpf_fs_kfuncs_filter (const struct bpf_prog * prog , u32 kfunc_id )
176
343
{
177
- if (!btf_id_set8_contains (& bpf_fs_kfunc_set_ids , kfunc_id ) ||
178
- prog -> type == BPF_PROG_TYPE_LSM )
344
+ if (!btf_id_set8_contains (& bpf_fs_kfunc_set_ids , kfunc_id ) &&
345
+ !btf_id_set8_contains (& bpf_fs_kfunc_hidden_set_ids , kfunc_id ))
346
+ return 0 ;
347
+ if (prog - > type == BPF_PROG_TYPE_LSM )
179
348
return 0 ;
180
349
return - EACCES ;
181
350
}
182
351
352
+ /* bpf_[set|remove]_dentry_xattr.* hooks have KF_TRUSTED_ARGS and
353
+ * KF_SLEEPABLE, so they are only available to sleepable hooks with
354
+ * dentry arguments.
355
+ *
356
+ * Setting and removing xattr requires exclusive lock on dentry->d_inode.
357
+ * Some hooks already locked d_inode, while some hooks have not locked
358
+ * d_inode. Therefore, we need different kfuncs for different hooks.
359
+ * Specifically, hooks in the following list (d_inode_locked_hooks)
360
+ * should call bpf_[set|remove]_dentry_xattr_locked; while other hooks
361
+ * should call bpf_[set|remove]_dentry_xattr.
362
+ */
363
+ BTF_SET_START (d_inode_locked_hooks )
364
+ BTF_ID (func , bpf_lsm_inode_post_removexattr )
365
+ BTF_ID (func , bpf_lsm_inode_post_setattr )
366
+ BTF_ID (func , bpf_lsm_inode_post_setxattr )
367
+ BTF_ID (func , bpf_lsm_inode_removexattr )
368
+ BTF_ID (func , bpf_lsm_inode_rmdir )
369
+ BTF_ID (func , bpf_lsm_inode_setattr )
370
+ BTF_ID (func , bpf_lsm_inode_setxattr )
371
+ BTF_ID (func , bpf_lsm_inode_unlink )
372
+ #ifdef CONFIG_SECURITY_PATH
373
+ BTF_ID (func , bpf_lsm_path_unlink )
374
+ BTF_ID (func , bpf_lsm_path_rmdir )
375
+ #endif /* CONFIG_SECURITY_PATH */
376
+ BTF_SET_END (d_inode_locked_hooks )
377
+
378
+ static bool bpf_lsm_has_d_inode_locked (const struct bpf_prog * prog )
379
+ {
380
+ return btf_id_set_contains (& d_inode_locked_hooks , prog -> aux -> attach_btf_id );
381
+ }
382
+
383
+ BTF_ID_LIST (not_locked_fs_kfuncs )
384
+ BTF_ID (func , bpf_set_dentry_xattr )
385
+ BTF_ID (func , bpf_remove_dentry_xattr )
386
+
387
+ BTF_ID_LIST (locked_fs_kfuncs )
388
+ BTF_ID (func , bpf_set_dentry_xattr_locked )
389
+ BTF_ID (func , bpf_remove_dentry_xattr_locked )
390
+
391
+ static u32 bpf_fs_kfunc_remap (const struct bpf_prog * prog , u32 kfunc_id )
392
+ {
393
+ if (!bpf_lsm_has_d_inode_locked (prog ))
394
+ return 0 ;
395
+
396
+ if (kfunc_id == not_locked_fs_kfuncs [0 ])
397
+ return locked_fs_kfuncs [0 ];
398
+ if (kfunc_id == not_locked_fs_kfuncs [1 ])
399
+ return locked_fs_kfuncs [1 ];
400
+
401
+ return 0 ;
402
+ }
403
+
183
404
static const struct btf_kfunc_id_set bpf_fs_kfunc_set = {
184
405
.owner = THIS_MODULE ,
185
406
.set = & bpf_fs_kfunc_set_ids ,
407
+ .hidden_set = & bpf_fs_kfunc_hidden_set_ids ,
186
408
.filter = bpf_fs_kfuncs_filter ,
409
+ .remap = bpf_fs_kfunc_remap ,
187
410
};
188
411
189
412
static int __init bpf_fs_kfuncs_init (void )
0 commit comments