Date: Fri, 19 Feb 2021 17:11:31 +0100 From: "Kristof Provost" <kp@FreeBSD.org> To: "Alexander V. Chernikov" <melifaro@FreeBSD.org> Cc: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: Re: git: 2fe5a79425c7 - main - Fix dst/netmask handling in routing socket code. Message-ID: <471C6715-4F53-4DE7-9233-FC1EDEE49E2D@FreeBSD.org> In-Reply-To: <26E2BA35-291E-4DC5-BDCB-D98347D7E24C@FreeBSD.org> References: <202102162031.11GKV0T6060307@gitrepo.freebsd.org> <26E2BA35-291E-4DC5-BDCB-D98347D7E24C@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On 19 Feb 2021, at 16:24, Kristof Provost wrote: > On 16 Feb 2021, at 21:31, Alexander V. Chernikov wrote: >> The branch main has been updated by melifaro: >> >> URL: = >> https://cgit.FreeBSD.org/src/commit/?id=3D2fe5a79425c79f7b828acd91da66= d97230925fc8 >> >> commit 2fe5a79425c79f7b828acd91da66d97230925fc8 >> Author: Alexander V. Chernikov <melifaro@FreeBSD.org> >> AuthorDate: 2021-02-16 20:30:04 +0000 >> Commit: Alexander V. Chernikov <melifaro@FreeBSD.org> >> CommitDate: 2021-02-16 20:30:04 +0000 >> >> Fix dst/netmask handling in routing socket code. >> >> Traditionally routing socket code did almost zero checks on >> the input message except for the most basic size checks. >> >> This resulted in the unclear KPI boundary for the routing system = >> code >> (`rtrequest*` and now `rib_action()`) w.r.t message validness. >> >> Multiple potential problems and nuances exists: >> * Host bits in RTAX_DST sockaddr. Existing applications do send = >> prefixes >> with hostbits uncleared. Even `route(8)` does this, as they hope = >> the kernel >> would do the job of fixing it. Code inside `rib_action()` needs = >> to handle >> it on its own (see `rt_maskedcopy()` ugly hack). >> * There are multiple way of adding the host route: it can be DST = >> without >> netmask or DST with /32(/128) netmask. Also, RTF_HOST has to be = >> set correspondingly. >> Currently, these 2 options create 2 DIFFERENT routes in the = >> kernel. >> * no sockaddr length/content checking for the "secondary" fields = >> exists: nothing >> stops rtsock application to send sockaddr_in with length of 25 = >> (instead of 16). >> Kernel will accept it, install to RIB as is and propagate to all = >> rtsock consumers, >> potentially triggering bugs in their code. Same goes for = >> sin_port, sin_zero, etc. >> >> The goal of this change is to make rtsock verify all sockaddr and = >> prefix consistency. >> Said differently, `rib_action()` or internals should NOT require = >> to change any of the >> sockaddrs supplied by `rt_addrinfo` structure due to = >> incorrectness. >> >> To be more specific, this change implements the following: >> * sockaddr cleanup/validation check is added immediately after = >> getting sockaddrs from rtm. >> * Per-family dst/netmask checks clears host bits in dst and zeros = >> all dst/netmask "secondary" fields. >> * The same netmask checking code converts /32(/128) netmasks to = >> "host" route case >> (NULL netmask, RTF_HOST), removing the dualism. >> * Instead of allowing ANY "known" sockaddr families = >> (0<..<AF_MAX), allow only actually >> supported ones (inet, inet6, link). >> * Automatically convert `sockaddr_sdl` (AF_LINK) gateways to >> `sockaddr_sdl_short`. >> >> Reported by: Guy Yur <guyyur at gmail.com> >> Reviewed By: donner >> Differential Revision: https://reviews.freebsd.org/D28668 >> MFC after: 3 days >> --- >> sys/net/rtsock.c | 201 = >> +++++++++++++++++++++++++++++++++- >> tests/sys/net/routing/rtsock_common.h | 4 - >> 2 files changed, 195 insertions(+), 10 deletions(-) >> > >> +static int >> +cleanup_xaddrs_inet(struct rt_addrinfo *info) >> +{ >> + struct sockaddr_in *dst_sa, *mask_sa; >> + >> + /* Check & fixup dst/netmask combination first */ >> + dst_sa =3D (struct sockaddr_in *)info->rti_info[RTAX_DST]; >> + mask_sa =3D (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; >> + >> + struct in_addr mask =3D { >> + .s_addr =3D mask_sa ? mask_sa->sin_addr.s_addr : INADDR_BROADCAST, >> + }; >> + struct in_addr dst =3D { >> + .s_addr =3D htonl(ntohl(dst_sa->sin_addr.s_addr) & = >> ntohl(mask.s_addr)) >> + }; >> + > This breaks things like `arp -d 10.0.2.1`. It always masks off the = > network address, which is the right thing to do in the routing table, = > but not in the arp table. > > I=E2=80=99ve worked around it for now with this hack: > > diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c > index 3c1fea497af6..533076db99a5 100644 > --- a/sys/net/rtsock.c > +++ b/sys/net/rtsock.c > @@ -638,9 +638,12 @@ fill_addrinfo(struct rt_msghdr *rtm, int len, = > u_int fibnum, struct rt_addrinfo * > return (EINVAL); > > info->rti_flags =3D rtm->rtm_flags; > - error =3D cleanup_xaddrs(info); > - if (error !=3D 0) > - return (error); > + /* XXX HACK */ > + if (! (rtm->rtm_flags & RTF_LLDATA)) { > + error =3D cleanup_xaddrs(info); > + if (error !=3D 0) > + return (error); > + } > saf =3D info->rti_info[RTAX_DST]->sa_family; > /* > * Verify that the caller has the appropriate privilege; = > RTM_GET > > But I=E2=80=99m not totally happy with this, obviously. This may be a bit more reasonable: diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 3c1fea497af6..5147b92e95d5 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1393,6 +1393,10 @@ cleanup_xaddrs_inet(struct rt_addrinfo *info) .s_addr =3D htonl(ntohl(dst_sa->sin_addr.s_addr) & = ntohl(mask.s_addr)) }; + /* Keep the address if we're LL */ + if (info->rti_flags & RTF_LLDATA) + dst.s_addr =3D dst_sa->sin_addr.s_addr; + if (dst_sa->sin_len < sizeof(struct sockaddr_in)) { printf("dst sin_len too small\n"); return (EINVAL); @@ -1431,7 +1435,10 @@ cleanup_xaddrs_inet6(struct rt_addrinfo *info) mask_sa =3D (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK];= mask =3D mask_sa ? mask_sa->sin6_addr : in6mask128; - IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); + + /* Keep the address if we're LL */ + if (! (info->rti_flags & RTF_LLDATA)) + IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); if (dst_sa->sin6_len < sizeof(struct sockaddr_in6)) { printf("dst sin6_len too small\n"); Best regards, Kristof
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?471C6715-4F53-4DE7-9233-FC1EDEE49E2D>