Message ID | 7646d8f6f0b7ba8206d2dc8625cbcb5bb33f9523.1546554049.git.rdna@fb.com |
---|---|
State | Changes Requested |
Delegated to: | BPF Maintainers |
Headers | show |
Series | bpf: Fix [::] -> [::1] rewrite in sys_sendmsg | expand |
Rawat, Nitin <nitin.rawat@intel.com> [Fri, 2019-01-04 00:35 -0800]: > Hi All, > Andrey,thanks for the fix . > I compiled the patch ½ provided by you , there was a compilation issue in your > patch in the below line . > > Original line : if (ipv6_addr_any(fl6.daddr)) > Expected line: if (ipv6_addr_any(&fl6.daddr)) > > I have made the above changes and test case was working fine for unconnected > test case . > Please let me know your view on that. Oops, I had this locally but missed it in the commit while baking the final patch somehow. Good catch, thanks! I'll send v2 with the fix. > There is also a another way to solve this way by putting the check just inside > the unconnected check , this will leave connected code path untouched > Hence I feel would be simpler > > @@ -1343,6 +1343,11 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, > size_t len) > fl6.fl6_dport = sin6->sin6_port; > fl6.daddr = sin6->sin6_addr; > } > + if (ipv6_addr_any(&fl6.daddr)) > + { > + fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback > (BSD'ism) */ > + } > + > } > > final_p = fl6_update_dst(&fl6, opt, &final); Yeah, it can be fixed like this but I intentionally didn't do it this way since it adds code duplication (copy/paste and checking ipv6_addr_any / setting [::1] twice). > I have tested second approach and it is working fine for unconnected case. > Please let us know your views on the above fix > > Regards, > Nitin > -----Original Message----- > From: Andrey Ignatov [mailto:rdna@fb.com] > Sent: Friday, January 4, 2019 4:13 AM > To: netdev@vger.kernel.org > Cc: Andrey Ignatov <rdna@fb.com>; ast@kernel.org; daniel@iogearbox.net; Rawat, > Nitin <nitin.rawat@intel.com>; kernel-team@fb.com > Subject: [PATCH bpf 1/2] bpf: Fix [::] -> [::1] rewrite in sys_sendmsg > > sys_sendmsg has supported unspecified destination IPv6 (wildcard) for > unconnected UDP sockets since 876c7f41. When [::] is passed by user as > destination, sys_sendmsg rewrites it with [::1] to be consistent with BSD (see > "BSD'ism" comment in the code). > > This didn't work when cgroup-bpf was enabled though since the rewrite [::] -> > [::1] happened before passing control to cgroup-bpf block where fl6.daddr was > updated with passed by user sockaddr_in6.sin6_addr (that might or might not be > changed by BPF program). That way if user passed [::] as dst IPv6 it was first > rewritten with [::1] by original code from 876c7f41, but then rewritten back > with [::] by cgroup-bpf block. > > It happened even when BPF_CGROUP_UDP6_SENDMSG program was not present > (CONFIG_CGROUP_BPF=y was enough). > > The fix is to apply BSD'ism after cgroup-bpf block so that [::] is replaced > with [::1] no matter where it came from: passed by user to sys_sendmsg or set > by BPF_CGROUP_UDP6_SENDMSG program. > > Fixes: 1cedee13d25a ("bpf: Hooks for sys_sendmsg") > Reported-by: Nitin Rawat <nitin.rawat@intel.com> > Signed-off-by: Andrey Ignatov <rdna@fb.com> > --- > net/ipv6/udp.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9cbf363172bd..cd563f985e1a > 100644 > --- a/net/ipv6/udp.c > +++ b/net/ipv6/udp.c > @@ -1390,10 +1390,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, > size_t len) > ipc6.opt = opt; > > fl6.flowi6_proto = sk->sk_protocol; > - if (!ipv6_addr_any(daddr)) > - fl6.daddr = *daddr; > - else > - fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ > + fl6.daddr = *daddr; > if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) > fl6.saddr = np->saddr; > fl6.fl6_sport = inet->inet_sport; > @@ -1421,6 +1418,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, > size_t len) > } > } > > + if (ipv6_addr_any(fl6.daddr)) > + fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ > + > final_p = fl6_update_dst(&fl6, opt, &final); > if (final_p) > connected = false; > -- > 2.17.1 > >
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9cbf363172bd..cd563f985e1a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1390,10 +1390,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) ipc6.opt = opt; fl6.flowi6_proto = sk->sk_protocol; - if (!ipv6_addr_any(daddr)) - fl6.daddr = *daddr; - else - fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ + fl6.daddr = *daddr; if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) fl6.saddr = np->saddr; fl6.fl6_sport = inet->inet_sport; @@ -1421,6 +1418,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) } } + if (ipv6_addr_any(fl6.daddr)) + fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ + final_p = fl6_update_dst(&fl6, opt, &final); if (final_p) connected = false;
sys_sendmsg has supported unspecified destination IPv6 (wildcard) for unconnected UDP sockets since 876c7f41. When [::] is passed by user as destination, sys_sendmsg rewrites it with [::1] to be consistent with BSD (see "BSD'ism" comment in the code). This didn't work when cgroup-bpf was enabled though since the rewrite [::] -> [::1] happened before passing control to cgroup-bpf block where fl6.daddr was updated with passed by user sockaddr_in6.sin6_addr (that might or might not be changed by BPF program). That way if user passed [::] as dst IPv6 it was first rewritten with [::1] by original code from 876c7f41, but then rewritten back with [::] by cgroup-bpf block. It happened even when BPF_CGROUP_UDP6_SENDMSG program was not present (CONFIG_CGROUP_BPF=y was enough). The fix is to apply BSD'ism after cgroup-bpf block so that [::] is replaced with [::1] no matter where it came from: passed by user to sys_sendmsg or set by BPF_CGROUP_UDP6_SENDMSG program. Fixes: 1cedee13d25a ("bpf: Hooks for sys_sendmsg") Reported-by: Nitin Rawat <nitin.rawat@intel.com> Signed-off-by: Andrey Ignatov <rdna@fb.com> --- net/ipv6/udp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)