mbox series

[v2,0/5] strict netlink validation

Message ID 20190426120731.9241-1-johannes@sipsolutions.net
Headers show
Series strict netlink validation | expand

Message

Johannes Berg April 26, 2019, 12:07 p.m. UTC
Here's a respin, with the following changes:
 * change message when rejecting unknown attribute types (David Ahern)
 * drop nl80211 patch - I'll apply it separately
 * remove NL_VALIDATE_POLICY - we have a lot of calls to nla_parse()
   that really should be without a policy as it has previously been
   validated - need to find a good way to handle this later
 * include the correct generic netlink change (d'oh, sorry)

johannes

Comments

David Ahern April 27, 2019, 2:28 a.m. UTC | #1
On 4/26/19 6:07 AM, Johannes Berg wrote:
> Here's a respin, with the following changes:
>  * change message when rejecting unknown attribute types (David Ahern)
>  * drop nl80211 patch - I'll apply it separately
>  * remove NL_VALIDATE_POLICY - we have a lot of calls to nla_parse()
>    that really should be without a policy as it has previously been
>    validated - need to find a good way to handle this later
>  * include the correct generic netlink change (d'oh, sorry)
> 
> johannes
> 
> 

I agree with this set and will help moving forward. As I recall it
requires follow up patches for each policy to set strict_start_type
opting in to the strict checking. With that in place new userspace on
old kernels will get a failure trying to configure a feature the old
kernel does not recognize.

For the series:
Acked-by: David Ahern <dsahern@gmail.com>
David Miller April 27, 2019, 9:07 p.m. UTC | #2
From: David Ahern <dsa@cumulusnetworks.com>
Date: Fri, 26 Apr 2019 20:28:20 -0600

> On 4/26/19 6:07 AM, Johannes Berg wrote:
>> Here's a respin, with the following changes:
>>  * change message when rejecting unknown attribute types (David Ahern)
>>  * drop nl80211 patch - I'll apply it separately
>>  * remove NL_VALIDATE_POLICY - we have a lot of calls to nla_parse()
>>    that really should be without a policy as it has previously been
>>    validated - need to find a good way to handle this later
>>  * include the correct generic netlink change (d'oh, sorry)
>> 
>> johannes
>> 
>> 
> 
> I agree with this set and will help moving forward. As I recall it
> requires follow up patches for each policy to set strict_start_type
> opting in to the strict checking. With that in place new userspace on
> old kernels will get a failure trying to configure a feature the old
> kernel does not recognize.
> 
> For the series:
> Acked-by: David Ahern <dsahern@gmail.com>

Series applied, thanks everyone.
Johannes Berg April 28, 2019, 7:32 p.m. UTC | #3
On Fri, 2019-04-26 at 20:28 -0600, David Ahern wrote:
> 
> I agree with this set and will help moving forward. As I recall it
> requires follow up patches for each policy to set strict_start_type
> opting in to the strict checking. With that in place new userspace on
> old kernels will get a failure trying to configure a feature the old
> kernel does not recognize.

Actually, that part you had already handled with nla_parse_strict() (now
nla_parse_strict_deprecated()) - and I'm not sure we can make this even
stricter because existing code might be setting future attributes
already, expecting them to be ignored. This is already fishy of
applications to expect though, but I'm not sure we really can change
that? I don't think I'm actually changing something here, but I'm
certainly open to suggestions - after all, when we actually do get
around to adding that future attribute it almost certainly will have a
different type than a (buggy) application would be using now.

However, what I did already do is that adding strict_start_type to
policies means that all future attributes added to those policies will
be handled in a strict fashion, i.e. if you add strict_start_type and
then add a new u32 attribute >= strict_start_type, that new u32
attribute will not be permitted to have a size other than 4 octets.

johannes
David Ahern April 28, 2019, 11:11 p.m. UTC | #4
On 4/28/19 1:32 PM, Johannes Berg wrote:
> On Fri, 2019-04-26 at 20:28 -0600, David Ahern wrote:
>>
>> I agree with this set and will help moving forward. As I recall it
>> requires follow up patches for each policy to set strict_start_type
>> opting in to the strict checking. With that in place new userspace on
>> old kernels will get a failure trying to configure a feature the old
>> kernel does not recognize.
> 
> Actually, that part you had already handled with nla_parse_strict() (now
> nla_parse_strict_deprecated()) - and I'm not sure we can make this even
> stricter because existing code might be setting future attributes
> already, expecting them to be ignored. This is already fishy of
> applications to expect though, but I'm not sure we really can change
> that? I don't think I'm actually changing something here, but I'm
> certainly open to suggestions - after all, when we actually do get
> around to adding that future attribute it almost certainly will have a
> different type than a (buggy) application would be using now.
> 
> However, what I did already do is that adding strict_start_type to
> policies means that all future attributes added to those policies will
> be handled in a strict fashion, i.e. if you add strict_start_type and
> then add a new u32 attribute >= strict_start_type, that new u32
> attribute will not be permitted to have a size other than 4 octets.
> 

For routes, an unknown attribute should cause the NEW/DEL command to
fail. There is a rare exception - something like RTA_PROTOCOL which is
just a passthrough, but in general the attribute is an important
modifier for the route.

With this change:

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index b298255f6fdb..7325c0265c5b 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -645,6 +645,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd,
struct rtentry *rt)
 }

 const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
+       [RTA_UNSPEC]            = { .strict_start_type = RTA_DPORT + 1 },
        [RTA_DST]               = { .type = NLA_U32 },
        [RTA_SRC]               = { .type = NLA_U32 },
        [RTA_IIF]               = { .type = NLA_U32 },
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b18e85cd7587..0760224927d2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4211,6 +4211,7 @@ void rt6_mtu_change(struct net_device *dev,
unsigned int mtu)
 }

 static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
+       [RTA_UNSPEC]            = { .strict_start_type = RTA_DPORT + 1 },
        [RTA_GATEWAY]           = { .len = sizeof(struct in6_addr) },
        [RTA_PREFSRC]           = { .len = sizeof(struct in6_addr) },
        [RTA_OIF]               = { .type = NLA_U32 },

I do get that behavior - a new command using a new attribute fails on an
older kernel.

And yes, exact length checking works though with extack we do not need
to spam dmesg:

[  475.175153] netlink: 'ip': attribute type 30 has an invalid length.