* [PATCH net] net/rose: prevent integer overflows in rose_setsockopt()
@ 2025-01-15 16:42 Nikita Zhandarovich
2025-01-15 23:29 ` David Laight
2025-01-21 1:10 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 5+ messages in thread
From: Nikita Zhandarovich @ 2025-01-15 16:42 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Nikita Zhandarovich, Simon Horman, linux-hams, netdev,
linux-kernel, lvc-project, stable
In case of possible unpredictably large arguments passed to
rose_setsockopt() and multiplied by extra values on top of that,
integer overflows may occur.
Do the safest minimum and fix these issues by checking the
contents of 'opt' and returning -EINVAL if they are too large. Also,
switch to unsigned int and remove useless check for negative 'opt'
in ROSE_IDLE case.
Found by Linux Verification Center (linuxtesting.org) with static
analysis tool SVACE.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru>
---
net/rose/af_rose.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 59050caab65c..72c65d938a15 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -397,15 +397,15 @@ static int rose_setsockopt(struct socket *sock, int level, int optname,
{
struct sock *sk = sock->sk;
struct rose_sock *rose = rose_sk(sk);
- int opt;
+ unsigned int opt;
if (level != SOL_ROSE)
return -ENOPROTOOPT;
- if (optlen < sizeof(int))
+ if (optlen < sizeof(unsigned int))
return -EINVAL;
- if (copy_from_sockptr(&opt, optval, sizeof(int)))
+ if (copy_from_sockptr(&opt, optval, sizeof(unsigned int)))
return -EFAULT;
switch (optname) {
@@ -414,31 +414,31 @@ static int rose_setsockopt(struct socket *sock, int level, int optname,
return 0;
case ROSE_T1:
- if (opt < 1)
+ if (opt < 1 || opt > UINT_MAX / HZ)
return -EINVAL;
rose->t1 = opt * HZ;
return 0;
case ROSE_T2:
- if (opt < 1)
+ if (opt < 1 || opt > UINT_MAX / HZ)
return -EINVAL;
rose->t2 = opt * HZ;
return 0;
case ROSE_T3:
- if (opt < 1)
+ if (opt < 1 || opt > UINT_MAX / HZ)
return -EINVAL;
rose->t3 = opt * HZ;
return 0;
case ROSE_HOLDBACK:
- if (opt < 1)
+ if (opt < 1 || opt > UINT_MAX / HZ)
return -EINVAL;
rose->hb = opt * HZ;
return 0;
case ROSE_IDLE:
- if (opt < 0)
+ if (opt > UINT_MAX / (60 * HZ))
return -EINVAL;
rose->idle = opt * 60 * HZ;
return 0;
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() 2025-01-15 16:42 [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() Nikita Zhandarovich @ 2025-01-15 23:29 ` David Laight 2025-01-16 2:04 ` Su Hui 2025-01-21 1:10 ` patchwork-bot+netdevbpf 1 sibling, 1 reply; 5+ messages in thread From: David Laight @ 2025-01-15 23:29 UTC (permalink / raw) To: Nikita Zhandarovich Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, linux-hams, netdev, linux-kernel, lvc-project, stable On Wed, 15 Jan 2025 08:42:20 -0800 Nikita Zhandarovich <n.zhandarovich@fintech.ru> wrote: > In case of possible unpredictably large arguments passed to > rose_setsockopt() and multiplied by extra values on top of that, > integer overflows may occur. > > Do the safest minimum and fix these issues by checking the > contents of 'opt' and returning -EINVAL if they are too large. Also, > switch to unsigned int and remove useless check for negative 'opt' > in ROSE_IDLE case. > > Found by Linux Verification Center (linuxtesting.org) with static > analysis tool SVACE. > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Cc: stable@vger.kernel.org > Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru> > --- > net/rose/af_rose.c | 16 ++++++++-------- > 1 file changed, 8 insertions(+), 8 deletions(-) > > diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c > index 59050caab65c..72c65d938a15 100644 > --- a/net/rose/af_rose.c > +++ b/net/rose/af_rose.c > @@ -397,15 +397,15 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, > { > struct sock *sk = sock->sk; > struct rose_sock *rose = rose_sk(sk); > - int opt; > + unsigned int opt; > > if (level != SOL_ROSE) > return -ENOPROTOOPT; > > - if (optlen < sizeof(int)) > + if (optlen < sizeof(unsigned int)) > return -EINVAL; > > - if (copy_from_sockptr(&opt, optval, sizeof(int))) > + if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) Shouldn't all those be 'sizeof (opt)' ? David > return -EFAULT; > > switch (optname) { > @@ -414,31 +414,31 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, > return 0; > > case ROSE_T1: > - if (opt < 1) > + if (opt < 1 || opt > UINT_MAX / HZ) > return -EINVAL; > rose->t1 = opt * HZ; > return 0; > > case ROSE_T2: > - if (opt < 1) > + if (opt < 1 || opt > UINT_MAX / HZ) > return -EINVAL; > rose->t2 = opt * HZ; > return 0; > > case ROSE_T3: > - if (opt < 1) > + if (opt < 1 || opt > UINT_MAX / HZ) > return -EINVAL; > rose->t3 = opt * HZ; > return 0; > > case ROSE_HOLDBACK: > - if (opt < 1) > + if (opt < 1 || opt > UINT_MAX / HZ) > return -EINVAL; > rose->hb = opt * HZ; > return 0; > > case ROSE_IDLE: > - if (opt < 0) > + if (opt > UINT_MAX / (60 * HZ)) > return -EINVAL; > rose->idle = opt * 60 * HZ; > return 0; > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() 2025-01-15 23:29 ` David Laight @ 2025-01-16 2:04 ` Su Hui 2025-01-16 12:37 ` Nikita Zhandarovich 0 siblings, 1 reply; 5+ messages in thread From: Su Hui @ 2025-01-16 2:04 UTC (permalink / raw) To: David Laight, Nikita Zhandarovich Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, linux-hams, netdev, linux-kernel, lvc-project, stable, kernel-janitors On 2025/1/16 07:29, David Laight wrote: > On Wed, 15 Jan 2025 08:42:20 -0800 > Nikita Zhandarovich <n.zhandarovich@fintech.ru> wrote: > >> In case of possible unpredictably large arguments passed to >> rose_setsockopt() and multiplied by extra values on top of that, >> integer overflows may occur. >> >> Do the safest minimum and fix these issues by checking the >> contents of 'opt' and returning -EINVAL if they are too large. Also, >> switch to unsigned int and remove useless check for negative 'opt' >> in ROSE_IDLE case. >> >> Found by Linux Verification Center (linuxtesting.org) with static >> analysis tool SVACE. >> >> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") >> Cc: stable@vger.kernel.org >> Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru> >> --- >> net/rose/af_rose.c | 16 ++++++++-------- >> 1 file changed, 8 insertions(+), 8 deletions(-) >> >> diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c >> index 59050caab65c..72c65d938a15 100644 >> --- a/net/rose/af_rose.c >> +++ b/net/rose/af_rose.c >> @@ -397,15 +397,15 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, >> { >> struct sock *sk = sock->sk; >> struct rose_sock *rose = rose_sk(sk); >> - int opt; >> + unsigned int opt; >> >> if (level != SOL_ROSE) >> return -ENOPROTOOPT; >> >> - if (optlen < sizeof(int)) >> + if (optlen < sizeof(unsigned int)) >> return -EINVAL; >> >> - if (copy_from_sockptr(&opt, optval, sizeof(int))) >> + if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) > Shouldn't all those be 'sizeof (opt)' ? > > David > >> return -EFAULT; >> >> switch (optname) { >> @@ -414,31 +414,31 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, >> return 0; >> >> case ROSE_T1: >> - if (opt < 1) >> + if (opt < 1 || opt > UINT_MAX / HZ) 'rose->t1' is unsigned long, how about 'opt > ULONG_MAX / HZ' ? BTW, I think only in 32bit or 16bit machine when 'sizeof(int) == sizeof(unsigned long)', this integer overflows may occur.. Su Hui >> return -EINVAL; >> rose->t1 = opt * HZ; >> return 0; >> >> case ROSE_T2: >> - if (opt < 1) >> + if (opt < 1 || opt > UINT_MAX / HZ) >> return -EINVAL; >> rose->t2 = opt * HZ; >> return 0; >> >> case ROSE_T3: >> - if (opt < 1) >> + if (opt < 1 || opt > UINT_MAX / HZ) >> return -EINVAL; >> rose->t3 = opt * HZ; >> return 0; >> >> case ROSE_HOLDBACK: >> - if (opt < 1) >> + if (opt < 1 || opt > UINT_MAX / HZ) >> return -EINVAL; >> rose->hb = opt * HZ; >> return 0; >> >> case ROSE_IDLE: >> - if (opt < 0) >> + if (opt > UINT_MAX / (60 * HZ)) >> return -EINVAL; >> rose->idle = opt * 60 * HZ; >> return 0; >> ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() 2025-01-16 2:04 ` Su Hui @ 2025-01-16 12:37 ` Nikita Zhandarovich 0 siblings, 0 replies; 5+ messages in thread From: Nikita Zhandarovich @ 2025-01-16 12:37 UTC (permalink / raw) To: Su Hui, David Laight Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, linux-hams, netdev, linux-kernel, lvc-project, stable, kernel-janitors Hello, On 1/15/25 18:04, Su Hui wrote: > On 2025/1/16 07:29, David Laight wrote: >> On Wed, 15 Jan 2025 08:42:20 -0800 >> Nikita Zhandarovich <n.zhandarovich@fintech.ru> wrote: >> >>> In case of possible unpredictably large arguments passed to >>> rose_setsockopt() and multiplied by extra values on top of that, >>> integer overflows may occur. >>> >>> Do the safest minimum and fix these issues by checking the >>> contents of 'opt' and returning -EINVAL if they are too large. Also, >>> switch to unsigned int and remove useless check for negative 'opt' >>> in ROSE_IDLE case. >>> >>> Found by Linux Verification Center (linuxtesting.org) with static >>> analysis tool SVACE. >>> >>> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") >>> Cc: stable@vger.kernel.org >>> Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru> >>> --- >>> net/rose/af_rose.c | 16 ++++++++-------- >>> 1 file changed, 8 insertions(+), 8 deletions(-) >>> >>> diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c >>> index 59050caab65c..72c65d938a15 100644 >>> --- a/net/rose/af_rose.c >>> +++ b/net/rose/af_rose.c >>> @@ -397,15 +397,15 @@ static int rose_setsockopt(struct socket *sock, >>> int level, int optname, >>> { >>> struct sock *sk = sock->sk; >>> struct rose_sock *rose = rose_sk(sk); >>> - int opt; >>> + unsigned int opt; >>> if (level != SOL_ROSE) >>> return -ENOPROTOOPT; >>> - if (optlen < sizeof(int)) >>> + if (optlen < sizeof(unsigned int)) >>> return -EINVAL; >>> - if (copy_from_sockptr(&opt, optval, sizeof(int))) >>> + if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) >> Shouldn't all those be 'sizeof (opt)' ? >> >> David >> Agreed, but my thinking was to keep it somewhat symmetrical to other similar checks in XXX_setsockopt(). For instance, in net/ax25/af_ax25.c, courtesy of commit 7b75c5a8c41 ("net: pass a sockptr_t into ->setsockopt") an explicit type is used. I don't mind sending v2, as it would be a bit neater. >>> return -EFAULT; >>> switch (optname) { >>> @@ -414,31 +414,31 @@ static int rose_setsockopt(struct socket *sock, >>> int level, int optname, >>> return 0; >>> case ROSE_T1: >>> - if (opt < 1) >>> + if (opt < 1 || opt > UINT_MAX / HZ) > > 'rose->t1' is unsigned long, how about 'opt > ULONG_MAX / HZ' ? > > BTW, I think only in 32bit or 16bit machine when 'sizeof(int) == > sizeof(unsigned long)', > this integer overflows may occur.. > > Su Hui > Here I was influenced by commits dc35616e6c29 ("netrom: fix api breakage in nr_setsockopt()") and 9371937092d5 ("ax25: uninitialized variable in ax25_setsockopt()") that essentially state that we only copy 4 bytes from userspace so opt being ulong is not desired. Even if the result of * HZ ends up stored in ulong 'XXX->t1'. I may be wrong but I think same principle applies to rose_setsockopt(). All we need to do here is to enable a sanity check that there is no int/uint overflow in right hand expression before the result gets stored in ulong. >>> return -EINVAL; >>> rose->t1 = opt * HZ; >>> return 0; >>> case ROSE_T2: >>> - if (opt < 1) >>> + if (opt < 1 || opt > UINT_MAX / HZ) >>> return -EINVAL; >>> rose->t2 = opt * HZ; >>> return 0; >>> case ROSE_T3: >>> - if (opt < 1) >>> + if (opt < 1 || opt > UINT_MAX / HZ) >>> return -EINVAL; >>> rose->t3 = opt * HZ; >>> return 0; >>> case ROSE_HOLDBACK: >>> - if (opt < 1) >>> + if (opt < 1 || opt > UINT_MAX / HZ) >>> return -EINVAL; >>> rose->hb = opt * HZ; >>> return 0; >>> case ROSE_IDLE: >>> - if (opt < 0) >>> + if (opt > UINT_MAX / (60 * HZ)) >>> return -EINVAL; >>> rose->idle = opt * 60 * HZ; >>> return 0; >>> Regards, Nikita ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() 2025-01-15 16:42 [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() Nikita Zhandarovich 2025-01-15 23:29 ` David Laight @ 2025-01-21 1:10 ` patchwork-bot+netdevbpf 1 sibling, 0 replies; 5+ messages in thread From: patchwork-bot+netdevbpf @ 2025-01-21 1:10 UTC (permalink / raw) To: Nikita Zhandarovich Cc: davem, edumazet, kuba, pabeni, horms, linux-hams, netdev, linux-kernel, lvc-project, stable Hello: This patch was applied to netdev/net.git (main) by Jakub Kicinski <kuba@kernel.org>: On Wed, 15 Jan 2025 08:42:20 -0800 you wrote: > In case of possible unpredictably large arguments passed to > rose_setsockopt() and multiplied by extra values on top of that, > integer overflows may occur. > > Do the safest minimum and fix these issues by checking the > contents of 'opt' and returning -EINVAL if they are too large. Also, > switch to unsigned int and remove useless check for negative 'opt' > in ROSE_IDLE case. > > [...] Here is the summary with links: - [net] net/rose: prevent integer overflows in rose_setsockopt() https://git.kernel.org/netdev/net/c/d640627663bf You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-01-21 1:10 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-01-15 16:42 [PATCH net] net/rose: prevent integer overflows in rose_setsockopt() Nikita Zhandarovich 2025-01-15 23:29 ` David Laight 2025-01-16 2:04 ` Su Hui 2025-01-16 12:37 ` Nikita Zhandarovich 2025-01-21 1:10 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).