Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: nexthop: Add flag to assert that NHGRP reserved fields are zero

There are many unpatched kernel versions out there that do not initialize
the reserved fields of struct nexthop_grp. The issue with that is that if
those fields were to be used for some end (i.e. stop being reserved), old
kernels would still keep sending random data through the field, and a new
userspace could not rely on the value.

In this patch, use the existing NHA_OP_FLAGS, which is currently inbound
only, to carry flags back to the userspace. Add a flag to indicate that the
reserved fields in struct nexthop_grp are zeroed before dumping. This is
reliant on the actual fix from commit 6d745cd0e972 ("net: nexthop:
Initialize all fields in dumped nexthops").

Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/21037748d4f9d8ff486151f4c09083bcf12d5df8.1723036486.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Petr Machata and committed by
Jakub Kicinski
75bab45e 246ef406

+12 -3
+3
include/uapi/linux/nexthop.h
··· 33 33 #define NHA_OP_FLAG_DUMP_STATS BIT(0) 34 34 #define NHA_OP_FLAG_DUMP_HW_STATS BIT(1) 35 35 36 + /* Response OP_FLAGS. */ 37 + #define NHA_OP_FLAG_RESP_GRP_RESVD_0 BIT(31) /* Dump clears resvd fields. */ 38 + 36 39 enum { 37 40 NHA_UNSPEC, 38 41 NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */
+9 -3
net/ipv4/nexthop.c
··· 865 865 } 866 866 867 867 static int nla_put_nh_group(struct sk_buff *skb, struct nexthop *nh, 868 - u32 op_flags) 868 + u32 op_flags, u32 *resp_op_flags) 869 869 { 870 870 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); 871 871 struct nexthop_grp *p; ··· 873 873 struct nlattr *nla; 874 874 u16 group_type = 0; 875 875 int i; 876 + 877 + *resp_op_flags |= NHA_OP_FLAG_RESP_GRP_RESVD_0; 876 878 877 879 if (nhg->hash_threshold) 878 880 group_type = NEXTHOP_GRP_TYPE_MPATH; ··· 936 934 937 935 if (nh->is_group) { 938 936 struct nh_group *nhg = rtnl_dereference(nh->nh_grp); 937 + u32 resp_op_flags = 0; 939 938 940 939 if (nhg->fdb_nh && nla_put_flag(skb, NHA_FDB)) 941 940 goto nla_put_failure; 942 - if (nla_put_nh_group(skb, nh, op_flags)) 941 + if (nla_put_nh_group(skb, nh, op_flags, &resp_op_flags) || 942 + nla_put_u32(skb, NHA_OP_FLAGS, resp_op_flags)) 943 943 goto nla_put_failure; 944 944 goto out; 945 945 } ··· 1054 1050 sz += nla_total_size(4); /* NHA_ID */ 1055 1051 1056 1052 if (nh->is_group) 1057 - sz += nh_nlmsg_size_grp(nh); 1053 + sz += nh_nlmsg_size_grp(nh) + 1054 + nla_total_size(4) + /* NHA_OP_FLAGS */ 1055 + 0; 1058 1056 else 1059 1057 sz += nh_nlmsg_size_single(nh); 1060 1058