rtnetlink: do_setlink: Use true struct sockaddr
Subsystems (2)
PATCH 1/1 rtnetlink: do_setlink: Use true struct sockaddr
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).
---
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(-)
net/core/rtnetlink.c +7 -15
@@ -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 ;
Signature · 1 line
2.34.1
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 18:04:45 -0800
Quoted 3 lines
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).
I remember Eric's feedback was to keep using heap instead of stack because rtnl_newlink() path already uses too much on stack.
Quoted 55 lines
Cap the copy to the minimum address size between
the incoming address and the traditionalsa_datafield 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(-)net/core/rtnetlink.c +7
-15@@ -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 ;Signature · 1 line
2.34.1
Quoted 8 lines · Kuniyuki Iwashima
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 18:04:45 -0800Quoted 3 lines
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).I remember Eric's feedback was to keep using heap instead of stack because
rtnl_newlink()path already uses too much on stack.
See below...
Quoted 8 lines
Quoted 8 lines
Cap the copy to the minimum address size between
the incoming address and the traditionalsa_datafield 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).
That's why I included the rationale above. (I.e. stack usage does not grow with this patch.)
-Kees
Quoted 50 lines
Quoted 49 lines
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(-)net/core/rtnetlink.c +7
-15@@ -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 ;Signature · 1 line
2.34.1
Signature · 1 line
Kees Cook
Quoted 5 lines · Kees Cook
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 traditionalsa_datafield itself.
Not sure what is a 'classic sockaddr'
Quoted 38 lines
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(-)net/core/rtnetlink.c +0
-12@@ -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]),
net/core/rtnetlink.c static int do_setlink(const struct sk_buff *skb, struct net_device *dev, · line 3057
Quoted 10 lines
net/core/rtnetlink.c +7
-3- 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);
Have you added debug checks in dev_set_mac_address_user() to make sure dev->addr_len is always smaller than 14 ?
I think we support devices with bigger addresses.
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 23:53:46 -0800
Quoted 14 lines · Kuniyuki Iwashima
Quoted 8 lines
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 18:04:45 -0800Quoted 3 lines
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).I remember Eric's feedback was to keep using heap instead of stack because
rtnl_newlink()path already uses too much on stack.See below...
Quoted 2 lines
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
Cap the copy to the minimum address size between
the incoming address and the traditionalsa_datafield 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).
That's why I included the rationale above. (I.e. stack usage does not grow with this patch.)
Ah okay, but I think we can't cap the address size to 14 bytes. MAX_ADDR_LEN is 32.
Also, dev_set_mac_address_user() still uses dev->addr_len.
Quoted 56 lines
-Kees
Quoted 50 lines
Quoted 49 lines
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(-)net/core/rtnetlink.c +7
-15@@ -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 ;Signature · 1 line
2.34.1Signature · 1 line
Kees Cook
Quoted 23 lines · Kuniyuki Iwashima
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 23:53:46 -0800Quoted 21 lines · Kuniyuki Iwashima
Quoted 8 lines
From: Kees Cook <[email protected]>
Date: Mon, 16 Dec 2024 18:04:45 -0800Quoted 3 lines
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).I remember Eric's feedback was to keep using heap instead of stack because
rtnl_newlink()path already uses too much on stack.See below...
Quoted 8 lines
Quoted 8 lines
Cap the copy to the minimum address size between
the incoming address and the traditionalsa_datafield 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).
Quoted 6 lines
Quoted 1 line
That's why I included the rationale above. (I.e. stack usage does not grow with this patch.)
Ah okay, but I think we can't cap the address size to 14 bytes.
MAX_ADDR_LENis 32.Also,
dev_set_mac_address_user()still usesdev->addr_len.
Oh, hrm, yes, that's true. I had audited callers of dev_set_mac_address(), but I think I must have missed callers of dev_set_mac_address_user(). Ugh. :( Let me take another look at this...
-Kees
Quoted 58 lines
Quoted 58 lines
-Kees
Quoted 50 lines
Quoted 49 lines
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(-)net/core/rtnetlink.c +7
-15@@ -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 ;Signature · 1 line
2.34.1Signature · 1 line
Kees Cook
Signature · 1 line
Kees Cook