diff mbox series

[net] net: Fix undefined behavior in netdev name allocation

Message ID 20231113083544.1685919-1-gal@nvidia.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] net: Fix undefined behavior in netdev name allocation | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1142 this patch: 1142
netdev/cc_maintainers fail 1 blamed authors not CCed: jiri@resnulli.us; 4 maintainers not CCed: daniel@iogearbox.net edumazet@google.com pabeni@redhat.com jiri@resnulli.us
netdev/build_clang success Errors and warnings before: 1162 this patch: 1162
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1169 this patch: 1169
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Gal Pressman Nov. 13, 2023, 8:35 a.m. UTC
Cited commit removed the strscpy() call and kept the snprintf() only.

When allocating a netdev, 'res' and 'name' pointers are equal, but
according to POSIX, if copying takes place between objects that overlap
as a result of a call to sprintf() or snprintf(), the results are
undefined.

Add back the strscpy() and use 'buf' as an intermediate buffer.

Fixes: 9a810468126c ("net: reduce indentation of __dev_alloc_name()")
Cc: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
---
 net/core/dev.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Simon Horman Nov. 13, 2023, 9:53 a.m. UTC | #1
On Mon, Nov 13, 2023 at 10:35:44AM +0200, Gal Pressman wrote:
> Cited commit removed the strscpy() call and kept the snprintf() only.
> 
> When allocating a netdev, 'res' and 'name' pointers are equal, but
> according to POSIX, if copying takes place between objects that overlap
> as a result of a call to sprintf() or snprintf(), the results are
> undefined.
> 
> Add back the strscpy() and use 'buf' as an intermediate buffer.
> 
> Fixes: 9a810468126c ("net: reduce indentation of __dev_alloc_name()")

Hi Gal,

perhaps my eyes are deceiving me, but I wonder if this fixes the following:

  7ad17b04dc7b ("net: trust the bitmap in __dev_alloc_name()")

> Cc: Jakub Kicinski <kuba@kernel.org>
> Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
> Signed-off-by: Gal Pressman <gal@nvidia.com>
> ---
>  net/core/dev.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 0d548431f3fa..af53f6d838ce 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -1119,7 +1119,9 @@ static int __dev_alloc_name(struct net *net, const char *name, char *res)
>  	if (i == max_netdevices)
>  		return -ENFILE;
>  
> -	snprintf(res, IFNAMSIZ, name, i);
> +	/* 'res' and 'name' could overlap, use 'buf' as an intermediate buffer */
> +	strscpy(buf, name, IFNAMSIZ);
> +	snprintf(res, IFNAMSIZ, buf, i);
>  	return i;
>  }
>  
> -- 
> 2.40.1
> 
>
Gal Pressman Nov. 13, 2023, 2:01 p.m. UTC | #2
On 13/11/2023 11:53, Simon Horman wrote:
> On Mon, Nov 13, 2023 at 10:35:44AM +0200, Gal Pressman wrote:
>> Cited commit removed the strscpy() call and kept the snprintf() only.
>>
>> When allocating a netdev, 'res' and 'name' pointers are equal, but
>> according to POSIX, if copying takes place between objects that overlap
>> as a result of a call to sprintf() or snprintf(), the results are
>> undefined.
>>
>> Add back the strscpy() and use 'buf' as an intermediate buffer.
>>
>> Fixes: 9a810468126c ("net: reduce indentation of __dev_alloc_name()")
> 
> Hi Gal,
> 
> perhaps my eyes are deceiving me, but I wonder if this fixes the following:
> 
>   7ad17b04dc7b ("net: trust the bitmap in __dev_alloc_name()")

Thanks Simon, you're right.

Should I resubmit?
Jakub Kicinski Nov. 14, 2023, 4:09 a.m. UTC | #3
On Mon, 13 Nov 2023 10:35:44 +0200 Gal Pressman wrote:
> Cited commit removed the strscpy() call and kept the snprintf() only.
> 
> When allocating a netdev, 'res' and 'name' pointers are equal, but
> according to POSIX, if copying takes place between objects that overlap
> as a result of a call to sprintf() or snprintf(), the results are
> undefined.
> 
> Add back the strscpy() and use 'buf' as an intermediate buffer.

It may be worth mentioning that it is fairly common to put the format
in dev->name before device is registered, IOW this condition takes
place a lot? IIUC once we cross into 3-digit IDs we may crash?

With that and the right fixes tag:

Reviewed-by: Jakub Kicinski <kuba@kernel.org>

Thanks!
Jakub Kicinski Nov. 14, 2023, 4:12 a.m. UTC | #4
On Mon, 13 Nov 2023 23:09:02 -0500 Jakub Kicinski wrote:
>  IIUC once we cross into 3-digit IDs we may crash?

Not really crash I guess just repeat some numbers until the end of
the buffer.
Gal Pressman Nov. 14, 2023, 7:26 a.m. UTC | #5
On 14/11/2023 6:09, Jakub Kicinski wrote:
> On Mon, 13 Nov 2023 10:35:44 +0200 Gal Pressman wrote:
>> Cited commit removed the strscpy() call and kept the snprintf() only.
>>
>> When allocating a netdev, 'res' and 'name' pointers are equal, but
>> according to POSIX, if copying takes place between objects that overlap
>> as a result of a call to sprintf() or snprintf(), the results are
>> undefined.
>>
>> Add back the strscpy() and use 'buf' as an intermediate buffer.
> 
> It may be worth mentioning that it is fairly common to put the format
> in dev->name before device is registered, IOW this condition takes
> place a lot?

I'll mention it.

> IIUC once we cross into 3-digit IDs we may crash?

Right, the bitmap and names get out of sync, it results in sysfs name
collision call traces.

> 
> With that and the right fixes tag:
> 
> Reviewed-by: Jakub Kicinski <kuba@kernel.org>
> 
> Thanks!

Thanks Jakub!
Simon Horman Nov. 15, 2023, 9:28 a.m. UTC | #6
On Mon, Nov 13, 2023 at 04:01:23PM +0200, Gal Pressman wrote:
> On 13/11/2023 11:53, Simon Horman wrote:
> > On Mon, Nov 13, 2023 at 10:35:44AM +0200, Gal Pressman wrote:
> >> Cited commit removed the strscpy() call and kept the snprintf() only.
> >>
> >> When allocating a netdev, 'res' and 'name' pointers are equal, but
> >> according to POSIX, if copying takes place between objects that overlap
> >> as a result of a call to sprintf() or snprintf(), the results are
> >> undefined.
> >>
> >> Add back the strscpy() and use 'buf' as an intermediate buffer.
> >>
> >> Fixes: 9a810468126c ("net: reduce indentation of __dev_alloc_name()")
> > 
> > Hi Gal,
> > 
> > perhaps my eyes are deceiving me, but I wonder if this fixes the following:
> > 
> >   7ad17b04dc7b ("net: trust the bitmap in __dev_alloc_name()")
> 
> Thanks Simon, you're right.
> 
> Should I resubmit?

I guess that it is not strictly necessary,
but it might be a good idea as I imagine it makes things
slightly easier for the maintainers.

In any case, thanks for confirming and with this changed (somehow)
this patch looks good to me.

Reviewed-by: Simon Horman <horms@kernel.org>
diff mbox series

Patch

diff --git a/net/core/dev.c b/net/core/dev.c
index 0d548431f3fa..af53f6d838ce 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1119,7 +1119,9 @@  static int __dev_alloc_name(struct net *net, const char *name, char *res)
 	if (i == max_netdevices)
 		return -ENFILE;
 
-	snprintf(res, IFNAMSIZ, name, i);
+	/* 'res' and 'name' could overlap, use 'buf' as an intermediate buffer */
+	strscpy(buf, name, IFNAMSIZ);
+	snprintf(res, IFNAMSIZ, buf, i);
 	return i;
 }