2023-09-07 18:56:50

by David Laight

[permalink] [raw]
Subject: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

The typical use of kmalloc_size_roundup() is:
ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
if (!ptr) return -ENOMEM.
This means it is vitally important that the returned value isn't
less than the argument even if the argument is insane.
In particular if kmalloc_slab() fails or the value is above
(MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
it's single zero-length buffer.

Fix by returning the input size on error or if the size exceeds
a 'sanity' limit.
kmalloc() will then return NULL is the size really is too big.


Signed-off-by: David Laight <[email protected]>
Fixes: 05a940656e1eb ("slab: Introduce kmalloc_size_roundup()")
---
v2:
- Use KMALLOC_MAX_SIZE for upper limit.
(KMALLOC_MAX_SIZE + 1 may give better code on some archs!)
- Invert test for overlarge for consistency.
- Put a likely() on result of kmalloc_slab().

mm/slab_common.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/mm/slab_common.c b/mm/slab_common.c
index cd71f9581e67..0fb7c7e19bad 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -747,22 +747,22 @@ size_t kmalloc_size_roundup(size_t size)
{
struct kmem_cache *c;

- /* Short-circuit the 0 size case. */
- if (unlikely(size == 0))
- return 0;
- /* Short-circuit saturated "too-large" case. */
- if (unlikely(size == SIZE_MAX))
- return SIZE_MAX;
+ if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
+ /*
+ * The flags don't matter since size_index is common to all.
+ * Neither does the caller for just getting ->object_size.
+ */
+ c = kmalloc_slab(size, GFP_KERNEL, 0);
+ return likely(c) ? c->object_size : size;
+ }
+
/* Above the smaller buckets, size is a multiple of page size. */
- if (size > KMALLOC_MAX_CACHE_SIZE)
+ if (size && size <= KMALLOC_MAX_SIZE)
return PAGE_SIZE << get_order(size);

- /*
- * The flags don't matter since size_index is common to all.
- * Neither does the caller for just getting ->object_size.
- */
- c = kmalloc_slab(size, GFP_KERNEL, 0);
- return c ? c->object_size : 0;
+ /* Return 'size' for 0 and very large - kmalloc() may fail. */
+ return size;
+
}
EXPORT_SYMBOL(kmalloc_size_roundup);

--
2.17.1

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


2023-09-08 18:19:35

by David Laight

[permalink] [raw]
Subject: RE: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

From: Kees Cook
> Sent: 07 September 2023 20:38
>
> On Thu, Sep 07, 2023 at 12:42:20PM +0000, David Laight wrote:
> > The typical use of kmalloc_size_roundup() is:
> > ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
> > if (!ptr) return -ENOMEM.
> > This means it is vitally important that the returned value isn't
> > less than the argument even if the argument is insane.
> > In particular if kmalloc_slab() fails or the value is above
> > (MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
> > it's single zero-length buffer.
> >
> > Fix by returning the input size on error or if the size exceeds
> > a 'sanity' limit.
> > kmalloc() will then return NULL is the size really is too big.
> >
> >
> > Signed-off-by: David Laight <[email protected]>
> > Fixes: 05a940656e1eb ("slab: Introduce kmalloc_size_roundup()")
> > ---
> > v2:
> > - Use KMALLOC_MAX_SIZE for upper limit.
> > (KMALLOC_MAX_SIZE + 1 may give better code on some archs!)
> > - Invert test for overlarge for consistency.
> > - Put a likely() on result of kmalloc_slab().
> >
> > mm/slab_common.c | 26 +++++++++++++-------------
> > 1 file changed, 13 insertions(+), 13 deletions(-)
> >
> > diff --git a/mm/slab_common.c b/mm/slab_common.c
> > index cd71f9581e67..0fb7c7e19bad 100644
> > --- a/mm/slab_common.c
> > +++ b/mm/slab_common.c
> > @@ -747,22 +747,22 @@ size_t kmalloc_size_roundup(size_t size)
> > {
> > struct kmem_cache *c;
> >
> > - /* Short-circuit the 0 size case. */
> > - if (unlikely(size == 0))
> > - return 0;
>
> If we want to allow 0, let's just leave this case as-is: the compiler
> will optimize it against the other tests.

I doubt the compiler will optimise it away - especially with
the unlikely().

OTOH the explicit checks for (size && size <= LIMIT) do
get optimised to ((size - 1) <= LIMIT - 1) so become
a single compare.

Then returning 'size' at the bottom means that zero is returned
in the arg is zero - which is fine.

>
> > - /* Short-circuit saturated "too-large" case. */
> > - if (unlikely(size == SIZE_MAX))
> > - return SIZE_MAX;
> > + if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
> > + /*
> > + * The flags don't matter since size_index is common to all.
> > + * Neither does the caller for just getting ->object_size.
> > + */
> > + c = kmalloc_slab(size, GFP_KERNEL, 0);
> > + return likely(c) ? c->object_size : size;
>
> I would like to have this fail "safe". c should never be NULL here, so
> let's return "KMALLOC_MAX_SIZE + 1" to force failures.

Why even try to force failure here?
The whole function is just an optimisation so that the caller
can use the spare space.

The only thing it mustn't do is return a smaller value.

>
> > + }
> > +
> > /* Above the smaller buckets, size is a multiple of page size. */
> > - if (size > KMALLOC_MAX_CACHE_SIZE)
> > + if (size && size <= KMALLOC_MAX_SIZE)
> > return PAGE_SIZE << get_order(size);
> >
> > - /*
> > - * The flags don't matter since size_index is common to all.
> > - * Neither does the caller for just getting ->object_size.
> > - */
> > - c = kmalloc_slab(size, GFP_KERNEL, 0);
> > - return c ? c->object_size : 0;
> > + /* Return 'size' for 0 and very large - kmalloc() may fail. */
>
> I want to _be certain_ failure happens. If we get here we need to return
> "KMALLOC_MAX_SIZE + 1"

Why care?

David

>
> -Kees
>
> > + return size;
> > +
> > }
> > EXPORT_SYMBOL(kmalloc_size_roundup);
> >
> > --
> > 2.17.1
> >
> > -
> > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> > Registration No: 1397386 (Wales)
> >
>
> --
> Kees Cook

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

2023-09-20 10:18:08

by David Laight

[permalink] [raw]
Subject: RE: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

From: Vlastimil Babka
> Sent: 20 September 2023 10:58
>
> On 9/11/23 18:38, David Laight wrote:
> >> >> So perhaps the best would be to return size for c == NULL, but also do a
> >> >> WARN_ONCE?
> >> >
> >> > That would add a real function call to an otherwise leaf function
> >> > and almost certainly require the compiler create a stack frame.
> >>
> >> Hm I thought WARN is done by tripping on undefined instruction like BUG
> >> these days. Also any code that accepts the call to kmalloc_size_roundup
> >> probably could accept that too.
> >
> > It's probably just worth removing the c == NULL check and
> > assuming there won't be any fallout.
> > The NULL pointer deref is an easy to debug as anything else.
> >
> > If it gets called in any early init code it'll soon show up.
>
> Good point, early crash should be ok.
> So how about this with my tweaks, looks ok?

Is that just/mainly the change to assume that kmalloc_slab() doesn't fail?
You can also remove 'c'.
return kmalloc_slab(size, GFP_KERNEL, 0)->object_size;
isn't too long.

I also did a grep for callers.
Nothing in early code, IIRC mainly 'net'.

David

> I'll put it in -next and
> send with another hotfix to 6.6 next week.
> ----8<----
> From f5de1ee7b35d7ab35c21c79dd13cea49fbe239b7 Mon Sep 17 00:00:00 2001
> From: David Laight <[email protected]>
> Date: Thu, 7 Sep 2023 12:42:20 +0000
> Subject: [PATCH] Subject: [PATCH v2] slab: kmalloc_size_roundup() must not
> return 0 for non-zero size
>
> The typical use of kmalloc_size_roundup() is:
>
> ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
> if (!ptr) return -ENOMEM.
>
> This means it is vitally important that the returned value isn't less
> than the argument even if the argument is insane.
> In particular if kmalloc_slab() fails or the value is above
> (MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
> its single zero-length buffer ZERO_SIZE_PTR.
>
> Fix this by returning the input size if the size exceeds
> KMALLOC_MAX_SIZE. kmalloc() will then return NULL as the size really is
> too big.
>
> kmalloc_slab() should not normally return NULL, unless called too early.
> Again, returning zero is not the correct action as it can be in some
> usage scenarios stored to a variable and only later cause kmalloc()
> return ZERO_SIZE_PTR and subsequent crashes on access. Instead we can
> simply stop checking the kmalloc_slab() result completely, as calling
> kmalloc_size_roundup() too early would then result in an immediate crash
> during boot and the developer noticing an issue in their code.
>
> [[email protected]: remove kmalloc_slab() result check, tweak comments and
> commit log]
> Signed-off-by: David Laight <[email protected]>
> Fixes: 05a940656e1e ("slab: Introduce kmalloc_size_roundup()")
> Signed-off-by: Vlastimil Babka <[email protected]>
> ---
> mm/slab_common.c | 25 ++++++++++++++-----------
> 1 file changed, 14 insertions(+), 11 deletions(-)
>
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> index e99e821065c3..1dc108224bd1 100644
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -747,22 +747,25 @@ size_t kmalloc_size_roundup(size_t size)
> {
> struct kmem_cache *c;
>
> - /* Short-circuit the 0 size case. */
> - if (unlikely(size == 0))
> - return 0;
> - /* Short-circuit saturated "too-large" case. */
> - if (unlikely(size == SIZE_MAX))
> - return SIZE_MAX;
> + if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
> + /*
> + * The flags don't matter since size_index is common to all.
> + * Neither does the caller for just getting ->object_size.
> + */
> + c = kmalloc_slab(size, GFP_KERNEL, 0);
> + return c->object_size;
> + }
> +
> /* Above the smaller buckets, size is a multiple of page size. */
> - if (size > KMALLOC_MAX_CACHE_SIZE)
> + if (size && size <= KMALLOC_MAX_SIZE)
> return PAGE_SIZE << get_order(size);
>
> /*
> - * The flags don't matter since size_index is common to all.
> - * Neither does the caller for just getting ->object_size.
> + * Return 'size' for 0 - kmalloc() returns ZERO_SIZE_PTR
> + * and very large size - kmalloc() may fail.
> */
> - c = kmalloc_slab(size, GFP_KERNEL, 0);
> - return c ? c->object_size : 0;
> + return size;
> +
> }
> EXPORT_SYMBOL(kmalloc_size_roundup);
>
> --
> 2.42.0
>
>

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

2023-09-20 14:37:41

by Vlastimil Babka

[permalink] [raw]
Subject: Re: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

On 9/11/23 18:38, David Laight wrote:
>> >> So perhaps the best would be to return size for c == NULL, but also do a
>> >> WARN_ONCE?
>> >
>> > That would add a real function call to an otherwise leaf function
>> > and almost certainly require the compiler create a stack frame.
>>
>> Hm I thought WARN is done by tripping on undefined instruction like BUG
>> these days. Also any code that accepts the call to kmalloc_size_roundup
>> probably could accept that too.
>
> It's probably just worth removing the c == NULL check and
> assuming there won't be any fallout.
> The NULL pointer deref is an easy to debug as anything else.
>
> If it gets called in any early init code it'll soon show up.

Good point, early crash should be ok.
So how about this with my tweaks, looks ok? I'll put it in -next and
send with another hotfix to 6.6 next week.
----8<----
From f5de1ee7b35d7ab35c21c79dd13cea49fbe239b7 Mon Sep 17 00:00:00 2001
From: David Laight <[email protected]>
Date: Thu, 7 Sep 2023 12:42:20 +0000
Subject: [PATCH] Subject: [PATCH v2] slab: kmalloc_size_roundup() must not
return 0 for non-zero size

The typical use of kmalloc_size_roundup() is:

ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
if (!ptr) return -ENOMEM.

This means it is vitally important that the returned value isn't less
than the argument even if the argument is insane.
In particular if kmalloc_slab() fails or the value is above
(MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
its single zero-length buffer ZERO_SIZE_PTR.

Fix this by returning the input size if the size exceeds
KMALLOC_MAX_SIZE. kmalloc() will then return NULL as the size really is
too big.

kmalloc_slab() should not normally return NULL, unless called too early.
Again, returning zero is not the correct action as it can be in some
usage scenarios stored to a variable and only later cause kmalloc()
return ZERO_SIZE_PTR and subsequent crashes on access. Instead we can
simply stop checking the kmalloc_slab() result completely, as calling
kmalloc_size_roundup() too early would then result in an immediate crash
during boot and the developer noticing an issue in their code.

[[email protected]: remove kmalloc_slab() result check, tweak comments and
commit log]
Signed-off-by: David Laight <[email protected]>
Fixes: 05a940656e1e ("slab: Introduce kmalloc_size_roundup()")
Signed-off-by: Vlastimil Babka <[email protected]>
---
mm/slab_common.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/mm/slab_common.c b/mm/slab_common.c
index e99e821065c3..1dc108224bd1 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -747,22 +747,25 @@ size_t kmalloc_size_roundup(size_t size)
{
struct kmem_cache *c;

- /* Short-circuit the 0 size case. */
- if (unlikely(size == 0))
- return 0;
- /* Short-circuit saturated "too-large" case. */
- if (unlikely(size == SIZE_MAX))
- return SIZE_MAX;
+ if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
+ /*
+ * The flags don't matter since size_index is common to all.
+ * Neither does the caller for just getting ->object_size.
+ */
+ c = kmalloc_slab(size, GFP_KERNEL, 0);
+ return c->object_size;
+ }
+
/* Above the smaller buckets, size is a multiple of page size. */
- if (size > KMALLOC_MAX_CACHE_SIZE)
+ if (size && size <= KMALLOC_MAX_SIZE)
return PAGE_SIZE << get_order(size);

/*
- * The flags don't matter since size_index is common to all.
- * Neither does the caller for just getting ->object_size.
+ * Return 'size' for 0 - kmalloc() returns ZERO_SIZE_PTR
+ * and very large size - kmalloc() may fail.
*/
- c = kmalloc_slab(size, GFP_KERNEL, 0);
- return c ? c->object_size : 0;
+ return size;
+
}
EXPORT_SYMBOL(kmalloc_size_roundup);

--
2.42.0



2023-09-21 13:56:06

by Vlastimil Babka

[permalink] [raw]
Subject: Re: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

On 9/20/23 12:06, David Laight wrote:
> From: Vlastimil Babka
>> Sent: 20 September 2023 10:58
>>
>> On 9/11/23 18:38, David Laight wrote:
>> >> >> So perhaps the best would be to return size for c == NULL, but also do a
>> >> >> WARN_ONCE?
>> >> >
>> >> > That would add a real function call to an otherwise leaf function
>> >> > and almost certainly require the compiler create a stack frame.
>> >>
>> >> Hm I thought WARN is done by tripping on undefined instruction like BUG
>> >> these days. Also any code that accepts the call to kmalloc_size_roundup
>> >> probably could accept that too.
>> >
>> > It's probably just worth removing the c == NULL check and
>> > assuming there won't be any fallout.
>> > The NULL pointer deref is an easy to debug as anything else.
>> >
>> > If it gets called in any early init code it'll soon show up.
>>
>> Good point, early crash should be ok.
>> So how about this with my tweaks, looks ok?
>
> Is that just/mainly the change to assume that kmalloc_slab() doesn't fail?

Yes.

> You can also remove 'c'.
> return kmalloc_slab(size, GFP_KERNEL, 0)->object_size;
> isn't too long.

Right, did that and pushed to -next. Thanks!

> I also did a grep for callers.
> Nothing in early code, IIRC mainly 'net'.
>
> David
>
>> I'll put it in -next and
>> send with another hotfix to 6.6 next week.
>> ----8<----
>> From f5de1ee7b35d7ab35c21c79dd13cea49fbe239b7 Mon Sep 17 00:00:00 2001
>> From: David Laight <[email protected]>
>> Date: Thu, 7 Sep 2023 12:42:20 +0000
>> Subject: [PATCH] Subject: [PATCH v2] slab: kmalloc_size_roundup() must not
>> return 0 for non-zero size
>>
>> The typical use of kmalloc_size_roundup() is:
>>
>> ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
>> if (!ptr) return -ENOMEM.
>>
>> This means it is vitally important that the returned value isn't less
>> than the argument even if the argument is insane.
>> In particular if kmalloc_slab() fails or the value is above
>> (MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
>> its single zero-length buffer ZERO_SIZE_PTR.
>>
>> Fix this by returning the input size if the size exceeds
>> KMALLOC_MAX_SIZE. kmalloc() will then return NULL as the size really is
>> too big.
>>
>> kmalloc_slab() should not normally return NULL, unless called too early.
>> Again, returning zero is not the correct action as it can be in some
>> usage scenarios stored to a variable and only later cause kmalloc()
>> return ZERO_SIZE_PTR and subsequent crashes on access. Instead we can
>> simply stop checking the kmalloc_slab() result completely, as calling
>> kmalloc_size_roundup() too early would then result in an immediate crash
>> during boot and the developer noticing an issue in their code.
>>
>> [[email protected]: remove kmalloc_slab() result check, tweak comments and
>> commit log]
>> Signed-off-by: David Laight <[email protected]>
>> Fixes: 05a940656e1e ("slab: Introduce kmalloc_size_roundup()")
>> Signed-off-by: Vlastimil Babka <[email protected]>
>> ---
>> mm/slab_common.c | 25 ++++++++++++++-----------
>> 1 file changed, 14 insertions(+), 11 deletions(-)
>>
>> diff --git a/mm/slab_common.c b/mm/slab_common.c
>> index e99e821065c3..1dc108224bd1 100644
>> --- a/mm/slab_common.c
>> +++ b/mm/slab_common.c
>> @@ -747,22 +747,25 @@ size_t kmalloc_size_roundup(size_t size)
>> {
>> struct kmem_cache *c;
>>
>> - /* Short-circuit the 0 size case. */
>> - if (unlikely(size == 0))
>> - return 0;
>> - /* Short-circuit saturated "too-large" case. */
>> - if (unlikely(size == SIZE_MAX))
>> - return SIZE_MAX;
>> + if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
>> + /*
>> + * The flags don't matter since size_index is common to all.
>> + * Neither does the caller for just getting ->object_size.
>> + */
>> + c = kmalloc_slab(size, GFP_KERNEL, 0);
>> + return c->object_size;
>> + }
>> +
>> /* Above the smaller buckets, size is a multiple of page size. */
>> - if (size > KMALLOC_MAX_CACHE_SIZE)
>> + if (size && size <= KMALLOC_MAX_SIZE)
>> return PAGE_SIZE << get_order(size);
>>
>> /*
>> - * The flags don't matter since size_index is common to all.
>> - * Neither does the caller for just getting ->object_size.
>> + * Return 'size' for 0 - kmalloc() returns ZERO_SIZE_PTR
>> + * and very large size - kmalloc() may fail.
>> */
>> - c = kmalloc_slab(size, GFP_KERNEL, 0);
>> - return c ? c->object_size : 0;
>> + return size;
>> +
>> }
>> EXPORT_SYMBOL(kmalloc_size_roundup);
>>
>> --
>> 2.42.0
>>
>>
>
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)

2023-09-30 20:56:02

by Hyeonggon Yoo

[permalink] [raw]
Subject: Re: Subject: [PATCH v2] slab: kmalloc_size_roundup() must not return 0 for non-zero size

On Wed, Sep 20, 2023 at 9:48 PM Vlastimil Babka <[email protected]> wrote:
>
> On 9/20/23 12:06, David Laight wrote:
> > From: Vlastimil Babka
> >> Sent: 20 September 2023 10:58
> >>
> >> On 9/11/23 18:38, David Laight wrote:
> >> >> >> So perhaps the best would be to return size for c == NULL, but also do a
> >> >> >> WARN_ONCE?
> >> >> >
> >> >> > That would add a real function call to an otherwise leaf function
> >> >> > and almost certainly require the compiler create a stack frame.
> >> >>
> >> >> Hm I thought WARN is done by tripping on undefined instruction like BUG
> >> >> these days. Also any code that accepts the call to kmalloc_size_roundup
> >> >> probably could accept that too.
> >> >
> >> > It's probably just worth removing the c == NULL check and
> >> > assuming there won't be any fallout.
> >> > The NULL pointer deref is an easy to debug as anything else.
> >> >
> >> > If it gets called in any early init code it'll soon show up.
> >>
> >> Good point, early crash should be ok.
> >> So how about this with my tweaks, looks ok?
> >
> > Is that just/mainly the change to assume that kmalloc_slab() doesn't fail?
>
> Yes.
>
> > You can also remove 'c'.
> > return kmalloc_slab(size, GFP_KERNEL, 0)->object_size;
> > isn't too long.
>
> Right, did that and pushed to -next. Thanks!

A bit late, but for the record:

Looks good to me,
Reviewed-by: Hyeonggon Yoo <[email protected]>

> > I also did a grep for callers.
> > Nothing in early code, IIRC mainly 'net'.
> >
> > David
> >
> >> I'll put it in -next and
> >> send with another hotfix to 6.6 next week.
> >> ----8<----
> >> From f5de1ee7b35d7ab35c21c79dd13cea49fbe239b7 Mon Sep 17 00:00:00 2001
> >> From: David Laight <[email protected]>
> >> Date: Thu, 7 Sep 2023 12:42:20 +0000
> >> Subject: [PATCH] Subject: [PATCH v2] slab: kmalloc_size_roundup() must not
> >> return 0 for non-zero size
> >>
> >> The typical use of kmalloc_size_roundup() is:
> >>
> >> ptr = kmalloc(sz = kmalloc_size_roundup(size), ...);
> >> if (!ptr) return -ENOMEM.
> >>
> >> This means it is vitally important that the returned value isn't less
> >> than the argument even if the argument is insane.
> >> In particular if kmalloc_slab() fails or the value is above
> >> (MAX_ULONG - PAGE_SIZE) zero is returned and kmalloc() will return
> >> its single zero-length buffer ZERO_SIZE_PTR.
> >>
> >> Fix this by returning the input size if the size exceeds
> >> KMALLOC_MAX_SIZE. kmalloc() will then return NULL as the size really is
> >> too big.
> >>
> >> kmalloc_slab() should not normally return NULL, unless called too early.
> >> Again, returning zero is not the correct action as it can be in some
> >> usage scenarios stored to a variable and only later cause kmalloc()
> >> return ZERO_SIZE_PTR and subsequent crashes on access. Instead we can
> >> simply stop checking the kmalloc_slab() result completely, as calling
> >> kmalloc_size_roundup() too early would then result in an immediate crash
> >> during boot and the developer noticing an issue in their code.
> >>
> >> [[email protected]: remove kmalloc_slab() result check, tweak comments and
> >> commit log]
> >> Signed-off-by: David Laight <[email protected]>
> >> Fixes: 05a940656e1e ("slab: Introduce kmalloc_size_roundup()")
> >> Signed-off-by: Vlastimil Babka <[email protected]>
> >> ---
> >> mm/slab_common.c | 25 ++++++++++++++-----------
> >> 1 file changed, 14 insertions(+), 11 deletions(-)
> >>
> >> diff --git a/mm/slab_common.c b/mm/slab_common.c
> >> index e99e821065c3..1dc108224bd1 100644
> >> --- a/mm/slab_common.c
> >> +++ b/mm/slab_common.c
> >> @@ -747,22 +747,25 @@ size_t kmalloc_size_roundup(size_t size)
> >> {
> >> struct kmem_cache *c;
> >>
> >> - /* Short-circuit the 0 size case. */
> >> - if (unlikely(size == 0))
> >> - return 0;
> >> - /* Short-circuit saturated "too-large" case. */
> >> - if (unlikely(size == SIZE_MAX))
> >> - return SIZE_MAX;
> >> + if (size && size <= KMALLOC_MAX_CACHE_SIZE) {
> >> + /*
> >> + * The flags don't matter since size_index is common to all.
> >> + * Neither does the caller for just getting ->object_size.
> >> + */
> >> + c = kmalloc_slab(size, GFP_KERNEL, 0);
> >> + return c->object_size;
> >> + }
> >> +
> >> /* Above the smaller buckets, size is a multiple of page size. */
> >> - if (size > KMALLOC_MAX_CACHE_SIZE)
> >> + if (size && size <= KMALLOC_MAX_SIZE)
> >> return PAGE_SIZE << get_order(size);
> >>
> >> /*
> >> - * The flags don't matter since size_index is common to all.
> >> - * Neither does the caller for just getting ->object_size.
> >> + * Return 'size' for 0 - kmalloc() returns ZERO_SIZE_PTR
> >> + * and very large size - kmalloc() may fail.
> >> */
> >> - c = kmalloc_slab(size, GFP_KERNEL, 0);
> >> - return c ? c->object_size : 0;
> >> + return size;
> >> +
> >> }
> >> EXPORT_SYMBOL(kmalloc_size_roundup);
> >>
> >> --
> >> 2.42.0
> >>
> >>
> >
> > -
> > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> > Registration No: 1397386 (Wales)
>