|
19 | 19 | #include "priv_prog.skel.h"
|
20 | 20 | #include "dummy_st_ops_success.skel.h"
|
21 | 21 | #include "token_lsm.skel.h"
|
| 22 | +#include "priv_freplace_prog.skel.h" |
22 | 23 |
|
23 | 24 | static inline int sys_mount(const char *dev_name, const char *dir_name,
|
24 | 25 | const char *type, unsigned long flags,
|
@@ -788,6 +789,84 @@ static int userns_obj_priv_prog(int mnt_fd, struct token_lsm *lsm_skel)
|
788 | 789 | return 0;
|
789 | 790 | }
|
790 | 791 |
|
| 792 | +static int userns_obj_priv_freplace_setup(int mnt_fd, struct priv_freplace_prog **fr_skel, |
| 793 | + struct priv_prog **skel, int *tgt_fd) |
| 794 | +{ |
| 795 | + LIBBPF_OPTS(bpf_object_open_opts, opts); |
| 796 | + int err; |
| 797 | + char buf[256]; |
| 798 | + |
| 799 | + /* use bpf_token_path to provide BPF FS path */ |
| 800 | + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", mnt_fd); |
| 801 | + opts.bpf_token_path = buf; |
| 802 | + *skel = priv_prog__open_opts(&opts); |
| 803 | + if (!ASSERT_OK_PTR(*skel, "priv_prog__open_opts")) |
| 804 | + return -EINVAL; |
| 805 | + err = priv_prog__load(*skel); |
| 806 | + if (!ASSERT_OK(err, "priv_prog__load")) |
| 807 | + return -EINVAL; |
| 808 | + |
| 809 | + *fr_skel = priv_freplace_prog__open_opts(&opts); |
| 810 | + if (!ASSERT_OK_PTR(*skel, "priv_freplace_prog__open_opts")) |
| 811 | + return -EINVAL; |
| 812 | + |
| 813 | + *tgt_fd = bpf_program__fd((*skel)->progs.xdp_prog1); |
| 814 | + return 0; |
| 815 | +} |
| 816 | + |
| 817 | +/* Verify that freplace works from user namespace, because bpf token is loaded |
| 818 | + * in bpf_object__prepare |
| 819 | + */ |
| 820 | +static int userns_obj_priv_freplace_prog(int mnt_fd, struct token_lsm *lsm_skel) |
| 821 | +{ |
| 822 | + struct priv_freplace_prog *fr_skel = NULL; |
| 823 | + struct priv_prog *skel = NULL; |
| 824 | + int err, tgt_fd; |
| 825 | + |
| 826 | + err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd); |
| 827 | + if (!ASSERT_OK(err, "setup")) |
| 828 | + goto out; |
| 829 | + |
| 830 | + err = bpf_object__prepare(fr_skel->obj); |
| 831 | + if (!ASSERT_OK(err, "freplace__prepare")) |
| 832 | + goto out; |
| 833 | + |
| 834 | + err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1"); |
| 835 | + if (!ASSERT_OK(err, "set_attach_target")) |
| 836 | + goto out; |
| 837 | + |
| 838 | + err = priv_freplace_prog__load(fr_skel); |
| 839 | + ASSERT_OK(err, "priv_freplace_prog__load"); |
| 840 | + |
| 841 | +out: |
| 842 | + priv_freplace_prog__destroy(fr_skel); |
| 843 | + priv_prog__destroy(skel); |
| 844 | + return err; |
| 845 | +} |
| 846 | + |
| 847 | +/* Verify that replace fails to set attach target from user namespace without bpf token */ |
| 848 | +static int userns_obj_priv_freplace_prog_fail(int mnt_fd, struct token_lsm *lsm_skel) |
| 849 | +{ |
| 850 | + struct priv_freplace_prog *fr_skel = NULL; |
| 851 | + struct priv_prog *skel = NULL; |
| 852 | + int err, tgt_fd; |
| 853 | + |
| 854 | + err = userns_obj_priv_freplace_setup(mnt_fd, &fr_skel, &skel, &tgt_fd); |
| 855 | + if (!ASSERT_OK(err, "setup")) |
| 856 | + goto out; |
| 857 | + |
| 858 | + err = bpf_program__set_attach_target(fr_skel->progs.new_xdp_prog2, tgt_fd, "xdp_prog1"); |
| 859 | + if (ASSERT_ERR(err, "attach fails")) |
| 860 | + err = 0; |
| 861 | + else |
| 862 | + err = -EINVAL; |
| 863 | + |
| 864 | +out: |
| 865 | + priv_freplace_prog__destroy(fr_skel); |
| 866 | + priv_prog__destroy(skel); |
| 867 | + return err; |
| 868 | +} |
| 869 | + |
791 | 870 | /* this test is called with BPF FS that doesn't delegate BPF_BTF_LOAD command,
|
792 | 871 | * which should cause struct_ops application to fail, as BTF won't be uploaded
|
793 | 872 | * into the kernel, even if STRUCT_OPS programs themselves are allowed
|
@@ -1004,12 +1083,28 @@ void test_token(void)
|
1004 | 1083 | if (test__start_subtest("obj_priv_prog")) {
|
1005 | 1084 | struct bpffs_opts opts = {
|
1006 | 1085 | .cmds = bit(BPF_PROG_LOAD),
|
1007 |
| - .progs = bit(BPF_PROG_TYPE_KPROBE), |
| 1086 | + .progs = bit(BPF_PROG_TYPE_XDP), |
1008 | 1087 | .attachs = ~0ULL,
|
1009 | 1088 | };
|
1010 | 1089 |
|
1011 | 1090 | subtest_userns(&opts, userns_obj_priv_prog);
|
1012 | 1091 | }
|
| 1092 | + if (test__start_subtest("obj_priv_freplace_prog")) { |
| 1093 | + struct bpffs_opts opts = { |
| 1094 | + .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID), |
| 1095 | + .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP), |
| 1096 | + .attachs = ~0ULL, |
| 1097 | + }; |
| 1098 | + subtest_userns(&opts, userns_obj_priv_freplace_prog); |
| 1099 | + } |
| 1100 | + if (test__start_subtest("obj_priv_freplace_prog_fail")) { |
| 1101 | + struct bpffs_opts opts = { |
| 1102 | + .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID), |
| 1103 | + .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP), |
| 1104 | + .attachs = ~0ULL, |
| 1105 | + }; |
| 1106 | + subtest_userns(&opts, userns_obj_priv_freplace_prog_fail); |
| 1107 | + } |
1013 | 1108 | if (test__start_subtest("obj_priv_btf_fail")) {
|
1014 | 1109 | struct bpffs_opts opts = {
|
1015 | 1110 | /* disallow BTF loading */
|
|
0 commit comments