Instead of a heap allocation use a stack allocated struct sockaddr, as dev_set_mac_address_user() is the consumer (which uses a classic struct sockaddr). Cap the copy to the minimum address size between the incoming address and the traditional sa_data field itself.
Putting "sa" on the stack means it will get a reused stack slot since it is smaller than other existing single-scope stack variables (like the vfinfo array). Signed-off-by: Kees Cook <[email protected]> --- Cc: Eric Dumazet <[email protected]> Cc: "David S. Miller" <[email protected]> Cc: Jakub Kicinski <[email protected]> Cc: Paolo Abeni <[email protected]> Cc: Ido Schimmel <[email protected]> Cc: Petr Machata <[email protected]> Cc: [email protected] --- net/core/rtnetlink.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ab5f201bf0ab..6da0edc0870d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3048,21 +3048,13 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev, } if (tb[IFLA_ADDRESS]) { - struct sockaddr *sa; - int len; - - len = sizeof(sa_family_t) + max_t(size_t, dev->addr_len, - sizeof(*sa)); - sa = kmalloc(len, GFP_KERNEL); - if (!sa) { - err = -ENOMEM; - goto errout; - } - sa->sa_family = dev->type; - memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), - dev->addr_len); - err = dev_set_mac_address_user(dev, sa, extack); - kfree(sa); + struct sockaddr sa = { }; + + /* dev_set_mac_address_user() uses a true struct sockaddr. */ + sa.sa_family = dev->type; + memcpy(sa.sa_data, nla_data(tb[IFLA_ADDRESS]), + min(dev->addr_len, sizeof(sa.sa_data_min))); + err = dev_set_mac_address_user(dev, &sa, extack); if (err) goto errout; status |= DO_SETLINK_MODIFIED; -- 2.34.1
