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.

Reply via email to