/* pass BPF FS context object to parent */
err = sendfd(sock_fd, fs_fd); if (!ASSERT_OK(err, "send_fs_fd")) goto cleanup;
/* wait that the parent reads the fd, does the fsconfig() calls * and send us a signal that it is done
*/
err = read(sock_fd, &one, sizeof(one)); if (!ASSERT_GE(err, 0, "read_one")) goto cleanup;
/* avoid mucking around with mount namespaces and mounting at * well-known path, just create O_PATH fd for detached mount
*/
mnt_fd = sys_fsmount(fs_fd, 0, 0); if (!ASSERT_OK_FD(mnt_fd, "mnt_fd")) goto cleanup;
/* try to fspick() BPF FS and try to add some delegation options */
fs_fd = sys_fspick(mnt_fd, "", FSPICK_EMPTY_PATH); if (!ASSERT_GE(fs_fd, 0, "bpffs_fspick")) {
err = -EINVAL; goto cleanup;
}
/* create BPF token FD and pass it to parent for some extra checks */
token_fd = bpf_token_create(bpffs_fd, NULL); if (!ASSERT_GT(token_fd, 0, "child_token_create")) {
err = -EINVAL; goto cleanup;
}
err = sendfd(sock_fd, token_fd); if (!ASSERT_OK(err, "send_token_fd")) goto cleanup;
zclose(token_fd);
/* do custom test logic with customly set up BPF FS instance */
err = callback(bpffs_fd, lsm_skel); if (!ASSERT_OK(err, "test_callback")) goto cleanup;
/* notify the child that we did the fsconfig() calls and it can proceed. */
err = write(sock_fd, &one, sizeof(one)); if (!ASSERT_EQ(err, sizeof(one), "send_one")) goto cleanup;
zclose(fs_fd);
/* receive BPF token FD back from child for some extra tests */
err = recvfd(sock_fd, &token_fd); if (!ASSERT_OK(err, "recv_token_fd")) goto cleanup;
/* create BPF token from BPF FS mount */
token_fd = bpf_token_create(mnt_fd, NULL); if (!ASSERT_GT(token_fd, 0, "token_create")) {
err = -EINVAL; goto cleanup;
}
/* while inside non-init userns, we need both a BPF token *and* * CAP_BPF inside current userns to create privileged map; let's test * that neither BPF token alone nor namespaced CAP_BPF is sufficient
*/
err = drop_priv_caps(&old_caps); if (!ASSERT_OK(err, "drop_caps")) goto cleanup;
/* create BPF token from BPF FS mount */
token_fd = bpf_token_create(mnt_fd, NULL); if (!ASSERT_GT(token_fd, 0, "token_create")) {
err = -EINVAL; goto cleanup;
}
/* while inside non-init userns, we need both a BPF token *and* * CAP_BPF inside current userns to create privileged map; let's test * that neither BPF token alone nor namespaced CAP_BPF is sufficient
*/
err = drop_priv_caps(&old_caps); if (!ASSERT_OK(err, "drop_caps")) goto cleanup;
/* setup a trivial BTF data to load to the kernel */
btf = btf__new_empty(); if (!ASSERT_OK_PTR(btf, "empty_btf")) goto cleanup;
/* create BPF token from BPF FS mount */
token_fd = bpf_token_create(mnt_fd, NULL); if (!ASSERT_GT(token_fd, 0, "token_create")) {
err = -EINVAL; goto cleanup;
}
/* validate we can successfully load BPF program with token; this * being XDP program (CAP_NET_ADMIN) using bpf_jiffies64() (CAP_BPF) * and bpf_get_current_task() (CAP_PERFMON) helpers validates we have * BPF token wired properly in a bunch of places in the kernel
*/
prog_opts.prog_flags = BPF_F_TOKEN_FD;
prog_opts.token_fd = token_fd;
prog_opts.expected_attach_type = BPF_XDP;
prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, "token_prog", "GPL",
insns, insn_cnt, &prog_opts); if (!ASSERT_GT(prog_fd, 0, "prog_fd")) {
err = -EPERM; goto cleanup;
}
/* Verify that freplace works from user namespace, because bpf token is loaded * in bpf_object__prepare
*/ staticint 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;
/* 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
*/ staticint validate_struct_ops_load(int mnt_fd, bool expect_success)
{
LIBBPF_OPTS(bpf_object_open_opts, opts); char buf[256]; 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;
/* disable implicit BPF token creation by setting * LIBBPF_BPF_TOKEN_PATH envvar to empty value, load should fail
*/
err = setenv(TOKEN_ENVVAR, "", 1/*overwrite*/); if (!ASSERT_OK(err, "setenv_token_path")) return -EINVAL;
skel = dummy_st_ops_success__open_and_load(); if (!ASSERT_ERR_PTR(skel, "obj_token_envvar_disabled_load")) {
unsetenv(TOKEN_ENVVAR);
dummy_st_ops_success__destroy(skel); return -EINVAL;
}
unsetenv(TOKEN_ENVVAR);
/* now the same struct_ops skeleton should succeed thanks to libbpf * 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;
/* 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 custom location, so libbpf can't create * BPF token implicitly, unless pointed to it through * LIBBPF_BPF_TOKEN_PATH envvar
*/
rmdir(custom_dir); if (!ASSERT_OK(mkdir(custom_dir, 0777), "mkdir_bpffs_custom")) goto err_out;
err = sys_move_mount(mnt_fd, "", AT_FDCWD, custom_dir, MOVE_MOUNT_F_EMPTY_PATH); if (!ASSERT_OK(err, "move_mount_bpffs")) goto err_out;
/* even though we have BPF FS with delegation, it's not at default * /sys/fs/bpf location, so we still fail to load until envvar is set up
*/
skel = dummy_st_ops_success__open_and_load(); if (!ASSERT_ERR_PTR(skel, "obj_tokenless_load2")) {
dummy_st_ops_success__destroy(skel); goto err_out;
}
err = setenv(TOKEN_ENVVAR, custom_dir, 1/*overwrite*/); if (!ASSERT_OK(err, "setenv_token_path")) goto err_out;
/* now the same struct_ops skeleton should succeed thanks to libbpf * creating BPF token from custom mount point
*/
skel = dummy_st_ops_success__open_and_load(); if (!ASSERT_OK_PTR(skel, "obj_implicit_token_load")) goto err_out;
dummy_st_ops_success__destroy(skel);
/* now disable implicit token through empty bpf_token_path, envvar * will be ignored, should fail
*/
opts.bpf_token_path = "";
skel = dummy_st_ops_success__open_opts(&opts); if (!ASSERT_OK_PTR(skel, "obj_empty_token_path_open")) goto err_out;
err = dummy_st_ops_success__load(skel);
dummy_st_ops_success__destroy(skel); if (!ASSERT_ERR(err, "obj_empty_token_path_load")) goto err_out;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet am 2026-06-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.