diff options
author | Alexei Starovoitov <ast@kernel.org> | 2019-01-04 23:23:33 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-01-04 23:23:34 -0500 |
commit | 466f89e9ec8c6868131c2d2ba9cd5f536879c42a (patch) | |
tree | 34278582594c9b6909bab6005a955521dc3d4ee1 | |
parent | ec90ad334986fa5856d11dd272f7f22fa86c55c4 (diff) | |
parent | 976b4f3a4646fbf0d189caca25f91f82e4be4b5a (diff) |
Merge branch 'udpv6_sendmsg-addr_any-fix'
Andrey Ignatov says:
====================
The patch set fixes BSD'ism in sys_sendmsg to rewrite unspecified
destination IPv6 for unconnected UDP sockets in sys_sendmsg with [::1] in
case when either CONFIG_CGROUP_BPF is enabled or when sys_sendmsg BPF hook
sets destination IPv6 to [::].
Patch 1 is the fix and provides more details.
Patch 2 adds two test cases to verify the fix.
v1->v2:
* Fix compile error in patch 1.
====================
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r-- | net/ipv6/udp.c | 8 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_sock_addr.c | 53 |
2 files changed, 54 insertions, 7 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9cbf363172bd..7c3505006f8e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1390,10 +1390,7 @@ do_udp_sendmsg: | |||
1390 | ipc6.opt = opt; | 1390 | ipc6.opt = opt; |
1391 | 1391 | ||
1392 | fl6.flowi6_proto = sk->sk_protocol; | 1392 | fl6.flowi6_proto = sk->sk_protocol; |
1393 | if (!ipv6_addr_any(daddr)) | 1393 | fl6.daddr = *daddr; |
1394 | fl6.daddr = *daddr; | ||
1395 | else | ||
1396 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
1397 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) | 1394 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
1398 | fl6.saddr = np->saddr; | 1395 | fl6.saddr = np->saddr; |
1399 | fl6.fl6_sport = inet->inet_sport; | 1396 | fl6.fl6_sport = inet->inet_sport; |
@@ -1421,6 +1418,9 @@ do_udp_sendmsg: | |||
1421 | } | 1418 | } |
1422 | } | 1419 | } |
1423 | 1420 | ||
1421 | if (ipv6_addr_any(&fl6.daddr)) | ||
1422 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
1423 | |||
1424 | final_p = fl6_update_dst(&fl6, opt, &final); | 1424 | final_p = fl6_update_dst(&fl6, opt, &final); |
1425 | if (final_p) | 1425 | if (final_p) |
1426 | connected = false; | 1426 | connected = false; |
diff --git a/tools/testing/selftests/bpf/test_sock_addr.c b/tools/testing/selftests/bpf/test_sock_addr.c index 73b7493d4120..d94336cbd8bd 100644 --- a/tools/testing/selftests/bpf/test_sock_addr.c +++ b/tools/testing/selftests/bpf/test_sock_addr.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define SERV6_V4MAPPED_IP "::ffff:192.168.0.4" | 44 | #define SERV6_V4MAPPED_IP "::ffff:192.168.0.4" |
45 | #define SRC6_IP "::1" | 45 | #define SRC6_IP "::1" |
46 | #define SRC6_REWRITE_IP "::6" | 46 | #define SRC6_REWRITE_IP "::6" |
47 | #define WILDCARD6_IP "::" | ||
47 | #define SERV6_PORT 6060 | 48 | #define SERV6_PORT 6060 |
48 | #define SERV6_REWRITE_PORT 6666 | 49 | #define SERV6_REWRITE_PORT 6666 |
49 | 50 | ||
@@ -85,12 +86,14 @@ static int bind4_prog_load(const struct sock_addr_test *test); | |||
85 | static int bind6_prog_load(const struct sock_addr_test *test); | 86 | static int bind6_prog_load(const struct sock_addr_test *test); |
86 | static int connect4_prog_load(const struct sock_addr_test *test); | 87 | static int connect4_prog_load(const struct sock_addr_test *test); |
87 | static int connect6_prog_load(const struct sock_addr_test *test); | 88 | static int connect6_prog_load(const struct sock_addr_test *test); |
89 | static int sendmsg_allow_prog_load(const struct sock_addr_test *test); | ||
88 | static int sendmsg_deny_prog_load(const struct sock_addr_test *test); | 90 | static int sendmsg_deny_prog_load(const struct sock_addr_test *test); |
89 | static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test); | 91 | static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test); |
90 | static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test); | 92 | static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test); |
91 | static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test); | 93 | static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test); |
92 | static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test); | 94 | static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test); |
93 | static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test); | 95 | static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test); |
96 | static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test); | ||
94 | 97 | ||
95 | static struct sock_addr_test tests[] = { | 98 | static struct sock_addr_test tests[] = { |
96 | /* bind */ | 99 | /* bind */ |
@@ -463,6 +466,34 @@ static struct sock_addr_test tests[] = { | |||
463 | SYSCALL_ENOTSUPP, | 466 | SYSCALL_ENOTSUPP, |
464 | }, | 467 | }, |
465 | { | 468 | { |
469 | "sendmsg6: set dst IP = [::] (BSD'ism)", | ||
470 | sendmsg6_rw_wildcard_prog_load, | ||
471 | BPF_CGROUP_UDP6_SENDMSG, | ||
472 | BPF_CGROUP_UDP6_SENDMSG, | ||
473 | AF_INET6, | ||
474 | SOCK_DGRAM, | ||
475 | SERV6_IP, | ||
476 | SERV6_PORT, | ||
477 | SERV6_REWRITE_IP, | ||
478 | SERV6_REWRITE_PORT, | ||
479 | SRC6_REWRITE_IP, | ||
480 | SUCCESS, | ||
481 | }, | ||
482 | { | ||
483 | "sendmsg6: preserve dst IP = [::] (BSD'ism)", | ||
484 | sendmsg_allow_prog_load, | ||
485 | BPF_CGROUP_UDP6_SENDMSG, | ||
486 | BPF_CGROUP_UDP6_SENDMSG, | ||
487 | AF_INET6, | ||
488 | SOCK_DGRAM, | ||
489 | WILDCARD6_IP, | ||
490 | SERV6_PORT, | ||
491 | SERV6_REWRITE_IP, | ||
492 | SERV6_PORT, | ||
493 | SRC6_IP, | ||
494 | SUCCESS, | ||
495 | }, | ||
496 | { | ||
466 | "sendmsg6: deny call", | 497 | "sendmsg6: deny call", |
467 | sendmsg_deny_prog_load, | 498 | sendmsg_deny_prog_load, |
468 | BPF_CGROUP_UDP6_SENDMSG, | 499 | BPF_CGROUP_UDP6_SENDMSG, |
@@ -734,16 +765,27 @@ static int connect6_prog_load(const struct sock_addr_test *test) | |||
734 | return load_path(test, CONNECT6_PROG_PATH); | 765 | return load_path(test, CONNECT6_PROG_PATH); |
735 | } | 766 | } |
736 | 767 | ||
737 | static int sendmsg_deny_prog_load(const struct sock_addr_test *test) | 768 | static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test, |
769 | int32_t rc) | ||
738 | { | 770 | { |
739 | struct bpf_insn insns[] = { | 771 | struct bpf_insn insns[] = { |
740 | /* return 0 */ | 772 | /* return rc */ |
741 | BPF_MOV64_IMM(BPF_REG_0, 0), | 773 | BPF_MOV64_IMM(BPF_REG_0, rc), |
742 | BPF_EXIT_INSN(), | 774 | BPF_EXIT_INSN(), |
743 | }; | 775 | }; |
744 | return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); | 776 | return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); |
745 | } | 777 | } |
746 | 778 | ||
779 | static int sendmsg_allow_prog_load(const struct sock_addr_test *test) | ||
780 | { | ||
781 | return sendmsg_ret_only_prog_load(test, /*rc*/ 1); | ||
782 | } | ||
783 | |||
784 | static int sendmsg_deny_prog_load(const struct sock_addr_test *test) | ||
785 | { | ||
786 | return sendmsg_ret_only_prog_load(test, /*rc*/ 0); | ||
787 | } | ||
788 | |||
747 | static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) | 789 | static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) |
748 | { | 790 | { |
749 | struct sockaddr_in dst4_rw_addr; | 791 | struct sockaddr_in dst4_rw_addr; |
@@ -864,6 +906,11 @@ static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test) | |||
864 | return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP); | 906 | return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP); |
865 | } | 907 | } |
866 | 908 | ||
909 | static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test) | ||
910 | { | ||
911 | return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP); | ||
912 | } | ||
913 | |||
867 | static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test) | 914 | static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test) |
868 | { | 915 | { |
869 | return load_path(test, SENDMSG6_PROG_PATH); | 916 | return load_path(test, SENDMSG6_PROG_PATH); |