[PATCH] mm: slub: fix dereference invalid pointer in alloc_consistency_checks

Li Qiong posted 1 patch 2 months, 1 week ago
mm/slub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] mm: slub: fix dereference invalid pointer in alloc_consistency_checks
Posted by Li Qiong 2 months, 1 week ago
In object_err(), need dereference the 'object' pointer, it may cause
a invalid pointer fault. Use slab_err() instead.

Signed-off-by: Li Qiong <liqiong@nfschina.com>
---
 mm/slub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/slub.c b/mm/slub.c
index 31e11ef256f9..3a2e57e2e2d7 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1587,7 +1587,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
 		return 0;
 
 	if (!check_valid_pointer(s, slab, object)) {
-		object_err(s, slab, object, "Freelist Pointer check fails");
+		slab_err(s, slab, "Freelist Pointer (0x%p) check fails", object);
 		return 0;
 	}
 
-- 
2.30.2
Re: [PATCH] mm: slub: fix dereference invalid pointer in alloc_consistency_checks
Posted by Harry Yoo 2 months, 1 week ago
On Fri, Jul 25, 2025 at 10:48:54AM +0800, Li Qiong wrote:
> In object_err(), need dereference the 'object' pointer, it may cause
> a invalid pointer fault. Use slab_err() instead.

Hi Li Qiong, this patch makes sense to me.
But I'd suggest to rephrase it a little bit, like:

mm/slab: avoid deref of free pointer in sanity checks if object is invalid

For debugging purposes, object_err() prints free pointer of the object.
However, if check_valid_pointer() returns false for object,
`object + s->offset` is also invalid and dereferncing it can lead to a
crash. Therefore, avoid dereferencing it and only print the object's
address in such cases.

> Signed-off-by: Li Qiong <liqiong@nfschina.com>

Which commit introduced this problem?
A Fixes: tag is needed to determine which -stable versions it should be
backported to.

And to backport MM patches to -stable, you need to explicitly add
'Cc: stable@vger.kernel.org' to the patch.

> ---
>  mm/slub.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index 31e11ef256f9..3a2e57e2e2d7 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1587,7 +1587,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
>  		return 0;
>  
>  	if (!check_valid_pointer(s, slab, object)) {
> -		object_err(s, slab, object, "Freelist Pointer check fails");
> +		slab_err(s, slab, "Freelist Pointer (0x%p) check fails", object);

Can this be
slab_err(s, slab, "Invalid object pointer 0x%p", object);
to align with free_consistency_checks()?

>  		return 0;
>  	}
>  

It might be worth adding a comment in object_err() stating that it should
only be called when check_valid_pointer() returns true for object, and
a WARN_ON_ONCE(!check_valid_pointer(s, slab, object)) to catch incorrect
usages?

-- 
Cheers,
Harry / Hyeonggon
Re: [PATCH] mm: slub: fix dereference invalid pointer in alloc_consistency_checks
Posted by liqiong 2 months, 1 week ago

在 2025/7/25 12:01, Harry Yoo 写道:
> On Fri, Jul 25, 2025 at 10:48:54AM +0800, Li Qiong wrote:
>> In object_err(), need dereference the 'object' pointer, it may cause
>> a invalid pointer fault. Use slab_err() instead.
> Hi Li Qiong, this patch makes sense to me.
> But I'd suggest to rephrase it a little bit, like:
>
> mm/slab: avoid deref of free pointer in sanity checks if object is invalid
>
> For debugging purposes, object_err() prints free pointer of the object.
> However, if check_valid_pointer() returns false for object,
> `object + s->offset` is also invalid and dereferncing it can lead to a
> crash. Therefore, avoid dereferencing it and only print the object's
> address in such cases.

Thanks, I will send a v2 patch.


>
>> Signed-off-by: Li Qiong <liqiong@nfschina.com>
> Which commit introduced this problem?
> A Fixes: tag is needed to determine which -stable versions it should be
> backported to.
>
> And to backport MM patches to -stable, you need to explicitly add
> 'Cc: stable@vger.kernel.org' to the patch.
>
>> ---
>>  mm/slub.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/mm/slub.c b/mm/slub.c
>> index 31e11ef256f9..3a2e57e2e2d7 100644
>> --- a/mm/slub.c
>> +++ b/mm/slub.c
>> @@ -1587,7 +1587,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
>>  		return 0;
>>  
>>  	if (!check_valid_pointer(s, slab, object)) {
>> -		object_err(s, slab, object, "Freelist Pointer check fails");
>> +		slab_err(s, slab, "Freelist Pointer (0x%p) check fails", object);
> Can this be
> slab_err(s, slab, "Invalid object pointer 0x%p", object);
> to align with free_consistency_checks()?




>
>>  		return 0;
>>  	}
>>  
> It might be worth adding a comment in object_err() stating that it should
> only be called when check_valid_pointer() returns true for object, and
> a WARN_ON_ONCE(!check_valid_pointer(s, slab, object)) to catch incorrect
> usages?



[PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Li Qiong 2 months, 1 week ago
For debugging, object_err() prints free pointer of the object.
However, if check_valid_pointer() returns false for a object,
dereferncing `object + s->offset` can lead to a crash. Therefore,
print the object's address in such cases.

Fixes: bb192ed9aa71 ("mm/slub: Convert most struct page to struct slab by spatch")
Signed-off-by: Li Qiong <liqiong@nfschina.com>
---
v2:
- rephrase the commit message, add comment for object_err().
---
 mm/slub.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/mm/slub.c b/mm/slub.c
index 31e11ef256f9..8b24f1cf3079 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1097,6 +1097,10 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p)
 			      size_from_object(s) - off);
 }
 
+/*
+ * object - should be a valid object.
+ * check_valid_pointer(s, slab, object) should be true.
+ */
 static void object_err(struct kmem_cache *s, struct slab *slab,
 			u8 *object, const char *reason)
 {
@@ -1587,7 +1591,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
 		return 0;
 
 	if (!check_valid_pointer(s, slab, object)) {
-		object_err(s, slab, object, "Freelist Pointer check fails");
+		slab_err(s, slab, "Invalid object pointer 0x%p", object);
 		return 0;
 	}
 
-- 
2.30.2
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Vlastimil Babka 2 months, 1 week ago
On 7/25/25 08:49, Li Qiong wrote:
> For debugging, object_err() prints free pointer of the object.
> However, if check_valid_pointer() returns false for a object,
> dereferncing `object + s->offset` can lead to a crash. Therefore,
> print the object's address in such cases.
> 
> Fixes: bb192ed9aa71 ("mm/slub: Convert most struct page to struct slab by spatch")

That was the last commit to change the line, but the problem existed before,
AFAICS all the time, so I did:

    Fixes: 7656c72b5a63 ("SLUB: add macros for scanning objects in a slab")
    Cc: <stable@vger.kernel.org>

> Signed-off-by: Li Qiong <liqiong@nfschina.com>

Added to slab/for-next, thanks!

> ---
> v2:
> - rephrase the commit message, add comment for object_err().
> ---
>  mm/slub.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index 31e11ef256f9..8b24f1cf3079 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1097,6 +1097,10 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p)
>  			      size_from_object(s) - off);
>  }
>  
> +/*
> + * object - should be a valid object.
> + * check_valid_pointer(s, slab, object) should be true.
> + */
>  static void object_err(struct kmem_cache *s, struct slab *slab,
>  			u8 *object, const char *reason)
>  {
> @@ -1587,7 +1591,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
>  		return 0;
>  
>  	if (!check_valid_pointer(s, slab, object)) {
> -		object_err(s, slab, object, "Freelist Pointer check fails");
> +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
>  		return 0;
>  	}
>
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Vlastimil Babka 2 months, 1 week ago
On 7/25/25 18:47, Vlastimil Babka wrote:
> On 7/25/25 08:49, Li Qiong wrote:
>> For debugging, object_err() prints free pointer of the object.
>> However, if check_valid_pointer() returns false for a object,
>> dereferncing `object + s->offset` can lead to a crash. Therefore,
>> print the object's address in such cases.
>> 
>> Fixes: bb192ed9aa71 ("mm/slub: Convert most struct page to struct slab by spatch")
> 
> That was the last commit to change the line, but the problem existed before,
> AFAICS all the time, so I did:
> 
>     Fixes: 7656c72b5a63 ("SLUB: add macros for scanning objects in a slab")
>     Cc: <stable@vger.kernel.org>
> 
>> Signed-off-by: Li Qiong <liqiong@nfschina.com>
> 
> Added to slab/for-next, thanks!

Dropped based on Matthew's review

>> ---
>> v2:
>> - rephrase the commit message, add comment for object_err().
>> ---
>>  mm/slub.c | 6 +++++-
>>  1 file changed, 5 insertions(+), 1 deletion(-)
>> 
>> diff --git a/mm/slub.c b/mm/slub.c
>> index 31e11ef256f9..8b24f1cf3079 100644
>> --- a/mm/slub.c
>> +++ b/mm/slub.c
>> @@ -1097,6 +1097,10 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p)
>>  			      size_from_object(s) - off);
>>  }
>>  
>> +/*
>> + * object - should be a valid object.
>> + * check_valid_pointer(s, slab, object) should be true.
>> + */
>>  static void object_err(struct kmem_cache *s, struct slab *slab,
>>  			u8 *object, const char *reason)
>>  {
>> @@ -1587,7 +1591,7 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,
>>  		return 0;
>>  
>>  	if (!check_valid_pointer(s, slab, object)) {
>> -		object_err(s, slab, object, "Freelist Pointer check fails");
>> +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
>>  		return 0;
>>  	}
>>  
>
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Matthew Wilcox 2 months, 1 week ago
On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
> On 7/25/25 08:49, Li Qiong wrote:
> > For debugging, object_err() prints free pointer of the object.
> > However, if check_valid_pointer() returns false for a object,
> > dereferncing `object + s->offset` can lead to a crash. Therefore,
> > print the object's address in such cases.

I don't know where this patch came from (was it cc'd to linux-mm? i
don't see it)

> >  
> > +/*
> > + * object - should be a valid object.
> > + * check_valid_pointer(s, slab, object) should be true.
> > + */

This comment is very confusing.  It tries to ape kernel-doc style,
but if it were kernel-doc, the word before the hyphen should be the name
of the function, and it isn't.  If we did use kernel-doc for this, we'd
use @object to denote that we're documenting the argument.

But I don't see the need to pretend this is related to kernel-doc.  This
would be better:

/*
 * 'object' must be a valid pointer into this slab.  ie
 * check_valid_pointer() would return true
 */

I'm sure better wording for that is possible ...

> >  	if (!check_valid_pointer(s, slab, object)) {
> > -		object_err(s, slab, object, "Freelist Pointer check fails");
> > +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
> >  		return 0;

No, the error message is now wrong.  It's not an object, it's the
freelist pointer.

		slab_err(s, slab, "Invalid freelist pointer %p", object);

(the 0x%p is wrong because it will print 0x twice)

But I think there are even more things wrong here.  Like slab_err() is
not nerely as severe as slab_bug(), which is what used to be called.
And object_err() adds a taint, which this skips.

Altogether, this is a poorly thought out patch and should be dropped.
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Harry Yoo 2 months, 1 week ago
On Fri, Jul 25, 2025 at 06:10:51PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
> > On 7/25/25 08:49, Li Qiong wrote:
> > > For debugging, object_err() prints free pointer of the object.
> > > However, if check_valid_pointer() returns false for a object,
> > > dereferncing `object + s->offset` can lead to a crash. Therefore,
> > > print the object's address in such cases.
> 
> I don't know where this patch came from (was it cc'd to linux-mm? i
> don't see it)

https://lore.kernel.org/all/20250725024854.1201926-1-liqiong@nfschina.com

Looks like it's rejected by linux-mm for some reason..

> > > +/*
> > > + * object - should be a valid object.
> > > + * check_valid_pointer(s, slab, object) should be true.
> > > + */
> 
> This comment is very confusing.  It tries to ape kernel-doc style,
> but if it were kernel-doc, the word before the hyphen should be the name
> of the function, and it isn't.  If we did use kernel-doc for this, we'd
> use @object to denote that we're documenting the argument.

Yes, the comment is indeed confusing and agree with your point.

When I suggested it I expected adding something like:

  /* print_trailer() may deref invalid freepointer if object pointer is invalid */
  WARN_ON_ONCE(!check_valid_pointer(s, slab, object));

to be added to object_err().

> But I don't see the need to pretend this is related to kernel-doc.  This
> would be better:
>
> /*
>  * 'object' must be a valid pointer into this slab.  ie
>  * check_valid_pointer() would return true
>  */
> 
> I'm sure better wording for that is possible ...
>
> > >  	if (!check_valid_pointer(s, slab, object)) {
> > > -		object_err(s, slab, object, "Freelist Pointer check fails");
> > > +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
> > >  		return 0;
> 
> No, the error message is now wrong.  It's not an object, it's the
> freelist pointer.

Because it's the object is about to be allocated, it will look like
this:

  object pointer -> obj: [ garbage ][   freelist pointer   ][ garbage ]

SLUB uses check_valid_pointer() to check either 1) freelist pointer of
an object is valid (e.g. in check_object()), or 2) an object pointer
points to a valid address (e.g. in free_debug_processing()).

In this case it's an object pointer, not a freelist pointer.
Or am I misunderstanding something?

> 		slab_err(s, slab, "Invalid freelist pointer %p", object);
> 
> (the 0x%p is wrong because it will print 0x twice)

"0x%p" is used all over the place in mm/slub.c.

In the printk documentation [1]:
> Plain Pointers
> %p      abcdef12 or 00000000abcdef12

0x%p should be 0xabcdef12 or 0x00000000abcdef12, no?

[1] https://www.kernel.org/doc/html/next/core-api/printk-formats.html#printk-specifiers

> But I think there are even more things wrong here.  Like slab_err() is
> not nerely as severe as slab_bug(), which is what used to be called.

What do you mean by slab_err() is not as severe as slab_bug()?
Both object_err() and slab_err() add a taint and trigger a WARNING.

> And object_err() adds a taint, which this skips.

adding a taint is done via
slab_err()->__slab_err()->add_taint()

-- 
Cheers,
Harry / Hyeonggon
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Harry Yoo 2 months, 1 week ago
On Sat, Jul 26, 2025 at 04:55:06AM +0900, Harry Yoo wrote:
> On Fri, Jul 25, 2025 at 06:10:51PM +0100, Matthew Wilcox wrote:
> > On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
> > > On 7/25/25 08:49, Li Qiong wrote:
> > > > For debugging, object_err() prints free pointer of the object.
> > > > However, if check_valid_pointer() returns false for a object,
> > > > dereferncing `object + s->offset` can lead to a crash. Therefore,
> > > > print the object's address in such cases.
> > 
> > > >  	if (!check_valid_pointer(s, slab, object)) {
> > > > -		object_err(s, slab, object, "Freelist Pointer check fails");
> > > > +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
> > > >  		return 0;
> > 
> > No, the error message is now wrong.  It's not an object, it's the
> > freelist pointer.
> 
> Because it's the object is about to be allocated, it will look like
> this:
> 
>   object pointer -> obj: [ garbage ][   freelist pointer   ][ garbage ]
> 
> SLUB uses check_valid_pointer() to check either 1) freelist pointer of
> an object is valid (e.g. in check_object()), or 2) an object pointer
> points to a valid address (e.g. in free_debug_processing()).
> 
> In this case it's an object pointer, not a freelist pointer.
> Or am I misunderstanding something?

Actually, in alloc_debug_processing() the pointer came from slab->freelist,
so I think saying either "invalid freelist pointer" or
"invalid object pointer" make sense...

-- 
Cheers,
Harry / Hyeonggon
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by liqiong 2 months, 1 week ago

在 2025/7/26 07:00, Harry Yoo 写道:
> On Sat, Jul 26, 2025 at 04:55:06AM +0900, Harry Yoo wrote:
>> On Fri, Jul 25, 2025 at 06:10:51PM +0100, Matthew Wilcox wrote:
>>> On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
>>>> On 7/25/25 08:49, Li Qiong wrote:
>>>>> For debugging, object_err() prints free pointer of the object.
>>>>> However, if check_valid_pointer() returns false for a object,
>>>>> dereferncing `object + s->offset` can lead to a crash. Therefore,
>>>>> print the object's address in such cases.
>>>>>  	if (!check_valid_pointer(s, slab, object)) {
>>>>> -		object_err(s, slab, object, "Freelist Pointer check fails");
>>>>> +		slab_err(s, slab, "Invalid object pointer 0x%p", object);
>>>>>  		return 0;
>>> No, the error message is now wrong.  It's not an object, it's the
>>> freelist pointer.
>> Because it's the object is about to be allocated, it will look like
>> this:
>>
>>   object pointer -> obj: [ garbage ][   freelist pointer   ][ garbage ]
>>
>> SLUB uses check_valid_pointer() to check either 1) freelist pointer of
>> an object is valid (e.g. in check_object()), or 2) an object pointer
>> points to a valid address (e.g. in free_debug_processing()).
>>
>> In this case it's an object pointer, not a freelist pointer.
>> Or am I misunderstanding something?
> Actually, in alloc_debug_processing() the pointer came from slab->freelist,
> so I think saying either "invalid freelist pointer" or
> "invalid object pointer" make sense...

free_consistency_checks()  has 
 'slab_err(s, slab, "Invalid object pointer 0x%p", object);'
Maybe  it is better, alloc_consisency_checks() has the same  message.





>

Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Matthew Wilcox 2 months, 1 week ago
On Mon, Jul 28, 2025 at 10:06:42AM +0800, liqiong wrote:
> >> In this case it's an object pointer, not a freelist pointer.
> >> Or am I misunderstanding something?
> > Actually, in alloc_debug_processing() the pointer came from slab->freelist,
> > so I think saying either "invalid freelist pointer" or
> > "invalid object pointer" make sense...
> 
> free_consistency_checks()  has 
>  'slab_err(s, slab, "Invalid object pointer 0x%p", object);'
> Maybe  it is better, alloc_consisency_checks() has the same  message.

No.  Think about it.
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Harry Yoo 2 months, 1 week ago
On Mon, Jul 28, 2025 at 04:29:22AM +0100, Matthew Wilcox wrote:
> On Mon, Jul 28, 2025 at 10:06:42AM +0800, liqiong wrote:
> > >> In this case it's an object pointer, not a freelist pointer.
> > >> Or am I misunderstanding something?
> > > Actually, in alloc_debug_processing() the pointer came from slab->freelist,
> > > so I think saying either "invalid freelist pointer" or
> > > "invalid object pointer" make sense...
> > 
> > free_consistency_checks()  has 
> >  'slab_err(s, slab, "Invalid object pointer 0x%p", object);'
> > Maybe  it is better, alloc_consisency_checks() has the same  message.
> 
> No.  Think about it.

Haha, since I suggested that change, I feel like I have to rethink it
and respond... Maybe I'm wrong again, but I love to be proven wrong :)

On second thought,

Unlike free_consistency_checks() where an arbitrary address can be
passed, alloc_consistency_check() is not passed arbitrary addresses
but only addresses from the freelist. So if a pointer is invalid
there, it means the freelist pointer is invalid. And in all other
parts of slub.c, such cases are described as "Free(list) pointer",
or "Freechain" being invalid or corrupted.

So to stay consistent "Invalid freelist pointer" would be the right choice :)
Sorry for the confusion.

Anyway, Li, to make progress on this I think it make sense to start by making
object_err() resiliant against invalid pointers (as suggested by Matthew)?
If you go down that path, this patch might no longer be required to fix
the bug anyway...

And the change would be quite small. Most part of print_trailer() is printing
metadata and raw content of the object, which is risky when the pointer is
invalid. In that case we'd only want to print the address of the invalid
pointer and the information about slab (print_slab_info()) and nothing more.

-- 
Cheers,
Harry / Hyeonggon
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by liqiong 2 months, 1 week ago

在 2025/7/28 13:24, Harry Yoo 写道:
> On Mon, Jul 28, 2025 at 04:29:22AM +0100, Matthew Wilcox wrote:
>> On Mon, Jul 28, 2025 at 10:06:42AM +0800, liqiong wrote:
>>>>> In this case it's an object pointer, not a freelist pointer.
>>>>> Or am I misunderstanding something?
>>>> Actually, in alloc_debug_processing() the pointer came from slab->freelist,
>>>> so I think saying either "invalid freelist pointer" or
>>>> "invalid object pointer" make sense...
>>> free_consistency_checks()  has 
>>>  'slab_err(s, slab, "Invalid object pointer 0x%p", object);'
>>> Maybe  it is better, alloc_consisency_checks() has the same  message.
>> No.  Think about it.
> Haha, since I suggested that change, I feel like I have to rethink it
> and respond... Maybe I'm wrong again, but I love to be proven wrong :)
>
> On second thought,
>
> Unlike free_consistency_checks() where an arbitrary address can be
> passed, alloc_consistency_check() is not passed arbitrary addresses
> but only addresses from the freelist. So if a pointer is invalid
> there, it means the freelist pointer is invalid. And in all other
> parts of slub.c, such cases are described as "Free(list) pointer",
> or "Freechain" being invalid or corrupted.
>
> So to stay consistent "Invalid freelist pointer" would be the right choice :)
> Sorry for the confusion.
>
> Anyway, Li, to make progress on this I think it make sense to start by making
> object_err() resiliant against invalid pointers (as suggested by Matthew)?
> If you go down that path, this patch might no longer be required to fix
> the bug anyway...
>
> And the change would be quite small. Most part of print_trailer() is printing
> metadata and raw content of the object, which is risky when the pointer is
> invalid. In that case we'd only want to print the address of the invalid
> pointer and the information about slab (print_slab_info()) and nothing more.
>

Got it, I will a v3 patch, changing the message, and keep it simple, dropping the comments of object_err(),
just fix the issue.



Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Harry Yoo 2 months, 1 week ago
On Mon, Jul 28, 2025 at 05:08:57PM +0800, liqiong wrote:
> 
> 
> 在 2025/7/28 13:24, Harry Yoo 写道:
> > On Mon, Jul 28, 2025 at 04:29:22AM +0100, Matthew Wilcox wrote:
> >> On Mon, Jul 28, 2025 at 10:06:42AM +0800, liqiong wrote:
> >>>>> In this case it's an object pointer, not a freelist pointer.
> >>>>> Or am I misunderstanding something?
> >>>> Actually, in alloc_debug_processing() the pointer came from slab->freelist,
> >>>> so I think saying either "invalid freelist pointer" or
> >>>> "invalid object pointer" make sense...
> >>> free_consistency_checks()  has 
> >>>  'slab_err(s, slab, "Invalid object pointer 0x%p", object);'
> >>> Maybe  it is better, alloc_consisency_checks() has the same  message.
> >> No.  Think about it.
> > Haha, since I suggested that change, I feel like I have to rethink it
> > and respond... Maybe I'm wrong again, but I love to be proven wrong :)
> >
> > On second thought,
> >
> > Unlike free_consistency_checks() where an arbitrary address can be
> > passed, alloc_consistency_check() is not passed arbitrary addresses
> > but only addresses from the freelist. So if a pointer is invalid
> > there, it means the freelist pointer is invalid. And in all other
> > parts of slub.c, such cases are described as "Free(list) pointer",
> > or "Freechain" being invalid or corrupted.
> >
> > So to stay consistent "Invalid freelist pointer" would be the right choice :)
> > Sorry for the confusion.
> >
> > Anyway, Li, to make progress on this I think it make sense to start by making
> > object_err() resiliant against invalid pointers (as suggested by Matthew)?
> > If you go down that path, this patch might no longer be required to fix
> > the bug anyway...
> >
> > And the change would be quite small. Most part of print_trailer() is printing
> > metadata and raw content of the object, which is risky when the pointer is
> > invalid. In that case we'd only want to print the address of the invalid
> > pointer and the information about slab (print_slab_info()) and nothing more.
> >
> 
> Got it, I will a v3 patch, changing the message, and keep it simple,
> dropping the comments of object_err(), just fix the issue.

Well, I was saying let's start from making object_err() against wild
pointers [1] per Matthew's suggestion.

And with that this patch won't be necessary to fix the issue and will be
more robust against similar mistakes like this?

[1] https://lore.kernel.org/linux-mm/aIPZXSnkDF5r-PR5@casper.infradead.org

-- 
Cheers,
Harry / Hyeonggon
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Matthew Wilcox 2 months, 1 week ago
On Fri, Jul 25, 2025 at 06:10:51PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
> > On 7/25/25 08:49, Li Qiong wrote:
> > > For debugging, object_err() prints free pointer of the object.
> > > However, if check_valid_pointer() returns false for a object,
> > > dereferncing `object + s->offset` can lead to a crash. Therefore,
> > > print the object's address in such cases.
> 
> I don't know where this patch came from (was it cc'd to linux-mm? i
> don't see it)

I've spent some more time thinking about this and I now believe that
there are several calls to object_err() that can be passed a bad
pointer:

freelist_corrupted()
check_object()
on_freelist()
alloc_consistency_checks()
free_consistency_checks()

so I think this line of attack is inappropriate.  Instead, I think we
need to make object_err() resilient against wild pointers.  Specifically,
avoid doing risky things in print_trailer() if object is not within slab.
Re: [PATCH v2] mm: slub: avoid deref of free pointer in sanity checks if object is invalid
Posted by Harry Yoo 2 months, 1 week ago
On Fri, Jul 25, 2025 at 08:22:05PM +0100, Matthew Wilcox wrote:
> On Fri, Jul 25, 2025 at 06:10:51PM +0100, Matthew Wilcox wrote:
> > On Fri, Jul 25, 2025 at 06:47:01PM +0200, Vlastimil Babka wrote:
> > > On 7/25/25 08:49, Li Qiong wrote:
> > > > For debugging, object_err() prints free pointer of the object.
> > > > However, if check_valid_pointer() returns false for a object,
> > > > dereferncing `object + s->offset` can lead to a crash. Therefore,
> > > > print the object's address in such cases.
> > 
> > I don't know where this patch came from (was it cc'd to linux-mm? i
> > don't see it)

Oops, I missed this email when I was replying to the previous email.

> I've spent some more time thinking about this and I now believe that
> there are several calls to object_err() that can be passed a bad
> pointer:
> 
> freelist_corrupted()
> check_object()
> on_freelist()
> alloc_consistency_checks()
> free_consistency_checks()
> 
> so I think this line of attack is inappropriate. Instead, I think we
> need to make object_err() resilient against wild pointers.  Specifically,
> avoid doing risky things in print_trailer() if object is not within slab.

Making object_err() more resilient sounds good to me.

-- 
Cheers,
Harry / Hyeonggon