diff mbox series

[net-next] tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function

Message ID 20240306095430.1782163-1-Ilia.Gavrilov@infotecs.ru (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net-next] tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 942 this patch: 942
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 957 this patch: 957
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: 958 this patch: 958
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 13 lines checked
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
netdev/contest success net-next-2024-03-06--21-00 (tests: 892)

Commit Message

Gavrilov Ilia March 6, 2024, 9:57 a.m. UTC
The 'len' variable can't be negative because all 'min_t' parameters
cast to unsigned int, and then the minimum one is chosen.

To fix it, move the if statement higher.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
---
 net/ipv4/tcp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Paolo Abeni March 6, 2024, 11:36 a.m. UTC | #1
On Wed, 2024-03-06 at 09:57 +0000, Gavrilov Ilia wrote:
> The 'len' variable can't be negative because all 'min_t' parameters
> cast to unsigned int, and then the minimum one is chosen.

The above is incorrect, as the 'len' variable is a signed integer 


The same applies to the following patches. 

Cheers,

Paolo
Gavrilov Ilia March 6, 2024, 11:54 a.m. UTC | #2
On 3/6/24 14:36, Paolo Abeni wrote:
> The above is incorrect, as the 'len' variable is a signed integer

I mean, if 'len' is negative then after this expression
len = min_t(unsigned int, len, sizeof(int));
the 'len' variable will be equal to sizeof(int) == 4
and the statement
if (len < 0) return -EINVAL;
might be unreachable during program execution.
Jason Xing March 6, 2024, 11:56 a.m. UTC | #3
Hello Paolo,

On Wed, Mar 6, 2024 at 7:36 PM Paolo Abeni <pabeni@redhat.com> wrote:
>
> On Wed, 2024-03-06 at 09:57 +0000, Gavrilov Ilia wrote:
> > The 'len' variable can't be negative because all 'min_t' parameters
> > cast to unsigned int, and then the minimum one is chosen.
>
> The above is incorrect, as the 'len' variable is a signed integer

The 'len' variable should be converted to the non-negative value as
this sentence:

len = min_t(unsigned int, len, sizeof(int));

See the comments of min_t(): return minimum of two values, using the
specified type.

After executing the above code, it doesn't make sense to test if 'len
< 0', I think.

Thanks,
Jason

>
>
> The same applies to the following patches.
>
> Cheers,
>
> Paolo
>
>
Eric Dumazet March 6, 2024, 2:55 p.m. UTC | #4
On Wed, Mar 6, 2024 at 12:57 PM Jason Xing <kerneljasonxing@gmail.com> wrote:
>
> Hello Paolo,
>
> On Wed, Mar 6, 2024 at 7:36 PM Paolo Abeni <pabeni@redhat.com> wrote:
> >
> > On Wed, 2024-03-06 at 09:57 +0000, Gavrilov Ilia wrote:
> > > The 'len' variable can't be negative because all 'min_t' parameters
> > > cast to unsigned int, and then the minimum one is chosen.
> >
> > The above is incorrect, as the 'len' variable is a signed integer
>
> The 'len' variable should be converted to the non-negative value as
> this sentence:
>
> len = min_t(unsigned int, len, sizeof(int));
>
> See the comments of min_t(): return minimum of two values, using the
> specified type.
>
> After executing the above code, it doesn't make sense to test if 'len
> < 0', I think.

This is essentially dead (defensive ?) code.

Most compilers optimize this completely, no big deal.
Simon Horman March 7, 2024, 8:40 a.m. UTC | #5
On Wed, Mar 06, 2024 at 11:54:40AM +0000, Gavrilov Ilia wrote:
> On 3/6/24 14:36, Paolo Abeni wrote:
> > The above is incorrect, as the 'len' variable is a signed integer
> 
> I mean, if 'len' is negative then after this expression
> len = min_t(unsigned int, len, sizeof(int));
> the 'len' variable will be equal to sizeof(int) == 4
> and the statement
> if (len < 0) return -EINVAL;
> might be unreachable during program execution.

Hi Gavrilov and Paolo,

I could be missing something obvious but it seems to me that this is correct.
Although perhaps we could try rewording the patch description to
make things a bit clearer. Here is my attempt at that:

   The 'len' variable can't be negative when assigned the result of
   'min_t' because all 'min_t' parameters are cast to unsigned int,
   and then the minimum one is chosen.

   To fix the logic, check 'len' as read from 'optlen',
   where the types of relevant variables are (signed) int.

FWIIW, I see four similar patches on netdev this morning.
It does seem to me that they are all valid fixes.
But if they need to be reposted, or there are more coming,
then I think it would be useful to bundle them up,
say into batches of 10, and send as patch-sets.

This may help with fragmentation of review of what seems
to be the same change in multiple places.
Gavrilov Ilia March 7, 2024, 2:17 p.m. UTC | #6
С уважением,
Илья Гаврилов
Ведущий программист
Отдел разработки
АО "ИнфоТеКС" в г. Санкт-Петербург
127287, г. Москва, Старый Петровско-Разумовский проезд, дом 1/23, стр. 1
T: +7 495 737-61-92 ( доб. 4921)
Ф: +7 495 737-72-78


Ilia.Gavrilov@infotecs.ru
www.infotecs.ru


On 3/7/24 11:40, Simon Horman wrote:
> On Wed, Mar 06, 2024 at 11:54:40AM +0000, Gavrilov Ilia wrote:
>> On 3/6/24 14:36, Paolo Abeni wrote:
>>> The above is incorrect, as the 'len' variable is a signed integer
>>
>> I mean, if 'len' is negative then after this expression
>> len = min_t(unsigned int, len, sizeof(int));
>> the 'len' variable will be equal to sizeof(int) == 4
>> and the statement
>> if (len < 0) return -EINVAL;
>> might be unreachable during program execution.
>
> Hi Gavrilov and Paolo,
>
> I could be missing something obvious but it seems to me that this is correct.
> Although perhaps we could try rewording the patch description to
> make things a bit clearer. Here is my attempt at that:
>
>     The 'len' variable can't be negative when assigned the result of
>     'min_t' because all 'min_t' parameters are cast to unsigned int,
>     and then the minimum one is chosen.
>
>     To fix the logic, check 'len' as read from 'optlen',
>     where the types of relevant variables are (signed) int.
>
> FWIIW, I see four similar patches on netdev this morning.
> It does seem to me that they are all valid fixes.
> But if they need to be reposted, or there are more coming,
> then I think it would be useful to bundle them up,
> say into batches of 10, and send as patch-sets.
>
> This may help with fragmentation of review of what seems
> to be the same change in multiple places.
>
>

Hi Simon, thank you for your answer.

I'll reword the patch description and repost a series of patches in V2.
I also found a couple of places with the same problem.
diff mbox series

Patch

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c82dc42f57c6..a4f418592314 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -4010,11 +4010,11 @@  int do_tcp_getsockopt(struct sock *sk, int level,
 	if (copy_from_sockptr(&len, optlen, sizeof(int)))
 		return -EFAULT;
 
-	len = min_t(unsigned int, len, sizeof(int));
-
 	if (len < 0)
 		return -EINVAL;
 
+	len = min_t(unsigned int, len, sizeof(int));
+
 	switch (optname) {
 	case TCP_MAXSEG:
 		val = tp->mss_cache;