Commit 18678cf0 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov
Browse files

selftests/bpf: add tests for BPF object load with implicit token



Add a test to validate libbpf's implicit BPF token creation from default
BPF FS location (/sys/fs/bpf). Also validate that disabling this
implicit BPF token creation works.

Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20231213190842.3844987-9-andrii@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 98e0eaa3
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/unistd.h>
#include <linux/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/un.h>
#include "priv_map.skel.h"
@@ -45,6 +46,13 @@ static inline int sys_fsmount(int fs_fd, unsigned flags, unsigned ms_flags)
	return syscall(__NR_fsmount, fs_fd, flags, ms_flags);
}

static inline int sys_move_mount(int from_dfd, const char *from_path,
				 int to_dfd, const char *to_path,
				 unsigned flags)
{
	return syscall(__NR_move_mount, from_dfd, from_path, to_dfd, to_path, flags);
}

static int drop_priv_caps(__u64 *old_caps)
{
	return cap_disable_effective((1ULL << CAP_BPF) |
@@ -761,6 +769,63 @@ static int userns_obj_priv_btf_success(int mnt_fd)
	return validate_struct_ops_load(mnt_fd, true /* should succeed */);
}

static int userns_obj_priv_implicit_token(int mnt_fd)
{
	LIBBPF_OPTS(bpf_object_open_opts, opts);
	struct dummy_st_ops_success *skel;
	int err;

	/* before we mount BPF FS with token delegation, struct_ops skeleton
	 * should fail to load
	 */
	skel = dummy_st_ops_success__open_and_load();
	if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load")) {
		dummy_st_ops_success__destroy(skel);
		return -EINVAL;
	}

	/* mount custom BPF FS over /sys/fs/bpf so that libbpf can create BPF
	 * token automatically and implicitly
	 */
	err = sys_move_mount(mnt_fd, "", AT_FDCWD, "/sys/fs/bpf", MOVE_MOUNT_F_EMPTY_PATH);
	if (!ASSERT_OK(err, "move_mount_bpffs"))
		return -EINVAL;

	/* now the same struct_ops skeleton should succeed thanks to libppf
	 * creating BPF token from /sys/fs/bpf mount point
	 */
	skel = dummy_st_ops_success__open_and_load();
	if (!ASSERT_OK_PTR(skel, "obj_implicit_token_load"))
		return -EINVAL;

	dummy_st_ops_success__destroy(skel);

	/* now disable implicit token through empty bpf_token_path, should fail */
	opts.bpf_token_path = "";
	skel = dummy_st_ops_success__open_opts(&opts);
	if (!ASSERT_OK_PTR(skel, "obj_empty_token_path_open"))
		return -EINVAL;

	err = dummy_st_ops_success__load(skel);
	dummy_st_ops_success__destroy(skel);
	if (!ASSERT_ERR(err, "obj_empty_token_path_load"))
		return -EINVAL;

	/* now disable implicit token through negative bpf_token_fd, should fail */
	opts.bpf_token_path = NULL;
	opts.bpf_token_fd = -1;
	skel = dummy_st_ops_success__open_opts(&opts);
	if (!ASSERT_OK_PTR(skel, "obj_neg_token_fd_open"))
		return -EINVAL;

	err = dummy_st_ops_success__load(skel);
	dummy_st_ops_success__destroy(skel);
	if (!ASSERT_ERR(err, "obj_neg_token_fd_load"))
		return -EINVAL;

	return 0;
}

#define bit(n) (1ULL << (n))

void test_token(void)
@@ -828,4 +893,15 @@ void test_token(void)

		subtest_userns(&opts, userns_obj_priv_btf_success);
	}
	if (test__start_subtest("obj_priv_implicit_token")) {
		struct bpffs_opts opts = {
			/* allow BTF loading */
			.cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
			.maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
			.progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
			.attachs = ~0ULL,
		};

		subtest_userns(&opts, userns_obj_priv_implicit_token);
	}
}