mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
bpf: allow fs kfuncs for binfmt_misc_ops programs
The fs kfuncs are currently exclusive to LSM programs. A binfmt_misc handler needs a subset of them to do anything interesting: computing an interpreter relative to the binary's location wants bpf_path_d_path() on bprm->file->f_path from the load program, and matching on per-binary metadata wants bpf_get_file_xattr() and friends right from the match program. Register the fs kfunc set for struct_ops programs as well and extend the filter to admit binfmt_misc_ops programs. The xattr setters stay exclusive to LSM programs: a binary type handler decides how to run a binary, it has no business modifying filesystem state. This only takes effect in builds that have the fs kfunc set at all, i.e. CONFIG_BPF_LSM. Without it a binfmt_misc handler is limited to bprm fields and the file-backed dynptr, which are provided by the common kfunc set. Link: https://lore.kernel.org/20260704211409.1978485-1-farid.m.zakaria@gmail.com Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-5-57b7529c002c@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
ceb912149e
commit
7bddf0e9f1
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2024 Google LLC. */
|
||||
|
||||
#include <linux/binfmt_misc.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_lsm.h>
|
||||
#include <linux/btf.h>
|
||||
|
|
@ -392,10 +393,25 @@ BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE)
|
|||
BTF_ID_FLAGS(func, bpf_real_data_inode, KF_SLEEPABLE | KF_RET_NULL)
|
||||
BTF_KFUNCS_END(bpf_fs_kfunc_set_ids)
|
||||
|
||||
/* Side-effecting kfuncs that stay exclusive to LSM programs. */
|
||||
BTF_SET_START(bpf_fs_kfunc_lsm_only_ids)
|
||||
BTF_ID(func, bpf_set_dentry_xattr)
|
||||
BTF_ID(func, bpf_remove_dentry_xattr)
|
||||
BTF_SET_END(bpf_fs_kfunc_lsm_only_ids)
|
||||
|
||||
static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
|
||||
{
|
||||
if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
|
||||
prog->type == BPF_PROG_TYPE_LSM)
|
||||
if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id))
|
||||
return 0;
|
||||
if (prog->type == BPF_PROG_TYPE_LSM)
|
||||
return 0;
|
||||
if (prog->type != BPF_PROG_TYPE_STRUCT_OPS)
|
||||
return -EACCES;
|
||||
/* ->st_ops is unset during the cfg pass; enforced once it is set. */
|
||||
if (!prog->aux->st_ops)
|
||||
return 0;
|
||||
if (bpf_prog_is_binfmt_misc_ops(prog) &&
|
||||
!btf_id_set_contains(&bpf_fs_kfunc_lsm_only_ids, kfunc_id))
|
||||
return 0;
|
||||
return -EACCES;
|
||||
}
|
||||
|
|
@ -438,7 +454,13 @@ static const struct btf_kfunc_id_set bpf_fs_kfunc_set = {
|
|||
|
||||
static int __init bpf_fs_kfuncs_init(void)
|
||||
{
|
||||
return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set);
|
||||
int ret;
|
||||
|
||||
ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set);
|
||||
if (ret || !IS_ENABLED(CONFIG_BINFMT_MISC_BPF))
|
||||
return ret;
|
||||
return register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
|
||||
&bpf_fs_kfunc_set);
|
||||
}
|
||||
|
||||
late_initcall(bpf_fs_kfuncs_init);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user