netfilter: nfnetlink: Remove VLA usage
Subsystems (3)
PATCH v2 1/1 netfilter: nfnetlink: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this allocates the maximum size expected for all possible attrs and adds sanity-checks at both registration and usage to make sure nothing gets out of sync.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
---
v2: Use a static value and add a check in nfnetlink_subsys_register()
--- net/netfilter/nfnetlink.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
net/netfilter/nfnetlink.c +23 -2
@@ -37,6 +37,8 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);rcu_dereference_protected (table[(id)].subsys, \ lockdep_nfnl_is_held((id))) +#define NFNL_MAX_ATTR_COUNT 32 + static struct { struct mutex mutex; const struct nfnetlink_subsystem __rcu *subsys;
@@ -76,6 +78,13 @@ EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);int nfnetlink_subsys_register (const struct nfnetlink_subsystem *n) { +u8 cb_id; + +/* Sanity-check attr_count size to avoid stack buffer overflow. */ +for (cb_id =0 ; cb_id < n->cb_count; cb_id++) +if (WARN_ON (n->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT )) +return -EINVAL ; +nfnl_lock (n->subsys_id);if (table[n->subsys_id].subsys) {nfnl_unlock (n->subsys_id);
@@ -185,11 +194,17 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, {int min_len =nlmsg_total_size (sizeof (struct nfgenmsg ));u8 cb_id =NFNL_MSG_TYPE (nlh->nlmsg_type); -struct nlattr *cda[ss->cb[cb_id].attr_count +1 ]; +struct nlattr *cda[NFNL_MAX_ATTR_COUNT +1 ];struct nlattr *attr = (void *)nlh + min_len;int attrlen = nlh->nlmsg_len - min_len;__u8 subsys_id =NFNL_SUBSYS_ID (type); +/* Sanity-check NFNL_MAX_ATTR_COUNT */ +if (ss->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT ) { +rcu_read_unlock (); +return -ENOMEM ; + } + err =nla_parse (cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy, extack);if (err <0 ) {
@@ -379,10 +394,16 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, {int min_len =nlmsg_total_size (sizeof (struct nfgenmsg ));u8 cb_id =NFNL_MSG_TYPE (nlh->nlmsg_type); -struct nlattr *cda[ss->cb[cb_id].attr_count +1 ]; +struct nlattr *cda[NFNL_MAX_ATTR_COUNT +1 ];struct nlattr *attr = (void *)nlh + min_len;int attrlen = nlh->nlmsg_len - min_len; +/* Sanity-check NFTA_MAX_ATTR */ +if (ss->cb[cb_id].attr_count >NFNL_MAX_ATTR_COUNT ) { + err = -ENOMEM ; + goto ack; + } + err =nla_parse (cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy,NULL );if (err <0 )
Signature · 6 lines
2.17.0 -- Kees Cook Pixel Security
Quoted 6 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this allocates the maximum size expected for all possible attrs and adds sanity-checks at both registration and usage to make sure nothing gets out of sync.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Applied, thanks Kees.