Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: harden sockmap program attach to ensure correct map type

When attaching a program to sockmap we need to check map type
is correct.

Fixes: 174a79ff9515 ("bpf: sockmap with sk redirect support")
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

John Fastabend and committed by
David S. Miller
81374aaa ed85054d

+33 -4
+3
kernel/bpf/sockmap.c
··· 794 794 struct bpf_stab *stab = container_of(map, struct bpf_stab, map); 795 795 struct bpf_prog *orig; 796 796 797 + if (unlikely(map->map_type != BPF_MAP_TYPE_SOCKMAP)) 798 + return -EINVAL; 799 + 797 800 switch (type) { 798 801 case BPF_SK_SKB_STREAM_PARSER: 799 802 orig = xchg(&stab->bpf_parse, prog);
+7
tools/testing/selftests/bpf/sockmap_verdict_prog.c
··· 26 26 .max_entries = 20, 27 27 }; 28 28 29 + struct bpf_map_def SEC("maps") sock_map_break = { 30 + .type = BPF_MAP_TYPE_ARRAY, 31 + .key_size = sizeof(int), 32 + .value_size = sizeof(int), 33 + .max_entries = 20, 34 + }; 35 + 29 36 SEC("sk_skb2") 30 37 int bpf_prog2(struct __sk_buff *skb) 31 38 {
+23 -4
tools/testing/selftests/bpf/test_maps.c
··· 463 463 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 464 464 static void test_sockmap(int task, void *data) 465 465 { 466 + int one = 1, map_fd_rx, map_fd_tx, map_fd_break, s, sc, rc; 467 + struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break; 466 468 int ports[] = {50200, 50201, 50202, 50204}; 467 469 int err, i, fd, sfd[6] = {0xdeadbeef}; 468 470 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 469 - int one = 1, map_fd_rx, map_fd_tx, s, sc, rc; 470 471 int parse_prog, verdict_prog; 471 - struct bpf_map *bpf_map_rx, *bpf_map_tx; 472 472 struct sockaddr_in addr; 473 473 struct bpf_object *obj; 474 474 struct timeval to; ··· 609 609 goto out_sockmap; 610 610 } 611 611 612 + bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 613 + if (IS_ERR(bpf_map_break)) { 614 + printf("Failed to load map tx from verdict prog\n"); 615 + goto out_sockmap; 616 + } 617 + 618 + map_fd_break = bpf_map__fd(bpf_map_break); 619 + if (map_fd_break < 0) { 620 + printf("Failed to get map tx fd\n"); 621 + goto out_sockmap; 622 + } 623 + 624 + err = bpf_prog_attach(parse_prog, map_fd_break, 625 + BPF_SK_SKB_STREAM_PARSER, 0); 626 + if (!err) { 627 + printf("Allowed attaching SK_SKB program to invalid map\n"); 628 + goto out_sockmap; 629 + } 630 + 612 631 err = bpf_prog_attach(parse_prog, map_fd_rx, 613 632 BPF_SK_SKB_STREAM_PARSER, 0); 614 633 if (err) { 615 - printf("Failed bpf prog attach\n"); 634 + printf("Failed stream parser bpf prog attach\n"); 616 635 goto out_sockmap; 617 636 } 618 637 619 638 err = bpf_prog_attach(verdict_prog, map_fd_rx, 620 639 BPF_SK_SKB_STREAM_VERDICT, 0); 621 640 if (err) { 622 - printf("Failed bpf prog attach\n"); 641 + printf("Failed stream verdict bpf prog attach\n"); 623 642 goto out_sockmap; 624 643 } 625 644