summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/core/sock_map.c20
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_strp.c31
-rw-r--r--tools/testing/selftests/bpf/progs/sockmap_parse_prog.c22
-rw-r--r--tools/testing/selftests/bpf/progs/test_sockmap_strp.c7
4 files changed, 58 insertions, 22 deletions
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 99e3789492a0..c60ba6d292f9 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -1515,6 +1515,17 @@ static int sock_map_prog_link_lookup(struct bpf_map *map, struct bpf_prog ***ppr
return 0;
}
+static int sock_map_prog_attach_check(enum bpf_attach_type attach_type,
+ struct bpf_prog *prog)
+{
+ /* A stream parser must not modify the skb, only measure it. */
+ if (prog && attach_type == BPF_SK_SKB_STREAM_PARSER &&
+ prog->aux->changes_pkt_data)
+ return -EINVAL;
+
+ return 0;
+}
+
/* Handle the following four cases:
* prog_attach: prog != NULL, old == NULL, link == NULL
* prog_detach: prog == NULL, old != NULL, link == NULL
@@ -1533,6 +1544,10 @@ static int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
if (ret)
return ret;
+ ret = sock_map_prog_attach_check(which, prog);
+ if (ret)
+ return ret;
+
/* for prog_attach/prog_detach/link_attach, return error if a bpf_link
* exists for that prog.
*/
@@ -1776,6 +1791,11 @@ static int sock_map_link_update_prog(struct bpf_link *link,
ret = -EINVAL;
goto out;
}
+
+ ret = sock_map_prog_attach_check(link->attach_type, prog);
+ if (ret)
+ goto out;
+
if (!sockmap_link->map) {
ret = -ENOLINK;
goto out;
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
index 621b3b71888e..1d7231728eaf 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
@@ -431,6 +431,35 @@ out:
test_sockmap_strp__destroy(strp);
}
+static void test_sockmap_strp_parser_reject(void)
+{
+ struct test_sockmap_strp *strp = NULL;
+ int parser_mod, parser_ro, link;
+ int err, map;
+
+ strp = test_sockmap_strp__open_and_load();
+ if (!ASSERT_OK_PTR(strp, "test_sockmap_strp__open_and_load"))
+ return;
+
+ map = bpf_map__fd(strp->maps.sock_map);
+ parser_mod = bpf_program__fd(strp->progs.prog_skb_parser_resize);
+ parser_ro = bpf_program__fd(strp->progs.prog_skb_parser);
+
+ err = bpf_prog_attach(parser_mod, map, BPF_SK_SKB_STREAM_PARSER, 0);
+ ASSERT_ERR(err, "bpf_prog_attach parser_mod");
+
+ link = bpf_link_create(parser_ro, map, BPF_SK_SKB_STREAM_PARSER, NULL);
+ if (!ASSERT_GE(link, 0, "bpf_link_create parser_ro"))
+ goto out;
+
+ err = bpf_link_update(link, parser_mod, NULL);
+ ASSERT_ERR(err, "bpf_link_update parser_mod");
+out:
+ if (link >= 0)
+ close(link);
+ test_sockmap_strp__destroy(strp);
+}
+
void test_sockmap_strp(void)
{
if (test__start_subtest("sockmap strp tcp pass"))
@@ -451,4 +480,6 @@ void test_sockmap_strp(void)
test_sockmap_strp_multiple_pkt(AF_INET, SOCK_STREAM);
if (test__start_subtest("sockmap strp tcp dispatch"))
test_sockmap_strp_dispatch_pkt(AF_INET, SOCK_STREAM);
+ if (test__start_subtest("sockmap strp parser reject pkt mod"))
+ test_sockmap_strp_parser_reject();
}
diff --git a/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c b/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
index c9abfe3a11af..56e9aebf05f2 100644
--- a/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
+++ b/tools/testing/selftests/bpf/progs/sockmap_parse_prog.c
@@ -5,28 +5,6 @@
SEC("sk_skb1")
int bpf_prog1(struct __sk_buff *skb)
{
- void *data_end = (void *)(long) skb->data_end;
- void *data = (void *)(long) skb->data;
- __u8 *d = data;
- int err;
-
- if (data + 10 > data_end) {
- err = bpf_skb_pull_data(skb, 10);
- if (err)
- return SK_DROP;
-
- data_end = (void *)(long)skb->data_end;
- data = (void *)(long)skb->data;
- if (data + 10 > data_end)
- return SK_DROP;
- }
-
- /* This write/read is a bit pointless but tests the verifier and
- * strparser handler for read/write pkt data and access into sk
- * fields.
- */
- d = data;
- d[7] = 1;
return skb->len;
}
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
index dde3d5bec515..fe88fa6d40bc 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
@@ -50,4 +50,11 @@ int prog_skb_parser_partial(struct __sk_buff *skb)
return 10;
}
+SEC("sk_skb/stream_parser")
+int prog_skb_parser_resize(struct __sk_buff *skb)
+{
+ bpf_skb_change_tail(skb, skb->len, 0);
+ return skb->len;
+}
+
char _license[] SEC("license") = "GPL";