Re: GRE datagram socket support

2020-01-21 Thread Theo de Raadt
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

2020-01-21 Thread David Gwynne



> 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

2020-01-21 Thread Theo de Raadt
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

2020-01-21 Thread YASUOKA Masahiko
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

2020-01-21 Thread Damien Miller
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

2020-01-21 Thread David Gwynne
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: