From: Rafael Aquini <aquini@redhat.com>
To: Waiman Long <longman@redhat.com>
Cc: Christoph Lameter <cl@linux.com>,
Pekka Enberg <penberg@kernel.org>,
David Rientjes <rientjes@google.com>,
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
Andrew Morton <akpm@linux-foundation.org>,
Kees Cook <keescook@chromium.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Changbin Du <changbin.du@gmail.com>,
Matthew Wilcox <willy@infradead.org>,
Markus Elfring <Markus.Elfring@web.de>
Subject: Re: [PATCH v3] mm/slub: Fix incorrect interpretation of s->offset
Date: Fri, 1 May 2020 17:29:12 -0400 [thread overview]
Message-ID: <20200501212912.GC27720@optiplex-lnx> (raw)
In-Reply-To: <20200429135328.26976-1-longman@redhat.com>
On Wed, Apr 29, 2020 at 09:53:28AM -0400, Waiman Long wrote:
> In a couple of places in the slub memory allocator, the code uses
> "s->offset" as a check to see if the free pointer is put right after the
> object. That check is no longer true with commit 3202fa62fb43 ("slub:
> relocate freelist pointer to middle of object").
>
> As a result, echoing "1" into the validate sysfs file, e.g. of dentry,
> may cause a bunch of "Freepointer corrupt" error reports like the
> following to appear with the system in panic afterwards.
>
> [ 38.579769] =============================================================================
> [ 38.580845] BUG dentry(666:pmcd.service) (Tainted: G B): Freepointer corrupt
> [ 38.581948] -----------------------------------------------------------------------------
>
> To fix it, use the check "s->offset == s->inuse" in the new helper
> function freeptr_outside_object() instead. Also add another helper function
> get_info_end() to return the end of info block (inuse + free pointer
> if not overlapping with object).
>
> Fixes: 3202fa62fb43 ("slub: relocate freelist pointer to middle of object")
> Signed-off-by: Waiman Long <longman@redhat.com>
> ---
> mm/slub.c | 45 ++++++++++++++++++++++++++++++---------------
> 1 file changed, 30 insertions(+), 15 deletions(-)
>
> [v3: Change function name to freeptr_outside_object(), update check & add comment]
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 9bf44955c4f1..b762450fc9f0 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -551,15 +551,32 @@ static void print_section(char *level, char *text, u8 *addr,
> metadata_access_disable();
> }
>
> +/*
> + * See comment in calculate_sizes().
> + */
> +static inline bool freeptr_outside_object(struct kmem_cache *s)
> +{
> + return s->offset >= s->inuse;
> +}
> +
> +/*
> + * Return offset of the end of info block which is inuse + free pointer if
> + * not overlapping with object.
> + */
> +static inline unsigned int get_info_end(struct kmem_cache *s)
> +{
> + if (freeptr_outside_object(s))
> + return s->inuse + sizeof(void *);
> + else
> + return s->inuse;
> +}
> +
> static struct track *get_track(struct kmem_cache *s, void *object,
> enum track_item alloc)
> {
> struct track *p;
>
> - if (s->offset)
> - p = object + s->offset + sizeof(void *);
> - else
> - p = object + s->inuse;
> + p = object + get_info_end(s);
>
> return p + alloc;
> }
> @@ -686,10 +703,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
> print_section(KERN_ERR, "Redzone ", p + s->object_size,
> s->inuse - s->object_size);
>
> - if (s->offset)
> - off = s->offset + sizeof(void *);
> - else
> - off = s->inuse;
> + off = get_info_end(s);
>
> if (s->flags & SLAB_STORE_USER)
> off += 2 * sizeof(struct track);
> @@ -782,7 +796,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
> * object address
> * Bytes of the object to be managed.
> * If the freepointer may overlay the object then the free
> - * pointer is the first word of the object.
> + * pointer is at the middle of the object.
> *
> * Poisoning uses 0x6b (POISON_FREE) and the last byte is
> * 0xa5 (POISON_END)
> @@ -816,11 +830,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
>
> static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
> {
> - unsigned long off = s->inuse; /* The end of info */
> -
> - if (s->offset)
> - /* Freepointer is placed after the object. */
> - off += sizeof(void *);
> + unsigned long off = get_info_end(s); /* The end of info */
>
> if (s->flags & SLAB_STORE_USER)
> /* We also have user information there */
> @@ -907,7 +917,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
> check_pad_bytes(s, page, p);
> }
>
> - if (!s->offset && val == SLUB_RED_ACTIVE)
> + if (!freeptr_outside_object(s) && val == SLUB_RED_ACTIVE)
> /*
> * Object and freepointer overlap. Cannot check
> * freepointer while object is allocated.
> @@ -3587,6 +3597,11 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
> *
> * This is the case if we do RCU, have a constructor or
> * destructor or are poisoning the objects.
> + *
> + * The assumption that s->offset >= s->inuse means free
> + * pointer is outside of the object is used in the
> + * freeptr_outside_object() function. If that is no
> + * longer true, the function needs to be modified.
> */
> s->offset = size;
> size += sizeof(void *);
> --
> 2.18.1
>
>
Acked-by: Rafael Aquini <aquini@redhat.com>
next prev parent reply other threads:[~2020-05-01 21:29 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-29 13:53 [PATCH v3] mm/slub: Fix incorrect interpretation of s->offset Waiman Long
2020-04-29 13:55 ` Waiman Long
2020-04-29 15:54 ` Matthew Wilcox
2020-04-29 16:42 ` Markus Elfring
2020-04-29 18:25 ` Matthew Wilcox
2020-05-01 21:29 ` Rafael Aquini [this message]
2020-05-01 22:01 ` Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200501212912.GC27720@optiplex-lnx \
--to=aquini@redhat.com \
--cc=Markus.Elfring@web.de \
--cc=akpm@linux-foundation.org \
--cc=changbin.du@gmail.com \
--cc=cl@linux.com \
--cc=iamjoonsoo.kim@lge.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=longman@redhat.com \
--cc=penberg@kernel.org \
--cc=rientjes@google.com \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.