diff options
Diffstat (limited to 'tools/testing/selftests/bpf/prog_tests/token.c')
| -rw-r--r-- | tools/testing/selftests/bpf/prog_tests/token.c | 97 | 
1 files changed, 96 insertions, 1 deletions
| diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c index c3ab9b6fb069..f9392df23f8a 100644 --- a/tools/testing/selftests/bpf/prog_tests/token.c +++ b/tools/testing/selftests/bpf/prog_tests/token.c @@ -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 */ | 
