From: Jiri Olsa <jolsa@kernel.org> Date: 2021-03-28 11:27:38
hi,
while adding test for pinning the module while there's
trampoline attach to it, I noticed that we don't allow
link detach and following re-attach for trampolines.
I'm not sure this was on purpose, but seems as natural
use of the interface, although the only user is the test
for now.
You need to have patch [1] from bpf tree for test module
attach test to pass.
thanks,
jirka
[1] https://lore.kernel.org/bpf/20210326105900.151466-1-jolsa@kernel.org/
---
Jiri Olsa (4):
bpf: Allow trampoline re-attach
selftests/bpf: Add re-attach test to fentry_test
selftests/bpf: Add re-attach test to fexit_test
selftests/bpf: Test that module can't be unloaded with attached trampoline
kernel/bpf/syscall.c | 25 +++++++++++++++++++------
kernel/bpf/trampoline.c | 2 +-
tools/testing/selftests/bpf/prog_tests/fentry_test.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-------------
tools/testing/selftests/bpf/prog_tests/fexit_test.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-------------
tools/testing/selftests/bpf/prog_tests/module_attach.c | 23 +++++++++++++++++++++++
5 files changed, 133 insertions(+), 33 deletions(-)
From: Jiri Olsa <jolsa@kernel.org> Date: 2021-03-28 11:27:37
Currently we don't allow re-attaching of trampolines. Once
it's detached, it can't be re-attach even when the program
is still loaded.
Adding the possibility to re-attach the loaded tracing
kernel program.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
kernel/bpf/syscall.c | 25 +++++++++++++++++++------
kernel/bpf/trampoline.c | 2 +-
2 files changed, 20 insertions(+), 7 deletions(-)
From: Jiri Olsa <jolsa@kernel.org> Date: 2021-03-28 11:27:38
Adding the test to re-attach (detach/attach again) tracing
fentry programs, plus check that already linked program can't
be attached again.
Fixing the number of check-ed results, which should be 8.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
.../selftests/bpf/prog_tests/fentry_test.c | 58 ++++++++++++++-----
1 file changed, 45 insertions(+), 13 deletions(-)
@@ -26,12 +19,51 @@ void test_fentry_test(void)err,errno,retval,duration);result=(__u64*)fentry_skel->bss;-for(i=0;i<6;i++){+for(i=0;i<8;i++){if(CHECK(result[i]!=1,"result","fentry_test%d failed err %lld\n",i+1,result[i]))-gotocleanup;+return-1;}+/* zero results for re-attach test */+for(i=0;i<8;i++)+result[i]=0;+return0;+}++voidtest_fentry_test(void)+{+structfentry_test*fentry_skel=NULL;+structbpf_link*link;+interr;++fentry_skel=fentry_test__open_and_load();+if(CHECK(!fentry_skel,"fentry_skel_load","fentry skeleton failed\n"))+gotocleanup;++err=fentry_test__attach(fentry_skel);+if(CHECK(err,"fentry_attach","fentry attach failed: %d\n",err))+gotocleanup;++err=fentry_test(fentry_skel);+if(CHECK(err,"fentry_test","fentry test failed: %d\n",err))+gotocleanup;++fentry_test__detach(fentry_skel);++/* Re-attach and test again */+err=fentry_test__attach(fentry_skel);+if(CHECK(err,"fentry_attach","fentry re-attach failed: %d\n",err))+gotocleanup;++link=bpf_program__attach(fentry_skel->progs.test1);+if(CHECK(!IS_ERR(link),"attach_fentry re-attach without detach",+"err: %ld\n",PTR_ERR(link)))+gotocleanup;++err=fentry_test(fentry_skel);+CHECK(err,"fentry_test","fentry test failed: %d\n",err);+cleanup:fentry_test__destroy(fentry_skel);}
From: Jiri Olsa <jolsa@kernel.org> Date: 2021-03-28 11:27:38
Adding test to verify that once we attach module's trampoline,
the module can't be unloaded.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
.../selftests/bpf/prog_tests/module_attach.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
From: Jiri Olsa <jolsa@kernel.org> Date: 2021-03-28 11:27:38
Adding the test to re-attach (detach/attach again) tracing
fexit programs, plus check that already linked program can't
be attached again.
Fixing the number of check-ed results, which should be 8.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
.../selftests/bpf/prog_tests/fexit_test.c | 58 ++++++++++++++-----
1 file changed, 45 insertions(+), 13 deletions(-)
@@ -26,12 +19,51 @@ void test_fexit_test(void)err,errno,retval,duration);result=(__u64*)fexit_skel->bss;-for(i=0;i<6;i++){+for(i=0;i<8;i++){if(CHECK(result[i]!=1,"result","fexit_test%d failed err %lld\n",i+1,result[i]))-gotocleanup;+return-1;}+/* zero results for re-attach test */+for(i=0;i<8;i++)+result[i]=0;+return0;+}++voidtest_fexit_test(void)+{+structfexit_test*fexit_skel=NULL;+structbpf_link*link;+interr;++fexit_skel=fexit_test__open_and_load();+if(CHECK(!fexit_skel,"fexit_skel_load","fexit skeleton failed\n"))+gotocleanup;++err=fexit_test__attach(fexit_skel);+if(CHECK(err,"fexit_attach","fexit attach failed: %d\n",err))+gotocleanup;++err=fexit_test(fexit_skel);+if(CHECK(err,"fexit_test","exit test failed: %d\n",err))+gotocleanup;++fexit_test__detach(fexit_skel);++/* Re-attach and test again */+err=fexit_test__attach(fexit_skel);+if(CHECK(err,"fexit_attach","fexit attach failed: %d\n",err))+gotocleanup;++link=bpf_program__attach(fexit_skel->progs.test1);+if(CHECK(!IS_ERR(link),"attach_fexit re-attach without detach",+"err: %ld\n",PTR_ERR(link)))+gotocleanup;++err=fexit_test(fexit_skel);+CHECK(err,"fexit_test","fexit test failed: %d\n",err);+cleanup:fexit_test__destroy(fexit_skel);}
On Mar 28, 2021, at 4:26 AM, Jiri Olsa [off-list ref] wrote:
Currently we don't allow re-attaching of trampolines. Once
it's detached, it can't be re-attach even when the program
is still loaded.
Adding the possibility to re-attach the loaded tracing
kernel program.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
On Mar 28, 2021, at 4:26 AM, Jiri Olsa [off-list ref] wrote:
Adding the test to re-attach (detach/attach again) tracing
fentry programs, plus check that already linked program can't
be attached again.
Fixing the number of check-ed results, which should be 8.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
[...]
+
+void test_fentry_test(void)
+{
+ struct fentry_test *fentry_skel = NULL;
+ struct bpf_link *link;
+ int err;
+
+ fentry_skel = fentry_test__open_and_load();
+ if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
+ goto cleanup;
+
+ err = fentry_test__attach(fentry_skel);
+ if (CHECK(err, "fentry_attach", "fentry attach failed: %d\n", err))
+ goto cleanup;
+
+ err = fentry_test(fentry_skel);
+ if (CHECK(err, "fentry_test", "fentry test failed: %d\n", err))
+ goto cleanup;
+
+ fentry_test__detach(fentry_skel);
+
+ /* Re-attach and test again */
+ err = fentry_test__attach(fentry_skel);
+ if (CHECK(err, "fentry_attach", "fentry re-attach failed: %d\n", err))
+ goto cleanup;
+
+ link = bpf_program__attach(fentry_skel->progs.test1);
+ if (CHECK(!IS_ERR(link), "attach_fentry re-attach without detach",
+ "err: %ld\n", PTR_ERR(link)))
nit: I guess we shouldn't print PTR_ERR(link) when link is not an error code?
This shouldn't break though.
Thanks,
Song
On Mar 28, 2021, at 4:26 AM, Jiri Olsa [off-list ref] wrote:
Adding test to verify that once we attach module's trampoline,
the module can't be unloaded.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
From: Jiri Olsa <hidden> Date: 2021-03-30 20:03:50
On Tue, Mar 30, 2021 at 01:23:15AM +0000, Song Liu wrote:
quoted
On Mar 28, 2021, at 4:26 AM, Jiri Olsa [off-list ref] wrote:
Adding the test to re-attach (detach/attach again) tracing
fentry programs, plus check that already linked program can't
be attached again.
Fixing the number of check-ed results, which should be 8.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
[...]
quoted
+
+void test_fentry_test(void)
+{
+ struct fentry_test *fentry_skel = NULL;
+ struct bpf_link *link;
+ int err;
+
+ fentry_skel = fentry_test__open_and_load();
+ if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
+ goto cleanup;
+
+ err = fentry_test__attach(fentry_skel);
+ if (CHECK(err, "fentry_attach", "fentry attach failed: %d\n", err))
+ goto cleanup;
+
+ err = fentry_test(fentry_skel);
+ if (CHECK(err, "fentry_test", "fentry test failed: %d\n", err))
+ goto cleanup;
+
+ fentry_test__detach(fentry_skel);
+
+ /* Re-attach and test again */
+ err = fentry_test__attach(fentry_skel);
+ if (CHECK(err, "fentry_attach", "fentry re-attach failed: %d\n", err))
+ goto cleanup;
+
+ link = bpf_program__attach(fentry_skel->progs.test1);
+ if (CHECK(!IS_ERR(link), "attach_fentry re-attach without detach",
+ "err: %ld\n", PTR_ERR(link)))
nit: I guess we shouldn't print PTR_ERR(link) when link is not an error code?
This shouldn't break though.
true, makes no sense.. I'll remove it
thanks,
jirka
Currently we don't allow re-attaching of trampolines. Once
it's detached, it can't be re-attach even when the program
is still loaded.
Adding the possibility to re-attach the loaded tracing
kernel program.
Hmm, yeah, didn't really consider this case when I added the original
disallow. But don't see why not, so (with one nit below):
Acked-by: Toke Høiland-Jørgensen <redacted>
@@ -2645,14 +2645,27 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,*target_btf_idusingthelink_createAPI.**-iftgt_prog==NULLwhenthisfunctionwascalledusingtheold-*raw_tracepoint_openAPI,andweneedatargetfromprog->aux-*-*Thecombinationofnosavedtargetinprog->aux,andnotarget-*specifiedonloadisillegal,andwerejectthathere.+*raw_tracepoint_openAPI,andweneedatargetfromprog->aux+*+*Thecombinationofnosavedtargetinprog->aux,andnotarget+*specifiedonislegalonlyfortracingprogramsre-attach,rest+*isillegal,andwerejectthathere.*/if(!prog->aux->dst_trampoline&&!tgt_prog){-err=-ENOENT;-gotoout_unlock;+/*+*Allowre-attachfortracingprograms,ifit'scurrently+*linked,bpf_trampoline_link_progwillfail.+*/+if(prog->type!=BPF_PROG_TYPE_TRACING){+err=-ENOENT;+gotoout_unlock;+}+if(!prog->aux->attach_btf){+err=-EINVAL;+gotoout_unlock;+}
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
-Toke
On Sat, Apr 03, 2021 at 01:24:12PM +0200, Toke Høiland-Jørgensen wrote:
quoted
if (!prog->aux->dst_trampoline && !tgt_prog) {
- err = -ENOENT;
- goto out_unlock;
+ /*
+ * Allow re-attach for tracing programs, if it's currently
+ * linked, bpf_trampoline_link_prog will fail.
+ */
+ if (prog->type != BPF_PROG_TYPE_TRACING) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+ if (!prog->aux->attach_btf) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
The feature makes sense to me as well.
I don't quite see how it would get here with attach_btf == NULL.
Maybe WARN_ON then?
Also if we're allowing re-attach this way why exclude PROG_EXT and LSM?
From: Jiri Olsa <hidden> Date: 2021-04-05 14:06:50
On Sat, Apr 03, 2021 at 01:24:12PM +0200, Toke Høiland-Jørgensen wrote:
Jiri Olsa [off-list ref] writes:
quoted
Currently we don't allow re-attaching of trampolines. Once
it's detached, it can't be re-attach even when the program
is still loaded.
Adding the possibility to re-attach the loaded tracing
kernel program.
Hmm, yeah, didn't really consider this case when I added the original
disallow. But don't see why not, so (with one nit below):
Acked-by: Toke Høiland-Jørgensen <redacted>
@@ -2645,14 +2645,27 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,*target_btf_idusingthelink_createAPI.**-iftgt_prog==NULLwhenthisfunctionwascalledusingtheold-*raw_tracepoint_openAPI,andweneedatargetfromprog->aux-*-*Thecombinationofnosavedtargetinprog->aux,andnotarget-*specifiedonloadisillegal,andwerejectthathere.+*raw_tracepoint_openAPI,andweneedatargetfromprog->aux+*+*Thecombinationofnosavedtargetinprog->aux,andnotarget+*specifiedonislegalonlyfortracingprogramsre-attach,rest+*isillegal,andwerejectthathere.*/if(!prog->aux->dst_trampoline&&!tgt_prog){-err=-ENOENT;-gotoout_unlock;+/*+*Allowre-attachfortracingprograms,ifit'scurrently+*linked,bpf_trampoline_link_progwillfail.+*/+if(prog->type!=BPF_PROG_TYPE_TRACING){+err=-ENOENT;+gotoout_unlock;+}+if(!prog->aux->attach_btf){+err=-EINVAL;+gotoout_unlock;+}
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
right, that should be always there.. I'll remove it
thanks,
jirka
From: Jiri Olsa <hidden> Date: 2021-04-05 14:08:29
On Sat, Apr 03, 2021 at 11:21:55AM -0700, Alexei Starovoitov wrote:
On Sat, Apr 03, 2021 at 01:24:12PM +0200, Toke Høiland-Jørgensen wrote:
quoted
quoted
if (!prog->aux->dst_trampoline && !tgt_prog) {
- err = -ENOENT;
- goto out_unlock;
+ /*
+ * Allow re-attach for tracing programs, if it's currently
+ * linked, bpf_trampoline_link_prog will fail.
+ */
+ if (prog->type != BPF_PROG_TYPE_TRACING) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+ if (!prog->aux->attach_btf) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
The feature makes sense to me as well.
I don't quite see how it would get here with attach_btf == NULL.
Maybe WARN_ON then?
right, that should be always there
Also if we're allowing re-attach this way why exclude PROG_EXT and LSM?
I was enabling just what I needed for the test, which is so far
the only use case.. I'll see if I can enable that for all of them
jirka
On Sat, Apr 03, 2021 at 11:21:55AM -0700, Alexei Starovoitov wrote:
quoted
On Sat, Apr 03, 2021 at 01:24:12PM +0200, Toke Høiland-Jørgensen wrote:
quoted
quoted
if (!prog->aux->dst_trampoline && !tgt_prog) {
- err = -ENOENT;
- goto out_unlock;
+ /*
+ * Allow re-attach for tracing programs, if it's currently
+ * linked, bpf_trampoline_link_prog will fail.
+ */
+ if (prog->type != BPF_PROG_TYPE_TRACING) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+ if (!prog->aux->attach_btf) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
The feature makes sense to me as well.
I don't quite see how it would get here with attach_btf == NULL.
Maybe WARN_ON then?
right, that should be always there
quoted
Also if we're allowing re-attach this way why exclude PROG_EXT and LSM?
I was enabling just what I needed for the test, which is so far
the only use case.. I'll see if I can enable that for all of them
How would that work? For PROG_EXT we clear the destination on the first
attach (to avoid keeping a ref on it), so re-attach can only be done
with an explicit target (which already works just fine)...
-Toke
From: Jiri Olsa <hidden> Date: 2021-04-05 21:58:40
On Mon, Apr 05, 2021 at 04:15:54PM +0200, Toke Høiland-Jørgensen wrote:
Jiri Olsa [off-list ref] writes:
quoted
On Sat, Apr 03, 2021 at 11:21:55AM -0700, Alexei Starovoitov wrote:
quoted
On Sat, Apr 03, 2021 at 01:24:12PM +0200, Toke Høiland-Jørgensen wrote:
quoted
quoted
if (!prog->aux->dst_trampoline && !tgt_prog) {
- err = -ENOENT;
- goto out_unlock;
+ /*
+ * Allow re-attach for tracing programs, if it's currently
+ * linked, bpf_trampoline_link_prog will fail.
+ */
+ if (prog->type != BPF_PROG_TYPE_TRACING) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+ if (!prog->aux->attach_btf) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
I'm wondering about the two different return codes here. Under what
circumstances will aux->attach_btf be NULL, and why is that not an
ENOENT error? :)
The feature makes sense to me as well.
I don't quite see how it would get here with attach_btf == NULL.
Maybe WARN_ON then?
right, that should be always there
quoted
Also if we're allowing re-attach this way why exclude PROG_EXT and LSM?
I was enabling just what I needed for the test, which is so far
the only use case.. I'll see if I can enable that for all of them
How would that work? For PROG_EXT we clear the destination on the first
attach (to avoid keeping a ref on it), so re-attach can only be done
with an explicit target (which already works just fine)...
right, I'm just looking on it ;-) extensions already seem allow for that,
I'll check LSM
jirka