mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
selftests/bpf: Test freplace from user namespace
Add selftests to verify that it is possible to load freplace program from user namespace if BPF token is initialized by bpf_object__prepare before calling bpf_program__set_attach_target. Negative test is added as well. Modified type of the priv_prog to xdp, as kprobe did not work on aarch64 and s390x. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: Yonghong Song <yonghong.song@linux.dev> Link: https://lore.kernel.org/bpf/20250317174039.161275-5-mykyta.yatsenko5@gmail.com
This commit is contained in:
committed by
Andrii Nakryiko
parent
974ef9f0d2
commit
a024843d92
@@ -19,6 +19,7 @@
|
||||
#include "priv_prog.skel.h"
|
||||
#include "dummy_st_ops_success.skel.h"
|
||||
#include "token_lsm.skel.h"
|
||||
#include "priv_freplace_prog.skel.h"
|
||||
|
||||
static inline int sys_mount(const char *dev_name, const char *dir_name,
|
||||
const char *type, unsigned long flags,
|
||||
@@ -788,6 +789,84 @@ static int userns_obj_priv_prog(int mnt_fd, struct token_lsm *lsm_skel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int userns_obj_priv_freplace_setup(int mnt_fd, struct priv_freplace_prog **fr_skel,
|
||||
struct priv_prog **skel, int *tgt_fd)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_object_open_opts, opts);
|
||||
int err;
|
||||
char buf[256];
|
||||
|
||||
/* use bpf_token_path to provide BPF FS path */
|
||||
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd);
|
||||
opts.bpf_token_path = buf;
|
||||
*skel = priv_prog__open_opts(&opts);
|
||||
if (!ASSERT_OK_PTR(*skel, "priv_prog__open_opts"))
|
||||
return -EINVAL;
|
||||
err = priv_prog__load(*skel);
|
||||
if (!ASSERT_OK(err, "priv_prog__load"))
|
||||
return -EINVAL;
|
||||
|
||||
*fr_skel = priv_freplace_prog__open_opts(&opts);
|
||||
if (!ASSERT_OK_PTR(*skel, "priv_freplace_prog__open_opts"))
|
||||
return -EINVAL;
|
||||
|
||||
*tgt_fd = bpf_program__fd((*skel)->progs.xdp_prog1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify that freplace works from user namespace, because bpf token is loaded
|
||||
* in bpf_object__prepare
|
||||
*/
|
||||
static int userns_obj_priv_freplace_prog(int mnt_fd, struct token_lsm *lsm_skel)
|
||||
{
|
||||
struct priv_freplace_prog *fr_skel = NULL;
|
||||
struct priv_prog *skel = NULL;
|
||||
int err, tgt_fd;
|
||||
|
||||
err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd);
|
||||
if (!ASSERT_OK(err, "setup"))
|
||||
goto out;
|
||||
|
||||
err = bpf_object__prepare(fr_skel->obj);
|
||||
if (!ASSERT_OK(err, "freplace__prepare"))
|
||||
goto out;
|
||||
|
||||
err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1");
|
||||
if (!ASSERT_OK(err, "set_attach_target"))
|
||||
goto out;
|
||||
|
||||
err = priv_freplace_prog__load(fr_skel);
|
||||
ASSERT_OK(err, "priv_freplace_prog__load");
|
||||
|
||||
out:
|
||||
priv_freplace_prog__destroy(fr_skel);
|
||||
priv_prog__destroy(skel);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Verify that replace fails to set attach target from user namespace without bpf token */
|
||||
static int userns_obj_priv_freplace_prog_fail(int mnt_fd, struct token_lsm *lsm_skel)
|
||||
{
|
||||
struct priv_freplace_prog *fr_skel = NULL;
|
||||
struct priv_prog *skel = NULL;
|
||||
int err, tgt_fd;
|
||||
|
||||
err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd);
|
||||
if (!ASSERT_OK(err, "setup"))
|
||||
goto out;
|
||||
|
||||
err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1");
|
||||
if (ASSERT_ERR(err, "attach fails"))
|
||||
err = 0;
|
||||
else
|
||||
err = -EINVAL;
|
||||
|
||||
out:
|
||||
priv_freplace_prog__destroy(fr_skel);
|
||||
priv_prog__destroy(skel);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* this test is called with BPF FS that doesn't delegate BPF_BTF_LOAD command,
|
||||
* which should cause struct_ops application to fail, as BTF won't be uploaded
|
||||
* into the kernel, even if STRUCT_OPS programs themselves are allowed
|
||||
@@ -1004,12 +1083,28 @@ void test_token(void)
|
||||
if (test__start_subtest("obj_priv_prog")) {
|
||||
struct bpffs_opts opts = {
|
||||
.cmds = bit(BPF_PROG_LOAD),
|
||||
.progs = bit(BPF_PROG_TYPE_KPROBE),
|
||||
.progs = bit(BPF_PROG_TYPE_XDP),
|
||||
.attachs = ~0ULL,
|
||||
};
|
||||
|
||||
subtest_userns(&opts, userns_obj_priv_prog);
|
||||
}
|
||||
if (test__start_subtest("obj_priv_freplace_prog")) {
|
||||
struct bpffs_opts opts = {
|
||||
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
|
||||
.progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
|
||||
.attachs = ~0ULL,
|
||||
};
|
||||
subtest_userns(&opts, userns_obj_priv_freplace_prog);
|
||||
}
|
||||
if (test__start_subtest("obj_priv_freplace_prog_fail")) {
|
||||
struct bpffs_opts opts = {
|
||||
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
|
||||
.progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
|
||||
.attachs = ~0ULL,
|
||||
};
|
||||
subtest_userns(&opts, userns_obj_priv_freplace_prog_fail);
|
||||
}
|
||||
if (test__start_subtest("obj_priv_btf_fail")) {
|
||||
struct bpffs_opts opts = {
|
||||
/* disallow BTF loading */
|
||||
|
||||
Reference in New Issue
Block a user