With the introduction of the struct_ops program type, it became possible to
implement kernel functionality in BPF, making it viable to use BPF in place
of a regular kernel module for these particular operations.
Thus far, the only user of this mechanism is for implementing TCP
congestion control algorithms. These are clearly marked as GPL-only when
implemented as modules (as seen by the use of EXPORT_SYMBOL_GPL for
tcp_register_congestion_control()), so it seems like an oversight that this
was not carried over to BPF implementations. Since this is the only user
of the struct_ops mechanism, just enforcing GPL-only for the struct_ops
program type seems like the simplest way to fix this.
v2: Move check to the top of check_struct_ops_btf_id().
Fixes: 0baf26b0fcd7 ("bpf: tcp: Support tcp_congestion_ops in bpf")
Acked-by: Martin KaFai Lau <redacted>
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
kernel/bpf/verifier.c | 5 +++++
1 file changed, 5 insertions(+)
@@ -12158,6 +12158,11 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)u32btf_id,member_idx;constchar*mname;+if(!prog->gpl_compatible){+verbose(env,"struct ops programs must have a GPL compatible license\n");+return-EINVAL;+}+btf_id=prog->aux->attach_btf_id;st_ops=bpf_struct_ops_find(btf_id);if(!st_ops){
This adds a selftest to check that the verifier rejects a TCP CC struct_ops
with a non-GPL license.
v2:
- Use a minimal struct_ops BPF program instead of rewriting bpf_dctcp's
license in memory.
- Check for the verifier reject message instead of just the return code.
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++
.../selftests/bpf/progs/bpf_nogpltcp.c | 19 ++++++++
2 files changed, 63 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_nogpltcp.c
From: Martin KaFai Lau <hidden> Date: 2021-03-25 23:00:17
On Thu, Mar 25, 2021 at 10:11:22PM +0100, Toke Høiland-Jørgensen wrote:
quoted hunk
This adds a selftest to check that the verifier rejects a TCP CC struct_ops
with a non-GPL license.
v2:
- Use a minimal struct_ops BPF program instead of rewriting bpf_dctcp's
license in memory.
- Check for the verifier reject message instead of just the return code.
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++
.../selftests/bpf/progs/bpf_nogpltcp.c | 19 ++++++++
2 files changed, 63 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_nogpltcp.c
On Thu, Mar 25, 2021 at 2:11 PM Toke Høiland-Jørgensen [off-list ref] wrote:
quoted hunk
This adds a selftest to check that the verifier rejects a TCP CC struct_ops
with a non-GPL license.
v2:
- Use a minimal struct_ops BPF program instead of rewriting bpf_dctcp's
license in memory.
- Check for the verifier reject message instead of just the return code.
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++
.../selftests/bpf/progs/bpf_nogpltcp.c | 19 ++++++++
2 files changed, 63 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_nogpltcp.c
On Thu, Mar 25, 2021 at 2:11 PM Toke Høiland-Jørgensen [off-list ref] wrote:
quoted
This adds a selftest to check that the verifier rejects a TCP CC struct_ops
with a non-GPL license.
v2:
- Use a minimal struct_ops BPF program instead of rewriting bpf_dctcp's
license in memory.
- Check for the verifier reject message instead of just the return code.
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++
.../selftests/bpf/progs/bpf_nogpltcp.c | 19 ++++++++
2 files changed, 63 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_nogpltcp.c
ASSERT_EQ(found, true, "expected_err_msg");
I can never be sure which way CHECK() is checking
Ah, thanks! I always get confused about CHECK() as well! Maybe it should
be renamed to ASSERT()? But that would require flipping all the if()
statements around them as well :/
-Toke
-- Andrii
On Fri, Mar 26, 2021 at 2:43 AM Toke Høiland-Jørgensen [off-list ref] wrote:
Andrii Nakryiko [off-list ref] writes:
quoted
On Thu, Mar 25, 2021 at 2:11 PM Toke Høiland-Jørgensen [off-list ref] wrote:
quoted
This adds a selftest to check that the verifier rejects a TCP CC struct_ops
with a non-GPL license.
v2:
- Use a minimal struct_ops BPF program instead of rewriting bpf_dctcp's
license in memory.
- Check for the verifier reject message instead of just the return code.
Signed-off-by: Toke Høiland-Jørgensen <redacted>
---
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++
.../selftests/bpf/progs/bpf_nogpltcp.c | 19 ++++++++
2 files changed, 63 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_nogpltcp.c
ASSERT_EQ(found, true, "expected_err_msg");
I can never be sure which way CHECK() is checking
Ah, thanks! I always get confused about CHECK() as well! Maybe it should
be renamed to ASSERT()? But that would require flipping all the if()
statements around them as well :/
Exactly, it's the opposite of assert (ASSERT_NOT %-), that
CHECK(!found) is "assert not not found", right?) and it throws me off
every. single. time. Ideally we complete the set of ASSERT_XXX()
macros and convert as much as possible to that. We can also have just
generic ASSERT() for all other complicated cases.
Ah, thanks! I always get confused about CHECK() as well! Maybe it should
be renamed to ASSERT()? But that would require flipping all the if()
statements around them as well :/
Exactly, it's the opposite of assert (ASSERT_NOT %-), that
CHECK(!found) is "assert not not found", right?) and it throws me off
every. single. time.
Yup, me too, I have to basically infer the right meaning from the
surrounding if statements (i.e., whether it triggers an error path or
not).
Ideally we complete the set of ASSERT_XXX() macros and convert as much
as possible to that. We can also have just generic ASSERT() for all
other complicated cases.
Totally on board with that! I'll try to remember to fix any selftests I
fiddle with (and not introduce any new uses of CHECK() of course).
-Toke