linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: llvm@lists.linux.dev
Cc: Kees Cook <keescook@chromium.org>, Marco Elver <elver@google.com>,
	Pekka Enberg <penberg@kernel.org>,
	David Rientjes <rientjes@google.com>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Vlastimil Babka <vbabka@suse.cz>,
	linux-mm@kvack.org, stable@vger.kernel.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	Christoph Lameter <cl@linux.com>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Daniel Micay <danielmicay@gmail.com>,
	linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: [PATCH] mm: Handle ksize() vs __alloc_size by forgetting size
Date: Fri, 25 Feb 2022 14:16:25 -0800	[thread overview]
Message-ID: <20220225221625.3531852-1-keescook@chromium.org> (raw)

If ksize() is used on an allocation, the compiler cannot make any
assumptions about its size any more (as hinted by __alloc_size). Force
it to forget.

One caller was using a container_of() construction that needed to be
worked around.

Cc: Marco Elver <elver@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: linux-mm@kvack.org
Link: https://github.com/ClangBuiltLinux/linux/issues/1599
Fixes: c37495d6254c ("slab: add __alloc_size attributes for better bounds checking")
Cc: stable@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
This appears to work for me, but I'm waiting for more feedback on
the specific instance got tripped over in Android.
---
 drivers/base/devres.c |  4 +++-
 include/linux/slab.h  | 26 +++++++++++++++++++++++++-
 mm/slab_common.c      | 19 +++----------------
 3 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index eaa9a5cd1db9..1a2645bd7234 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -855,6 +855,7 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
 	size_t total_new_size, total_old_size;
 	struct devres *old_dr, *new_dr;
 	unsigned long flags;
+	void *allocation;
 
 	if (unlikely(!new_size)) {
 		devm_kfree(dev, ptr);
@@ -874,7 +875,8 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
 	if (!check_dr_size(new_size, &total_new_size))
 		return NULL;
 
-	total_old_size = ksize(container_of(ptr, struct devres, data));
+	allocation = container_of(ptr, struct devres, data);
+	total_old_size = ksize(allocation);
 	if (total_old_size == 0) {
 		WARN(1, "Pointer doesn't point to dynamically allocated memory.");
 		return NULL;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 37bde99b74af..a14f3bfa2f44 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -182,8 +182,32 @@ int kmem_cache_shrink(struct kmem_cache *s);
 void * __must_check krealloc(const void *objp, size_t new_size, gfp_t flags) __alloc_size(2);
 void kfree(const void *objp);
 void kfree_sensitive(const void *objp);
+
+/**
+ * ksize - get the actual amount of memory allocated for a given object
+ * @objp: Pointer to the object
+ *
+ * kmalloc may internally round up allocations and return more memory
+ * than requested. ksize() can be used to determine the actual amount of
+ * memory allocated. The caller may use this additional memory, even though
+ * a smaller amount of memory was initially specified with the kmalloc call.
+ * The caller must guarantee that objp points to a valid object previously
+ * allocated with either kmalloc() or kmem_cache_alloc(). The object
+ * must not be freed during the duration of the call.
+ *
+ * Return: size of the actual memory used by @objp in bytes
+ */
+#define ksize(objp) ({							\
+	/*								\
+	 * Getting the actual allocation size means the __alloc_size	\
+	 * hints are no longer valid, and the compiler needs to		\
+	 * forget about them.						\
+	 */								\
+	OPTIMIZER_HIDE_VAR(objp);					\
+	_ksize(objp);							\
+})
 size_t __ksize(const void *objp);
-size_t ksize(const void *objp);
+size_t _ksize(const void *objp);
 #ifdef CONFIG_PRINTK
 bool kmem_valid_obj(void *object);
 void kmem_dump_obj(void *object);
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 23f2ab0713b7..ba5fa8481396 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1245,21 +1245,8 @@ void kfree_sensitive(const void *p)
 }
 EXPORT_SYMBOL(kfree_sensitive);
 
-/**
- * ksize - get the actual amount of memory allocated for a given object
- * @objp: Pointer to the object
- *
- * kmalloc may internally round up allocations and return more memory
- * than requested. ksize() can be used to determine the actual amount of
- * memory allocated. The caller may use this additional memory, even though
- * a smaller amount of memory was initially specified with the kmalloc call.
- * The caller must guarantee that objp points to a valid object previously
- * allocated with either kmalloc() or kmem_cache_alloc(). The object
- * must not be freed during the duration of the call.
- *
- * Return: size of the actual memory used by @objp in bytes
- */
-size_t ksize(const void *objp)
+/* Should not be called directly: use "ksize" macro wrapper. */
+size_t _ksize(const void *objp)
 {
 	size_t size;
 
@@ -1289,7 +1276,7 @@ size_t ksize(const void *objp)
 	kasan_unpoison_range(objp, size);
 	return size;
 }
-EXPORT_SYMBOL(ksize);
+EXPORT_SYMBOL(_ksize);
 
 /* Tracepoints definitions. */
 EXPORT_TRACEPOINT_SYMBOL(kmalloc);
-- 
2.30.2


             reply	other threads:[~2022-02-25 22:16 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-25 22:16 Kees Cook [this message]
2022-02-25 23:45 ` [PATCH] mm: Handle ksize() vs __alloc_size by forgetting size Andrew Morton
2022-02-28 23:16   ` Kees Cook
2022-02-28 11:24 ` Marco Elver
2022-02-28 14:30   ` Matthew Wilcox
2022-02-28 14:48   ` Daniel Micay
2022-02-28 15:15     ` Daniel Micay
2022-02-28 23:54   ` Kees Cook
2022-02-28 22:42 ` Nick Desaulniers

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=20220225221625.3531852-1-keescook@chromium.org \
    --to=keescook@chromium.org \
    --cc=akpm@linux-foundation.org \
    --cc=cl@linux.com \
    --cc=danielmicay@gmail.com \
    --cc=elver@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=llvm@lists.linux.dev \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=penberg@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rientjes@google.com \
    --cc=stable@vger.kernel.org \
    --cc=vbabka@suse.cz \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).