Commit 1c84724c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'slab-fixes-for-6.6-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab

Pull slab fixes from Vlastimil Babka:

 - stable fix to prevent list corruption when destroying caches with
   leftover objects (Rafael Aquini)

 - fix for a gotcha in kmalloc_size_roundup() when calling it with too
   high size, discovered when recently a networking call site had to be
   fixed for a different issue (David Laight)

* tag 'slab-fixes-for-6.6-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab:
  slab: kmalloc_size_roundup() must not return 0 for non-zero size
  mm/slab_common: fix slab_caches list corruption after kmem_cache_destroy()
parents 6edc84bc 8446a4de
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -479,7 +479,7 @@ void slab_kmem_cache_release(struct kmem_cache *s)

void kmem_cache_destroy(struct kmem_cache *s)
{
	int refcnt;
	int err = -EBUSY;
	bool rcu_set;

	if (unlikely(!s) || !kasan_check_byte(s))
@@ -490,17 +490,17 @@ void kmem_cache_destroy(struct kmem_cache *s)

	rcu_set = s->flags & SLAB_TYPESAFE_BY_RCU;

	refcnt = --s->refcount;
	if (refcnt)
	s->refcount--;
	if (s->refcount)
		goto out_unlock;

	WARN(shutdown_cache(s),
	     "%s %s: Slab cache still has objects when called from %pS",
	err = shutdown_cache(s);
	WARN(err, "%s %s: Slab cache still has objects when called from %pS",
	     __func__, s->name, (void *)_RET_IP_);
out_unlock:
	mutex_unlock(&slab_mutex);
	cpus_read_unlock();
	if (!refcnt && !rcu_set)
	if (!err && !rcu_set)
		kmem_cache_release(s);
}
EXPORT_SYMBOL(kmem_cache_destroy);
@@ -745,24 +745,24 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags, unsigned long caller)

size_t kmalloc_size_roundup(size_t size)
{
	struct kmem_cache *c;
	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.
		 */
		return kmalloc_slab(size, GFP_KERNEL, 0)->object_size;
	}

	/* 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;
	/* 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);