nexthop: More fine-grained policies for netlink message validation
Subsystems (3)
cover nexthop: More fine-grained policies for netlink message validation
From: Petr Machata <[email protected]>
There is currently one policy that covers all attributes for next hop object management. Actual validation is then done in code, which makes it unobvious which attributes are acceptable when, and indeed that everything is rejected as necessary.
In this series, split rtm_nh_policy to several policies that cover various aspects of the next hop object configuration, and instead of open-coding the validation, defer to nlmsg_parse(). This should make extending the next hop code simpler as well, which will be relevant in near future for resilient hashing implementation.
This was tested by running tools/testing/selftests/net/fib_nexthops.sh. Additionally iproute2 was tweaked to issue "nexthop list id" as an RTM_GETNEXTHOP dump request, instead of a straight get to test that unexpected attributes are indeed rejected.
In patch #1, convert attribute validation in nh_valid_get_del_req().
In patch #2, convert nh_valid_dump_req().
In patch #3, rtm_nh_policy is cleaned up and renamed to rtm_nh_policy_new, because after the above two patches, that is the only context that it is used in.
Petr Machata (3):
nexthop: Use a dedicated policy for nh_valid_get_del_req()
nexthop: Use a dedicated policy for nh_valid_dump_req()
nexthop: Specialize rtm_nh_policy
net/ipv4/nexthop.c | 85 +++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 53 deletions(-)
Signature · 1 line
2.26.2
PATCH 1/3 nexthop: Use a dedicated policy for nh_valid_get_del_req()
This function uses the global nexthop policy only to then bounce all arguments except for NHA_ID. Instead, just create a new policy that only includes the one allowed attribute.
--- net/ipv4/nexthop.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)
net/ipv4/nexthop.c +6 -15
@@ -36,6 +36,10 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, }; +static const struct nla_policy rtm_nh_policy_get[NHA_MAX +1 ] = { + [NHA_ID ] = { .type =NLA_U32 }, +}; +static bool nexthop_notifiers_is_empty (struct net *net) {return !net->nexthop.notifier_chain.head;
@@ -1843,27 +1847,14 @@ static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, {struct nhmsg *nhm =nlmsg_data (nlh);struct nlattr *tb[NHA_MAX +1 ]; -int err, i; +int err; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_get, extack);if (err <0 )return err; err = -EINVAL ; -for (i =0 ; i < __NHA_MAX; ++i) { -if (!tb[i]) -continue ; - -switch (i) { -case NHA_ID : -break ; -default : -NL_SET_ERR_MSG_ATTR (extack, tb[i], -"Unexpected attribute in request" ); - goto out; - } - }if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {NL_SET_ERR_MSG (extack,"Invalid values in header" ); goto out;
Signature · 1 line
2.26.2
Re: [PATCH net-next 1/3] nexthop: Use a dedicated policy for nh_valid_get_del_req()
Quoted 10 lines · Petr Machata
This function uses the global nexthop policy only to then bounce all arguments except for
NHA_ID. Instead, just create a new policy that only includes the one allowed attribute.Signed-off-by Petr Machata <[email protected]>Reviewed-by Ido Schimmel <[email protected]>--- net/ipv4/nexthop.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)
Jakub Kicinski
maintainerRe: [PATCH net-next 1/3] nexthop: Use a dedicated policy for nh_valid_get_del_req()
In reply to Petr MachataQuoted 15 lines · On Mon, 18 Jan 2021 15:05:23 +0100 Petr Machata wrote:
This function uses the global nexthop policy only to then bounce all arguments except for
NHA_ID. Instead, just create a new policy that only includes the one allowed attribute.Signed-off-by Petr Machata <[email protected]>Reviewed-by Ido Schimmel <[email protected]>--- net/ipv4/nexthop.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)net/ipv4/nexthop.c +0
-0
net/ipv4/nexthop.c static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { · line 39
Quoted 4 lines
net/ipv4/nexthop.c +1
-0@@ -36,6 +36,10 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, }; +static const struct nla_policy rtm_nh_policy_get[NHA_MAX +1 ] = {
This is an unnecessary waste of memory if you ask me.
NHA_ID is 1, so we're creating an array of 10 extra NULL elements.
Can you leave the size to the compiler and use ARRAY_SIZE() below?
Quoted 36 lines
net/ipv4/nexthop.c +5
-15+ [NHA_ID] = { .type = NLA_U32 }, +}; +static bool nexthop_notifiers_is_empty (struct net *net) {return !net->nexthop.notifier_chain.head;@@ -1843,27 +1847,14 @@ static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, {struct nhmsg *nhm =nlmsg_data (nlh);struct nlattr *tb[NHA_MAX +1 ]; -int err, i; +int err; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_get, extack);if (err <0 )return err; err = -EINVAL ; -for (i =0 ; i < __NHA_MAX; ++i) { -if (!tb[i]) -continue ; - -switch (i) { -case NHA_ID : -break ; -default : -NL_SET_ERR_MSG_ATTR (extack, tb[i], -"Unexpected attribute in request" ); - goto out; - } - }if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {NL_SET_ERR_MSG (extack,"Invalid values in header" ); goto out;
Re: [PATCH net-next 1/3] nexthop: Use a dedicated policy for nh_valid_get_del_req()
Quoted 8 lines · Jakub Kicinski
Quoted 8 lines
net/ipv4/nexthop.c +0
-0@@ -36,6 +36,10 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, };
Quoted 7 lines
net/ipv4/nexthop.c static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { · line 39
Quoted 1 line
net/ipv4/nexthop.c +1
-0+static const struct nla_policy rtm_nh_policy_get[NHA_MAX +1 ] = {This is an unnecessary waste of memory if you ask me.
NHA_IDis 1, so we're creating an array of 10 extra NULL elements.Can you leave the size to the compiler and use
ARRAY_SIZE()below?
interesting suggestion in general for netlink attributes.
Quoted 11 lines
net/ipv4/nexthop.c static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, · line 1849
Quoted 11 lines
net/ipv4/nexthop.c +3
-0+ [NHA_ID] = { .type = NLA_U32 }, +}; +static bool nexthop_notifiers_is_empty (struct net *net) {return !net->nexthop.notifier_chain.head;@@ -1843,27 +1847,14 @@ static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, {struct nhmsg *nhm =nlmsg_data (nlh);struct nlattr *tb[NHA_MAX +1 ];
This tb array too could be sized to just the highest indexed expected - NHA_ID in this case.
Quoted 27 lines
Quoted 26 lines
net/ipv4/nexthop.c +2
-15-int err, i; +int err; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_get, extack);if (err <0 )return err; err = -EINVAL ; -for (i =0 ; i < __NHA_MAX; ++i) { -if (!tb[i]) -continue ; - -switch (i) { -case NHA_ID : -break ; -default : -NL_SET_ERR_MSG_ATTR (extack, tb[i], -"Unexpected attribute in request" ); - goto out; - } - }if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {NL_SET_ERR_MSG (extack,"Invalid values in header" ); goto out;
Jakub Kicinski
maintainerRe: [PATCH net-next 1/3] nexthop: Use a dedicated policy for nh_valid_get_del_req()
Quoted 13 lines · On Tue, 19 Jan 2021 19:28:40 -0700 David Ahern wrote:
Quoted 12 lines · Jakub Kicinski
net/ipv4/nexthop.c static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { · line 39
Quoted 9 lines
net/ipv4/nexthop.c +1
-0@@ -36,6 +36,10 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, }; +static const struct nla_policy rtm_nh_policy_get[NHA_MAX +1 ] = {This is an unnecessary waste of memory if you ask me.
Quoted 5 lines
Quoted 3 lines
NHA_IDis 1, so we're creating an array of 10 extra NULL elements.Can you leave the size to the compiler and use
ARRAY_SIZE()below?interesting suggestion in general for netlink attributes.
According to tags on commit ff419afa4310 ("ethtool: trim policy tables") the credit goes to Johannes :)
Re: [PATCH net-next 1/3] nexthop: Use a dedicated policy for nh_valid_get_del_req()
In reply to David AhernQuoted 34 lines · David Ahern
Quoted 8 lines · Jakub Kicinski
Quoted 8 lines
net/ipv4/nexthop.c +0
-0@@ -36,6 +36,10 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, };Quoted 7 lines
net/ipv4/nexthop.c static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { · line 39
Quoted 1 line
net/ipv4/nexthop.c +1
-0+static const struct nla_policy rtm_nh_policy_get[NHA_MAX +1 ] = {This is an unnecessary waste of memory if you ask me.
NHA_IDis 1, so we're creating an array of 10 extra NULL elements.Can you leave the size to the compiler and use
ARRAY_SIZE()below?interesting suggestion in general for netlink attributes.
Quoted 11 lines
net/ipv4/nexthop.c static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, · line 1849
Quoted 11 lines
net/ipv4/nexthop.c +3
-0+ [NHA_ID] = { .type = NLA_U32 }, +}; +static bool nexthop_notifiers_is_empty (struct net *net) {return !net->nexthop.notifier_chain.head;@@ -1843,27 +1847,14 @@ static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, {struct nhmsg *nhm =nlmsg_data (nlh);struct nlattr *tb[NHA_MAX +1 ];This tb array too could be sized to just the highest indexed expected -
NHA_IDin this case.
Quoted 6 lines
Quoted 6 lines
net/ipv4/nexthop.c static int nh_valid_get_del_req(struct nlmsghdr *nlh, u32 *id, · line 1853
Quoted 6 lines
net/ipv4/nexthop.c +2
-2-int err, i; +int err; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_get, extack);
OK, I'll send a v2 that uses ARRAY_SIZE instead of hard-coding the max and size.
PATCH 2/3 nexthop: Use a dedicated policy for nh_valid_dump_req()
In reply to Petr MachataThis function uses the global nexthop policy, but only accepts four particular attributes. Create a new policy that only includes the four supported attributes, and use it. Convert the loop to a series of ifs.
--- net/ipv4/nexthop.c | 57 +++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 31 deletions(-)
net/ipv4/nexthop.c +26 -31
@@ -40,6 +40,13 @@ static const struct nla_policy rtm_nh_policy_get[NHA_MAX + 1] = { [NHA_ID] = { .type = NLA_U32 }, }; +static const struct nla_policy rtm_nh_policy_dump[NHA_MAX +1 ] = { + [NHA_OIF ] = { .type =NLA_U32 }, + [NHA_GROUPS ] = { .type =NLA_FLAG }, + [NHA_MASTER ] = { .type =NLA_U32 }, + [NHA_FDB ] = { .type =NLA_FLAG }, +}; +static bool nexthop_notifiers_is_empty (struct net *net) {return !net->nexthop.notifier_chain.head;
@@ -1984,46 +1991,34 @@ static int nh_valid_dump_req(const struct nlmsghdr *nlh, int *dev_idx,struct netlink_ext_ack *extack = cb->extack;struct nlattr *tb[NHA_MAX +1 ];struct nhmsg *nhm; -int err, i; +int err;u32 idx; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_dump,NULL );if (err <0 )return err; -for (i =0 ; i <=NHA_MAX ; ++i) { -if (!tb[i]) -continue ; - -switch (i) { -case NHA_OIF : - idx =nla_get_u32 (tb[i]); -if (idx >INT_MAX ) { -NL_SET_ERR_MSG (extack,"Invalid device index" ); -return -EINVAL ; - } - *dev_idx = idx; -break ; -case NHA_MASTER : - idx =nla_get_u32 (tb[i]); -if (idx >INT_MAX ) { -NL_SET_ERR_MSG (extack,"Invalid master device index" ); -return -EINVAL ; - } - *master_idx = idx; -break ; -case NHA_GROUPS : - *group_filter = true; -break ; -case NHA_FDB : - *fdb_filter = true; -break ; -default : -NL_SET_ERR_MSG (extack,"Unsupported attribute in dump request" ); +if (tb[NHA_OIF ]) { + idx =nla_get_u32 (tb[NHA_OIF ]); +if (idx >INT_MAX ) { +NL_SET_ERR_MSG (extack,"Invalid device index" ); +return -EINVAL ; + } + *dev_idx = idx; + } +if (tb[NHA_MASTER ]) { + idx =nla_get_u32 (tb[NHA_MASTER ]); +if (idx >INT_MAX ) { +NL_SET_ERR_MSG (extack,"Invalid master device index" );return -EINVAL ; } + *master_idx = idx; } +if (tb[NHA_GROUPS ]) + *group_filter = true; +if (tb[NHA_FDB ]) + *fdb_filter = true; nhm =nlmsg_data (nlh);if (nhm->nh_protocol || nhm->resvd || nhm->nh_scope || nhm->nh_flags) {
Signature · 1 line
2.26.2
Re: [PATCH net-next 2/3] nexthop: Use a dedicated policy for nh_valid_dump_req()
Quoted 10 lines · Petr Machata
This function uses the global nexthop policy, but only accepts four particular attributes. Create a new policy that only includes the four supported attributes, and use it. Convert the loop to a series of ifs.
Signed-off-by Petr Machata <[email protected]>Reviewed-by Ido Schimmel <[email protected]>--- net/ipv4/nexthop.c | 57 +++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 31 deletions(-)
Jakub Kicinski
maintainerRe: [PATCH net-next 2/3] nexthop: Use a dedicated policy for nh_valid_dump_req()
In reply to Petr Machatanet/ipv4/nexthop.c static int nh_valid_dump_req(const struct nlmsghdr *nlh, int *dev_idx, · line 2021
Quoted 4 lines · On Mon, 18 Jan 2021 15:05:24 +0100 Petr Machata wrote:
net/ipv4/nexthop.c +4
-0+if (tb[NHA_GROUPS ]) + *group_filter = true; +if (tb[NHA_FDB ]) + *fdb_filter = true;
nla_get_flag()
Re: [PATCH net-next 2/3] nexthop: Use a dedicated policy for nh_valid_dump_req()
Quoted 7 lines · Jakub Kicinski
net/ipv4/nexthop.c static int nh_valid_dump_req(const struct nlmsghdr *nlh, int *dev_idx, · line 2021
Quoted 4 lines · On Mon, 18 Jan 2021 15:05:24 +0100 Petr Machata wrote:
net/ipv4/nexthop.c +4
-0+if (tb[NHA_GROUPS ]) + *group_filter = true; +if (tb[NHA_FDB ]) + *fdb_filter = true;
nla_get_flag()
OK.
PATCH 3/3 nexthop: Specialize rtm_nh_policy
In reply to Petr MachataThis policy is currently only used for creation of new next hops and new next hop groups. Rename it accordingly and remove the two attributes that are not valid in that context: NHA_GROUPS and NHA_MASTER.
--- net/ipv4/nexthop.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
net/ipv4/nexthop.c +2 -9
@@ -22,7 +22,7 @@ static void remove_nexthop(struct net *net, struct nexthop *nh,#define NH_DEV_HASHBITS 8#define NH_DEV_HASHSIZE (1U << NH_DEV_HASHBITS) -static const struct nla_policy rtm_nh_policy[NHA_MAX +1 ] = { +static const struct nla_policy rtm_nh_policy_new[NHA_MAX +1 ] = { [NHA_ID ] = { .type =NLA_U32 }, [NHA_GROUP ] = { .type =NLA_BINARY }, [NHA_GROUP_TYPE ] = { .type =NLA_U16 },
@@ -31,8 +31,6 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_GATEWAY] = { .type = NLA_BINARY }, [NHA_ENCAP_TYPE] = { .type = NLA_U16 }, [NHA_ENCAP] = { .type = NLA_NESTED }, - [NHA_GROUPS] = { .type = NLA_FLAG }, - [NHA_MASTER] = { .type = NLA_U32 }, [NHA_FDB] = { .type = NLA_FLAG }, };
@@ -1657,7 +1655,7 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb,struct nlattr *tb[NHA_MAX +1 ];int err; - err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy, + err =nlmsg_parse (nlh,sizeof (*nhm), tb,NHA_MAX , rtm_nh_policy_new, extack);if (err <0 )return err;
@@ -1685,11 +1683,6 @@ static int rtm_to_nh_config(struct net *net, struct sk_buff *skb, goto out; } -if (tb[NHA_GROUPS ] || tb[NHA_MASTER ]) { -NL_SET_ERR_MSG (extack,"Invalid attributes in request" ); - goto out; - } -memset (cfg,0 ,sizeof (*cfg)); cfg->nlflags = nlh->nlmsg_flags; cfg->nlinfo.portid =NETLINK_CB (skb).portid;
Signature · 1 line
2.26.2
Re: [PATCH net-next 3/3] nexthop: Specialize rtm_nh_policy
Quoted 10 lines · Petr Machata
This policy is currently only used for creation of new next hops and new next hop groups. Rename it accordingly and remove the two attributes that are not valid in that context:
NHA_GROUPSandNHA_MASTER.Signed-off-by Petr Machata <[email protected]>Reviewed-by Ido Schimmel <[email protected]>--- net/ipv4/nexthop.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
Quoted 26 lines · Petr Machata
From: Petr Machata <[email protected]>
There is currently one policy that covers all attributes for next hop object management. Actual validation is then done in code, which makes it unobvious which attributes are acceptable when, and indeed that everything is rejected as necessary.
In this series, split
rtm_nh_policyto several policies that cover various aspects of the next hop object configuration, and instead of open-coding the validation, defer tonlmsg_parse(). This should make extending the next hop code simpler as well, which will be relevant in near future for resilient hashing implementation.This was tested by running
tools/testing/selftests/net/fib_nexthops.sh. Additionally iproute2 was tweaked to issue "nexthop list id" as anRTM_GETNEXTHOPdump request, instead of a straight get to test that unexpected attributes are indeed rejected.In patch #1, convert attribute validation in
nh_valid_get_del_req().In patch #2, convert
nh_valid_dump_req().In patch #3,
rtm_nh_policyis cleaned up and renamed tortm_nh_policy_new, because after the above two patches, that is the only context that it is used in.
Quoted 8 lines
Petr Machata (3):
nexthop: Use a dedicated policy fornh_valid_get_del_req()
nexthop: Use a dedicated policy fornh_valid_dump_req()
nexthop: Specializertm_nh_policynet/ipv4/nexthop.c | 85 +++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 53 deletions(-)
good cleanup. thanks for doing this. Did you run fib_nexthops.sh selftests on the change? Seems right, but always good to run that script which has functional tests about valid attribute combinations.
Quoted 32 lines · David Ahern
Quoted 31 lines · Petr Machata
From: Petr Machata <[email protected]>
There is currently one policy that covers all attributes for next hop object management. Actual validation is then done in code, which makes it unobvious which attributes are acceptable when, and indeed that everything is rejected as necessary.
In this series, split
rtm_nh_policyto several policies that cover various aspects of the next hop object configuration, and instead of open-coding the validation, defer tonlmsg_parse(). This should make extending the next hop code simpler as well, which will be relevant in near future for resilient hashing implementation.This was tested by running
tools/testing/selftests/net/fib_nexthops.sh. Additionally iproute2 was tweaked to issue "nexthop list id" as anRTM_GETNEXTHOPdump request, instead of a straight get to test that unexpected attributes are indeed rejected.In patch #1, convert attribute validation in
nh_valid_get_del_req().In patch #2, convert
nh_valid_dump_req().In patch #3,
rtm_nh_policyis cleaned up and renamed tortm_nh_policy_new, because after the above two patches, that is the only context that it is used in.Petr Machata (3):
nexthop: Use a dedicated policy fornh_valid_get_del_req()
nexthop: Use a dedicated policy fornh_valid_dump_req()
nexthop: Specializertm_nh_policy
Quoted 7 lines
Quoted 3 lines
net/ipv4/nexthop.c | 85 +++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 53 deletions(-)good cleanup. thanks for doing this. Did you run
fib_nexthops.shselftests on the change? Seems right, but always good to run that script which has functional tests about valid attribute combinations.
"This was tested by running tools/testing/selftests/net/fib_nexthops.sh" :)