mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
mm, slab: ignore hardened usercopy parameters when disabled
With CONFIG_HARDENED_USERCOPY not enabled, there are no __check_heap_object() checks happening that would use the struct kmem_cache useroffset and usersize fields. Yet the fields are still initialized, preventing merging of otherwise compatible caches. Also the fields contribute to struct kmem_cache size unnecessarily when unused. Thus #ifdef them out completely when CONFIG_HARDENED_USERCOPY is disabled. In kmem_dump_obj() print object_size instead of usersize, as that's actually the intention. In a quick virtme boot test, this has reduced the number of caches in /proc/slabinfo from 131 to 111. Cc: Kees Cook <keescook@chromium.org> Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Roman Gushchin <roman.gushchin@linux.dev> Acked-by: Mike Rapoport <rppt@linux.ibm.com> Reviewed-by: Christoph Lameter <cl@linux.com>
This commit is contained in:
parent
c18c20f162
commit
346907ceb9
5 changed files with 18 additions and 5 deletions
|
@ -80,8 +80,10 @@ struct kmem_cache {
|
||||||
unsigned int *random_seq;
|
unsigned int *random_seq;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
unsigned int useroffset; /* Usercopy region offset */
|
unsigned int useroffset; /* Usercopy region offset */
|
||||||
unsigned int usersize; /* Usercopy region size */
|
unsigned int usersize; /* Usercopy region size */
|
||||||
|
#endif
|
||||||
|
|
||||||
struct kmem_cache_node *node[MAX_NUMNODES];
|
struct kmem_cache_node *node[MAX_NUMNODES];
|
||||||
};
|
};
|
||||||
|
|
|
@ -136,8 +136,10 @@ struct kmem_cache {
|
||||||
struct kasan_cache kasan_info;
|
struct kasan_cache kasan_info;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
unsigned int useroffset; /* Usercopy region offset */
|
unsigned int useroffset; /* Usercopy region offset */
|
||||||
unsigned int usersize; /* Usercopy region size */
|
unsigned int usersize; /* Usercopy region size */
|
||||||
|
#endif
|
||||||
|
|
||||||
struct kmem_cache_node *node[MAX_NUMNODES];
|
struct kmem_cache_node *node[MAX_NUMNODES];
|
||||||
};
|
};
|
||||||
|
|
|
@ -207,8 +207,6 @@ struct kmem_cache {
|
||||||
unsigned int size; /* The aligned/padded/added on size */
|
unsigned int size; /* The aligned/padded/added on size */
|
||||||
unsigned int align; /* Alignment as calculated */
|
unsigned int align; /* Alignment as calculated */
|
||||||
slab_flags_t flags; /* Active flags on the slab */
|
slab_flags_t flags; /* Active flags on the slab */
|
||||||
unsigned int useroffset;/* Usercopy region offset */
|
|
||||||
unsigned int usersize; /* Usercopy region size */
|
|
||||||
const char *name; /* Slab name for sysfs */
|
const char *name; /* Slab name for sysfs */
|
||||||
int refcount; /* Use counter */
|
int refcount; /* Use counter */
|
||||||
void (*ctor)(void *); /* Called on object slot creation */
|
void (*ctor)(void *); /* Called on object slot creation */
|
||||||
|
|
|
@ -143,8 +143,10 @@ int slab_unmergeable(struct kmem_cache *s)
|
||||||
if (s->ctor)
|
if (s->ctor)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
if (s->usersize)
|
if (s->usersize)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have set a slab to be unmergeable during bootstrap.
|
* We may have set a slab to be unmergeable during bootstrap.
|
||||||
|
@ -223,8 +225,10 @@ static struct kmem_cache *create_cache(const char *name,
|
||||||
s->size = s->object_size = object_size;
|
s->size = s->object_size = object_size;
|
||||||
s->align = align;
|
s->align = align;
|
||||||
s->ctor = ctor;
|
s->ctor = ctor;
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
s->useroffset = useroffset;
|
s->useroffset = useroffset;
|
||||||
s->usersize = usersize;
|
s->usersize = usersize;
|
||||||
|
#endif
|
||||||
|
|
||||||
err = __kmem_cache_create(s, flags);
|
err = __kmem_cache_create(s, flags);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -317,7 +321,8 @@ kmem_cache_create_usercopy(const char *name,
|
||||||
flags &= CACHE_CREATE_MASK;
|
flags &= CACHE_CREATE_MASK;
|
||||||
|
|
||||||
/* Fail closed on bad usersize of useroffset values. */
|
/* Fail closed on bad usersize of useroffset values. */
|
||||||
if (WARN_ON(!usersize && useroffset) ||
|
if (!IS_ENABLED(CONFIG_HARDENED_USERCOPY) ||
|
||||||
|
WARN_ON(!usersize && useroffset) ||
|
||||||
WARN_ON(size < usersize || size - usersize < useroffset))
|
WARN_ON(size < usersize || size - usersize < useroffset))
|
||||||
usersize = useroffset = 0;
|
usersize = useroffset = 0;
|
||||||
|
|
||||||
|
@ -595,8 +600,8 @@ void kmem_dump_obj(void *object)
|
||||||
ptroffset = ((char *)object - (char *)kp.kp_objp) - kp.kp_data_offset;
|
ptroffset = ((char *)object - (char *)kp.kp_objp) - kp.kp_data_offset;
|
||||||
pr_cont(" pointer offset %lu", ptroffset);
|
pr_cont(" pointer offset %lu", ptroffset);
|
||||||
}
|
}
|
||||||
if (kp.kp_slab_cache && kp.kp_slab_cache->usersize)
|
if (kp.kp_slab_cache && kp.kp_slab_cache->object_size)
|
||||||
pr_cont(" size %u", kp.kp_slab_cache->usersize);
|
pr_cont(" size %u", kp.kp_slab_cache->object_size);
|
||||||
if (kp.kp_ret)
|
if (kp.kp_ret)
|
||||||
pr_cont(" allocated at %pS\n", kp.kp_ret);
|
pr_cont(" allocated at %pS\n", kp.kp_ret);
|
||||||
else
|
else
|
||||||
|
@ -640,8 +645,10 @@ void __init create_boot_cache(struct kmem_cache *s, const char *name,
|
||||||
align = max(align, size);
|
align = max(align, size);
|
||||||
s->align = calculate_alignment(flags, align, size);
|
s->align = calculate_alignment(flags, align, size);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
s->useroffset = useroffset;
|
s->useroffset = useroffset;
|
||||||
s->usersize = usersize;
|
s->usersize = usersize;
|
||||||
|
#endif
|
||||||
|
|
||||||
err = __kmem_cache_create(s, flags);
|
err = __kmem_cache_create(s, flags);
|
||||||
|
|
||||||
|
|
|
@ -5502,11 +5502,13 @@ static ssize_t cache_dma_show(struct kmem_cache *s, char *buf)
|
||||||
SLAB_ATTR_RO(cache_dma);
|
SLAB_ATTR_RO(cache_dma);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
static ssize_t usersize_show(struct kmem_cache *s, char *buf)
|
static ssize_t usersize_show(struct kmem_cache *s, char *buf)
|
||||||
{
|
{
|
||||||
return sysfs_emit(buf, "%u\n", s->usersize);
|
return sysfs_emit(buf, "%u\n", s->usersize);
|
||||||
}
|
}
|
||||||
SLAB_ATTR_RO(usersize);
|
SLAB_ATTR_RO(usersize);
|
||||||
|
#endif
|
||||||
|
|
||||||
static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
|
static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -5803,7 +5805,9 @@ static struct attribute *slab_attrs[] = {
|
||||||
#ifdef CONFIG_FAILSLAB
|
#ifdef CONFIG_FAILSLAB
|
||||||
&failslab_attr.attr,
|
&failslab_attr.attr,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
&usersize_attr.attr,
|
&usersize_attr.attr,
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_KFENCE
|
#ifdef CONFIG_KFENCE
|
||||||
&skip_kfence_attr.attr,
|
&skip_kfence_attr.attr,
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue