Re: GRE datagram socket support
David Gwynne wrote: > > On 22 Jan 2020, at 8:54 am, Damien Miller wrote: > > > > On Wed, 22 Jan 2020, David Gwynne wrote: > > > >>> Index: sys/kern/kern_pledge.c > >>> === > >>> RCS file: /cvs/src/sys/kern/kern_pledge.c,v > >>> retrieving revision 1.255 > >>> diff -u -p -r1.255 kern_pledge.c > >>> --- sys/kern/kern_pledge.c25 Aug 2019 18:46:40 - 1.255 > >>> +++ sys/kern/kern_pledge.c29 Oct 2019 07:57:58 - > >>> @@ -666,7 +666,7 @@ pledge_namei(struct proc *p, struct name > >>> } > >>> } > >>> > >>> - /* DNS needs /etc/{resolv.conf,hosts,services}. */ > >>> + /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ > >>> if ((ni->ni_pledge == PLEDGE_RPATH) && > >>> (p->p_p->ps_pledge & PLEDGE_DNS)) { > >>> if (strcmp(path, "/etc/resolv.conf") == 0) { > >>> @@ -678,6 +678,10 @@ pledge_namei(struct proc *p, struct name > >>> return (0); > >>> } > >>> if (strcmp(path, "/etc/services") == 0) { > >>> + ni->ni_cnd.cn_flags |= BYPASSUNVEIL; > >>> + return (0); > >>> + } > >>> + if (strcmp(path, "/etc/protocols") == 0) { > >>> ni->ni_cnd.cn_flags |= BYPASSUNVEIL; > >>> return (0); > > > > This looks like it is fixing a real, separate bug in pledge vs > > getaddrinfo, no? (specifically: that lookups for named ports will fail > > currently). > > no, our getaddrinfo currently hardcodes mapping of SOCK_STREAM, SOCK_DGRAM, > IPPROTO_TCP, and IPPROTO_UDP and maps them to "udp" and "tcp" for use when > looking up /etc/services via getservbyname_r. this is fine because they are > by far the most common case and worth optimising for. > > the problem is if (when) i want to use getnameinfo to look up entries for > IPPROTO_GRE. i either hardcode IPPROTO_GRE in getnameinfo guts to "gre" for > it to pass to getservbyname_r, or i look up /etc/protocols via > getprotobynumber_r to get a name. i opted for the latter. a number of people have expressed gaping-mouth horror that pledge knows about some userland paths. these specific paths are really part of what libc does. we could have hard-coded this info into libc and avoided the horror, but that approach would have other downsides. many programs hit libc interfaces which needed the /etc/services file because of getaddrinfo_async/getnameinfo which are highly desired interfaces. protocols hadn't hit this situation yet, but will now rise to the same level. i want to *minimize* the number of recognized paths, since there are two very subtle changes in behaviour. one other thing needs mentioning: this kind of translation won't work in a chroot.
Re: GRE datagram socket support
> On 22 Jan 2020, at 8:54 am, Damien Miller wrote: > > On Wed, 22 Jan 2020, David Gwynne wrote: > >>> Index: sys/kern/kern_pledge.c >>> === >>> RCS file: /cvs/src/sys/kern/kern_pledge.c,v >>> retrieving revision 1.255 >>> diff -u -p -r1.255 kern_pledge.c >>> --- sys/kern/kern_pledge.c 25 Aug 2019 18:46:40 - 1.255 >>> +++ sys/kern/kern_pledge.c 29 Oct 2019 07:57:58 - >>> @@ -666,7 +666,7 @@ pledge_namei(struct proc *p, struct name >>> } >>> } >>> >>> - /* DNS needs /etc/{resolv.conf,hosts,services}. */ >>> + /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ >>> if ((ni->ni_pledge == PLEDGE_RPATH) && >>> (p->p_p->ps_pledge & PLEDGE_DNS)) { >>> if (strcmp(path, "/etc/resolv.conf") == 0) { >>> @@ -678,6 +678,10 @@ pledge_namei(struct proc *p, struct name >>> return (0); >>> } >>> if (strcmp(path, "/etc/services") == 0) { >>> + ni->ni_cnd.cn_flags |= BYPASSUNVEIL; >>> + return (0); >>> + } >>> + if (strcmp(path, "/etc/protocols") == 0) { >>> ni->ni_cnd.cn_flags |= BYPASSUNVEIL; >>> return (0); > > This looks like it is fixing a real, separate bug in pledge vs > getaddrinfo, no? (specifically: that lookups for named ports will fail > currently). no, our getaddrinfo currently hardcodes mapping of SOCK_STREAM, SOCK_DGRAM, IPPROTO_TCP, and IPPROTO_UDP and maps them to "udp" and "tcp" for use when looking up /etc/services via getservbyname_r. this is fine because they are by far the most common case and worth optimising for. the problem is if (when) i want to use getnameinfo to look up entries for IPPROTO_GRE. i either hardcode IPPROTO_GRE in getnameinfo guts to "gre" for it to pass to getservbyname_r, or i look up /etc/protocols via getprotobynumber_r to get a name. i opted for the latter. dlg
Re: GRE datagram socket support
I am a big grumpy about /etc/protocols becoming another file that is bypassed (accepted transparently) in kernel pledge. but dlg has convinced me hardcoding would be worse.
Re: GRE datagram socket support
Hi, I think that is a good idea. On Wed, 22 Jan 2020 08:35:05 +1000 David Gwynne wrote: > Has anyone got an opinion on this? I am still interested in doing more > packet capture things on OpenBSD using GRE as a transport, and the idea > of maintaining this out of tree just makes me feel tired. > > On Tue, Oct 29, 2019 at 06:34:50PM +1000, David Gwynne wrote: >> i've been toying with this idea of implementing GRE as a datagram >> protocol that userland can use just like UDP. the idea is to make it >> easy to support the implementation of NHRP in userland for mgre(4), >> and also for ERSPAN* support without going down the path linux took**. >> >> so this is the result of having a go at implementing the idea. the diff >> includes several independent parts, but they all work together to make >> GRE as comfortable to use as UDP. the two main parts are the actual >> protocol implementation in src/sys/netinet/ip_gre.c, and the tweaks to >> getaddrinfo to allow the resolution of gre services. the /etc/services >> chunk gets used by the getaddrinfo bits. >> >> so, the first chunk lets you do this (as root in userland): >> >> int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_GRE); >> >> that gives you a file descriptor you can then use with bind(), >> connect(), sendto(), recvfrom(), etc. you write a message to the >> kernel and it prepends the GRE and IP headers and pushes it out. >> it is set up so the GRE protocol is handed to the kernel via the >> sin_port or sin6_port member of struct sockaddr_in an sockaddr_in6 >> respectively. there's no source and destination protocol fields, just >> one that both ends agree on, so if you connect then bind, your >> sockaddrs have to agree on the proto. unfortunately there's no such >> thing as a wildcard or reserved protocol in GRE, so 0 can't be used >> as a wildcard like it can in udp and tcp. >> >> the sockets support the configuration of optional GRE headers, as >> defined in RFC 2890, using setsockopt. importantly you can enable >> the key and sequence number headers, which again, the kernel offloads >> for you. >> >> the second chunk tweaks getaddrinfo so it lets you specify things other >> than IPPROTO_UDP and IPPROTO_TCP. protocols other than those are now >> looked up in /etc/protocols to get their name, which in turn is used to >> look up entries in /etc/services. while i was there and reading rfcs, i >> noted different behaviour for wildcarded socktypes and protocols, which >> i've tried to implement. eric@ seems generally ok with this stuff, and >> suggested the tweak to pledge to allow access to /etc/protocols using >> the dns pledge. tcp and udp are still special though, and are still >> omgoptimised. >> >> all this together lets the program at >> https://mild.embarrassm.net/~dlg/diff/egred.c work. it is a userland >> reimplementation of a simplified egre(4) using tap(4) and a gre socket. >> the io path is literally reading from one fd and writing it to the othe, >> everything else is boilerplate. >> >> i suspect the kernel stuff is a bit rough as i havent had to test every >> path, but it supports common functionality. >> >> thoughts? i am pretty pleased with this has turned out, and would be >> keen to put it in the tree and work on it some more. >> >> * https://tools.ietf.org/html/draft-foschiano-erspan-03 >> ** http://vger.kernel.org/lpc_net2018_talks/erspan-linux-presentation.pdf >> >> Index: etc/services >> === >> RCS file: /cvs/src/etc/services,v >> retrieving revision 1.96 >> diff -u -p -r1.96 services >> --- etc/services 27 Jan 2019 20:35:06 - 1.96 >> +++ etc/services 29 Oct 2019 07:57:44 - >> @@ -332,6 +332,21 @@ spamd-cfg 8026/tcp# >> spamd(8) configur >> dhcpd-sync 8067/udp# dhcpd(8) synchronisation >> hunt26740/udp # hunt(6) >> # >> +# GRE Protocol Types >> +# >> +keepalive 0/gre # 0x: IP tunnel keepalive >> +ipv42048/gre# 0x0800: IPv4 >> +nhrp8193/gre# 0x2001: Next Hop >> Resolution Protocol >> +erspan3 8939/gre# 0x22eb: ERSPAN III >> +transether 25944/gre ethernet# 0x6558: Trans Ether Bridging >> +ipv634525/gre # 0x86dd: IPv6 >> +wccp34878/gre # 0x883e: Web Content >> Cache Protocol >> +mpls34887/gre # 0x8847: MPLS >> +#mpls 34888/gre # 0x8848: MPLS Multicast >> +erspan 35006/gre erspan2 # 0x88be: ERSPAN I/II >> +nsh 35151/gre # 0x894f: Network Service Header >> +control 47082/gre # 0xb7ea: RFC 8157 >> +# >> # Appletalk >> # >> rtmp
Re: GRE datagram socket support
On Wed, 22 Jan 2020, David Gwynne wrote: > Has anyone got an opinion on this? I am still interested in doing more > packet capture things on OpenBSD using GRE as a transport, and the idea > of maintaining this out of tree just makes me feel tired. This is cool. I don't spot any major problems with this, but I'm rusty on kernel networking. > > Index: sys/kern/kern_pledge.c > > === > > RCS file: /cvs/src/sys/kern/kern_pledge.c,v > > retrieving revision 1.255 > > diff -u -p -r1.255 kern_pledge.c > > --- sys/kern/kern_pledge.c 25 Aug 2019 18:46:40 - 1.255 > > +++ sys/kern/kern_pledge.c 29 Oct 2019 07:57:58 - > > @@ -666,7 +666,7 @@ pledge_namei(struct proc *p, struct name > > } > > } > > > > - /* DNS needs /etc/{resolv.conf,hosts,services}. */ > > + /* DNS needs /etc/{resolv.conf,hosts,services,protocols}. */ > > if ((ni->ni_pledge == PLEDGE_RPATH) && > > (p->p_p->ps_pledge & PLEDGE_DNS)) { > > if (strcmp(path, "/etc/resolv.conf") == 0) { > > @@ -678,6 +678,10 @@ pledge_namei(struct proc *p, struct name > > return (0); > > } > > if (strcmp(path, "/etc/services") == 0) { > > + ni->ni_cnd.cn_flags |= BYPASSUNVEIL; > > + return (0); > > + } > > + if (strcmp(path, "/etc/protocols") == 0) { > > ni->ni_cnd.cn_flags |= BYPASSUNVEIL; > > return (0); This looks like it is fixing a real, separate bug in pledge vs getaddrinfo, no? (specifically: that lookups for named ports will fail currently).
Re: GRE datagram socket support
Has anyone got an opinion on this? I am still interested in doing more packet capture things on OpenBSD using GRE as a transport, and the idea of maintaining this out of tree just makes me feel tired. On Tue, Oct 29, 2019 at 06:34:50PM +1000, David Gwynne wrote: > i've been toying with this idea of implementing GRE as a datagram > protocol that userland can use just like UDP. the idea is to make it > easy to support the implementation of NHRP in userland for mgre(4), > and also for ERSPAN* support without going down the path linux took**. > > so this is the result of having a go at implementing the idea. the diff > includes several independent parts, but they all work together to make > GRE as comfortable to use as UDP. the two main parts are the actual > protocol implementation in src/sys/netinet/ip_gre.c, and the tweaks to > getaddrinfo to allow the resolution of gre services. the /etc/services > chunk gets used by the getaddrinfo bits. > > so, the first chunk lets you do this (as root in userland): > > int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_GRE); > > that gives you a file descriptor you can then use with bind(), > connect(), sendto(), recvfrom(), etc. you write a message to the > kernel and it prepends the GRE and IP headers and pushes it out. > it is set up so the GRE protocol is handed to the kernel via the > sin_port or sin6_port member of struct sockaddr_in an sockaddr_in6 > respectively. there's no source and destination protocol fields, just > one that both ends agree on, so if you connect then bind, your > sockaddrs have to agree on the proto. unfortunately there's no such > thing as a wildcard or reserved protocol in GRE, so 0 can't be used > as a wildcard like it can in udp and tcp. > > the sockets support the configuration of optional GRE headers, as > defined in RFC 2890, using setsockopt. importantly you can enable > the key and sequence number headers, which again, the kernel offloads > for you. > > the second chunk tweaks getaddrinfo so it lets you specify things other > than IPPROTO_UDP and IPPROTO_TCP. protocols other than those are now > looked up in /etc/protocols to get their name, which in turn is used to > look up entries in /etc/services. while i was there and reading rfcs, i > noted different behaviour for wildcarded socktypes and protocols, which > i've tried to implement. eric@ seems generally ok with this stuff, and > suggested the tweak to pledge to allow access to /etc/protocols using > the dns pledge. tcp and udp are still special though, and are still > omgoptimised. > > all this together lets the program at > https://mild.embarrassm.net/~dlg/diff/egred.c work. it is a userland > reimplementation of a simplified egre(4) using tap(4) and a gre socket. > the io path is literally reading from one fd and writing it to the othe, > everything else is boilerplate. > > i suspect the kernel stuff is a bit rough as i havent had to test every > path, but it supports common functionality. > > thoughts? i am pretty pleased with this has turned out, and would be > keen to put it in the tree and work on it some more. > > * https://tools.ietf.org/html/draft-foschiano-erspan-03 > ** http://vger.kernel.org/lpc_net2018_talks/erspan-linux-presentation.pdf > > Index: etc/services > === > RCS file: /cvs/src/etc/services,v > retrieving revision 1.96 > diff -u -p -r1.96 services > --- etc/services 27 Jan 2019 20:35:06 - 1.96 > +++ etc/services 29 Oct 2019 07:57:44 - > @@ -332,6 +332,21 @@ spamd-cfg8026/tcp# > spamd(8) configur > dhcpd-sync 8067/udp# dhcpd(8) synchronisation > hunt 26740/udp # hunt(6) > # > +# GRE Protocol Types > +# > +keepalive0/gre # 0x: IP tunnel keepalive > +ipv4 2048/gre# 0x0800: IPv4 > +nhrp 8193/gre# 0x2001: Next Hop Resolution > Protocol > +erspan3 8939/gre# 0x22eb: ERSPAN III > +transether 25944/gre ethernet# 0x6558: Trans Ether Bridging > +ipv6 34525/gre # 0x86dd: IPv6 > +wccp 34878/gre # 0x883e: Web Content Cache > Protocol > +mpls 34887/gre # 0x8847: MPLS > +#mpls34888/gre # 0x8848: MPLS Multicast > +erspan 35006/gre erspan2 # 0x88be: ERSPAN I/II > +nsh 35151/gre # 0x894f: Network Service Header > +control 47082/gre # 0xb7ea: RFC 8157 > +# > # Appletalk > # > rtmp 1/ddp # Routing Table Maintenance > Protocol > Index: lib/libc/asr/getaddrinfo_async.c > === > RCS file: