All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tcp: use kmalloc() than kmalloc_array().
@ 2015-11-07 15:50 Tetsuo Handa
  2015-11-07 15:58 ` Tetsuo Handa
  2015-11-07 18:50 ` Eric Dumazet
  0 siblings, 2 replies; 6+ messages in thread
From: Tetsuo Handa @ 2015-11-07 15:50 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, Tetsuo Handa

Commit 095dc8e0c3686d58 ("tcp: fix/cleanup inet_ehash_locks_alloc()")
silently changed from kmalloc() to kmalloc_array(). The latter has
overflow check whereas the former doesn't have.

If nblocks * locksz might overflow, we need to do like

  -  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
  +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
       hashinfo->ehash_locks = vmalloc(nblocks * locksz);

because kmalloc_array() detects overflow and returns NULL.
But if nblocks * locksz is guaranteed not to overflow, there is
no need to use kmalloc_array().

Since I assume it won't overflow, use kmalloc() than kmalloc_array().

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 net/ipv4/inet_hashtables.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ccc5980..8f4ab27 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -648,8 +648,8 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
 		/* no more locks than number of hash buckets */
 		nblocks = min(nblocks, hashinfo->ehash_mask + 1);
 
-		hashinfo->ehash_locks =	kmalloc_array(nblocks, locksz,
-						      GFP_KERNEL | __GFP_NOWARN);
+		hashinfo->ehash_locks =	kmalloc(nblocks * locksz,
+						GFP_KERNEL | __GFP_NOWARN);
 		if (!hashinfo->ehash_locks)
 			hashinfo->ehash_locks = vmalloc(nblocks * locksz);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] tcp: use kmalloc() than kmalloc_array().
  2015-11-07 15:50 [PATCH] tcp: use kmalloc() than kmalloc_array() Tetsuo Handa
@ 2015-11-07 15:58 ` Tetsuo Handa
  2015-11-07 18:02   ` David Miller
  2015-11-07 18:50 ` Eric Dumazet
  1 sibling, 1 reply; 6+ messages in thread
From: Tetsuo Handa @ 2015-11-07 15:58 UTC (permalink / raw)
  To: edumazet; +Cc: netdev

Tetsuo Handa wrote:
> Commit 095dc8e0c3686d58 ("tcp: fix/cleanup inet_ehash_locks_alloc()")
> silently changed from kmalloc() to kmalloc_array(). The latter has
> overflow check whereas the former doesn't have.
> 
> If nblocks * locksz might overflow, we need to do like
> 
>   -  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
>   +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)

Oops, I meant

   -  if (!hashinfo->ehash_locks)
   +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)

here.

>        hashinfo->ehash_locks = vmalloc(nblocks * locksz);
> 
> because kmalloc_array() detects overflow and returns NULL.
> But if nblocks * locksz is guaranteed not to overflow, there is
> no need to use kmalloc_array().
> 
> Since I assume it won't overflow, use kmalloc() than kmalloc_array().

I don't know about possible value range.
Please confirm that it can't overflow.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] tcp: use kmalloc() than kmalloc_array().
  2015-11-07 15:58 ` Tetsuo Handa
@ 2015-11-07 18:02   ` David Miller
  0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2015-11-07 18:02 UTC (permalink / raw)
  To: penguin-kernel; +Cc: edumazet, netdev

From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Sun, 8 Nov 2015 00:58:50 +0900

> Tetsuo Handa wrote:
>> Commit 095dc8e0c3686d58 ("tcp: fix/cleanup inet_ehash_locks_alloc()")
>> silently changed from kmalloc() to kmalloc_array(). The latter has
>> overflow check whereas the former doesn't have.
>> 
>> If nblocks * locksz might overflow, we need to do like
>> 
>>   -  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
>>   +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
> 
> Oops, I meant
> 
>    -  if (!hashinfo->ehash_locks)
>    +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
> 
> here.
> 
>>        hashinfo->ehash_locks = vmalloc(nblocks * locksz);
>> 
>> because kmalloc_array() detects overflow and returns NULL.
>> But if nblocks * locksz is guaranteed not to overflow, there is
>> no need to use kmalloc_array().
>> 
>> Since I assume it won't overflow, use kmalloc() than kmalloc_array().
> 
> I don't know about possible value range.
> Please confirm that it can't overflow.

Whether it can overflow or not, I don't like your change at all.

If kmalloc_array() provides overflow protection, we want to keep using
it, rather than reverting back to not checking for overflow.

kmalloc_array() can fail for us at this stage for two reasons, either:

1) overflow

2) allocation size exceeds kmalloc() maximum alloc size

so if you want to be completely perfect about all of this you need
to add code to distinguish between these two cases as you suggest
above.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] tcp: use kmalloc() than kmalloc_array().
  2015-11-07 15:50 [PATCH] tcp: use kmalloc() than kmalloc_array() Tetsuo Handa
  2015-11-07 15:58 ` Tetsuo Handa
@ 2015-11-07 18:50 ` Eric Dumazet
  2015-11-07 19:21   ` David Miller
  1 sibling, 1 reply; 6+ messages in thread
From: Eric Dumazet @ 2015-11-07 18:50 UTC (permalink / raw)
  To: Tetsuo Handa; +Cc: edumazet, netdev

On Sun, 2015-11-08 at 00:50 +0900, Tetsuo Handa wrote:
> Commit 095dc8e0c3686d58 ("tcp: fix/cleanup inet_ehash_locks_alloc()")
> silently changed from kmalloc() to kmalloc_array(). The latter has
> overflow check whereas the former doesn't have.
> 
> If nblocks * locksz might overflow, we need to do like
> 
>   -  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
>   +  if (!hashinfo->ehash_locks && nblocks > SIZE_MAX / locksz)
>        hashinfo->ehash_locks = vmalloc(nblocks * locksz);
> 
> because kmalloc_array() detects overflow and returns NULL.
> But if nblocks * locksz is guaranteed not to overflow, there is
> no need to use kmalloc_array().
> 
> Since I assume it won't overflow, use kmalloc() than kmalloc_array().
> 
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> ---
>  net/ipv4/inet_hashtables.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
> index ccc5980..8f4ab27 100644
> --- a/net/ipv4/inet_hashtables.c
> +++ b/net/ipv4/inet_hashtables.c
> @@ -648,8 +648,8 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
>  		/* no more locks than number of hash buckets */
>  		nblocks = min(nblocks, hashinfo->ehash_mask + 1);
>  
> -		hashinfo->ehash_locks =	kmalloc_array(nblocks, locksz,
> -						      GFP_KERNEL | __GFP_NOWARN);
> +		hashinfo->ehash_locks =	kmalloc(nblocks * locksz,
> +						GFP_KERNEL | __GFP_NOWARN);
>  		if (!hashinfo->ehash_locks)
>  			hashinfo->ehash_locks = vmalloc(nblocks * locksz);
>  

I remember that my initial attempt had been to use size_t for nblocks,
but I realized roundup_pow_of_two() only accepted an 'unsigned long'

Then, presumably I just gave up.

I do not feel we should go back to kmalloc() just because
vmalloc_array() does not exist yet.

Maybe the following would clear things for you guys ?

If it is OK, please Tetsuo submit this patch formally.

Thanks !

diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ccc5980797fc..8f7c71e20089 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -638,15 +638,15 @@ EXPORT_SYMBOL_GPL(inet_hashinfo_init);
 int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
 {
 	unsigned int locksz = sizeof(spinlock_t);
-	unsigned int i, nblocks = 1;
+	size_t i, nblocks = 1;
 
 	if (locksz != 0) {
 		/* allocate 2 cache lines or at least one spinlock per cpu */
-		nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U);
+		nblocks = max_t(size_t, 2 * L1_CACHE_BYTES / locksz, 1);
 		nblocks = roundup_pow_of_two(nblocks * num_possible_cpus());
 
 		/* no more locks than number of hash buckets */
-		nblocks = min(nblocks, hashinfo->ehash_mask + 1);
+		nblocks = min_t(size_t, nblocks, hashinfo->ehash_mask + 1);
 
 		hashinfo->ehash_locks =	kmalloc_array(nblocks, locksz,
 						      GFP_KERNEL | __GFP_NOWARN);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] tcp: use kmalloc() than kmalloc_array().
  2015-11-07 18:50 ` Eric Dumazet
@ 2015-11-07 19:21   ` David Miller
  2015-11-08  4:43     ` Tetsuo Handa
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2015-11-07 19:21 UTC (permalink / raw)
  To: eric.dumazet; +Cc: penguin-kernel, edumazet, netdev

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sat, 07 Nov 2015 10:50:07 -0800

> I do not feel we should go back to kmalloc() just because
> vmalloc_array() does not exist yet.

Agreed.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] tcp: use kmalloc() than kmalloc_array().
  2015-11-07 19:21   ` David Miller
@ 2015-11-08  4:43     ` Tetsuo Handa
  0 siblings, 0 replies; 6+ messages in thread
From: Tetsuo Handa @ 2015-11-08  4:43 UTC (permalink / raw)
  To: davem, eric.dumazet; +Cc: edumazet, netdev

David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Sat, 07 Nov 2015 10:50:07 -0800
> 
> > I do not feel we should go back to kmalloc() just because
> > vmalloc_array() does not exist yet.
> 
> Agreed.
> 

Please change as you like.

I was thinking to introduce a helper that does vmalloc() when
kmalloc() failed because locations that do

  ptr = kmalloc(size, GFP_NOFS);
  if (!ptr)
      ptr = vmalloc(size); /* Wrong because GFP_KERNEL is used implicitly */

are found. I just noticed that inet_ehash_locks_alloc() is doing

  ptr = kmalloc_array(count, size, GFP_KERNEL);
  if (!ptr)
      ptr = vmalloc(count * size); /* Wrong because overflow is not checked */

and wanted to know your intent.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-11-08  4:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-07 15:50 [PATCH] tcp: use kmalloc() than kmalloc_array() Tetsuo Handa
2015-11-07 15:58 ` Tetsuo Handa
2015-11-07 18:02   ` David Miller
2015-11-07 18:50 ` Eric Dumazet
2015-11-07 19:21   ` David Miller
2015-11-08  4:43     ` Tetsuo Handa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.