Skip to content

Commit 6e48a96

Browse files
Matthew Wilcox (Oracle)tehcaster
authored andcommitted
mm/kasan: Convert to struct folio and struct slab
KASAN accesses some slab related struct page fields so we need to convert it to struct slab. Some places are a bit simplified thanks to kasan_addr_to_slab() encapsulating the PageSlab flag check through virt_to_slab(). When resolving object address to either a real slab or a large kmalloc, use struct folio as the intermediate type for testing the slab flag to avoid unnecessary implicit compound_head(). [ [email protected]: use struct folio, adjust to differences in previous patches ] Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]> Reviewed-by: Andrey Konovalov <[email protected]> Reviewed-by: Roman Gushchin <[email protected]> Tested-by: Hyeongogn Yoo <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Andrey Konovalov <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: <[email protected]>
1 parent 5075701 commit 6e48a96

File tree

9 files changed

+42
-28
lines changed

9 files changed

+42
-28
lines changed

include/linux/kasan.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
struct kmem_cache;
1111
struct page;
12+
struct slab;
1213
struct vm_struct;
1314
struct task_struct;
1415

@@ -193,11 +194,11 @@ static __always_inline size_t kasan_metadata_size(struct kmem_cache *cache)
193194
return 0;
194195
}
195196

196-
void __kasan_poison_slab(struct page *page);
197-
static __always_inline void kasan_poison_slab(struct page *page)
197+
void __kasan_poison_slab(struct slab *slab);
198+
static __always_inline void kasan_poison_slab(struct slab *slab)
198199
{
199200
if (kasan_enabled())
200-
__kasan_poison_slab(page);
201+
__kasan_poison_slab(slab);
201202
}
202203

203204
void __kasan_unpoison_object_data(struct kmem_cache *cache, void *object);
@@ -322,7 +323,7 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
322323
slab_flags_t *flags) {}
323324
static inline void kasan_cache_create_kmalloc(struct kmem_cache *cache) {}
324325
static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; }
325-
static inline void kasan_poison_slab(struct page *page) {}
326+
static inline void kasan_poison_slab(struct slab *slab) {}
326327
static inline void kasan_unpoison_object_data(struct kmem_cache *cache,
327328
void *object) {}
328329
static inline void kasan_poison_object_data(struct kmem_cache *cache,

mm/kasan/common.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ struct kasan_free_meta *kasan_get_free_meta(struct kmem_cache *cache,
247247
}
248248
#endif
249249

250-
void __kasan_poison_slab(struct page *page)
250+
void __kasan_poison_slab(struct slab *slab)
251251
{
252+
struct page *page = slab_page(slab);
252253
unsigned long i;
253254

254255
for (i = 0; i < compound_nr(page); i++)
@@ -401,22 +402,24 @@ void __kasan_kfree_large(void *ptr, unsigned long ip)
401402

402403
void __kasan_slab_free_mempool(void *ptr, unsigned long ip)
403404
{
404-
struct page *page;
405+
struct folio *folio;
405406

406-
page = virt_to_head_page(ptr);
407+
folio = virt_to_folio(ptr);
407408

408409
/*
409410
* Even though this function is only called for kmem_cache_alloc and
410411
* kmalloc backed mempool allocations, those allocations can still be
411412
* !PageSlab() when the size provided to kmalloc is larger than
412413
* KMALLOC_MAX_SIZE, and kmalloc falls back onto page_alloc.
413414
*/
414-
if (unlikely(!PageSlab(page))) {
415+
if (unlikely(!folio_test_slab(folio))) {
415416
if (____kasan_kfree_large(ptr, ip))
416417
return;
417-
kasan_poison(ptr, page_size(page), KASAN_FREE_PAGE, false);
418+
kasan_poison(ptr, folio_size(folio), KASAN_FREE_PAGE, false);
418419
} else {
419-
____kasan_slab_free(page->slab_cache, ptr, ip, false, false);
420+
struct slab *slab = folio_slab(folio);
421+
422+
____kasan_slab_free(slab->slab_cache, ptr, ip, false, false);
420423
}
421424
}
422425

@@ -560,7 +563,7 @@ void * __must_check __kasan_kmalloc_large(const void *ptr, size_t size,
560563

561564
void * __must_check __kasan_krealloc(const void *object, size_t size, gfp_t flags)
562565
{
563-
struct page *page;
566+
struct slab *slab;
564567

565568
if (unlikely(object == ZERO_SIZE_PTR))
566569
return (void *)object;
@@ -572,13 +575,13 @@ void * __must_check __kasan_krealloc(const void *object, size_t size, gfp_t flag
572575
*/
573576
kasan_unpoison(object, size, false);
574577

575-
page = virt_to_head_page(object);
578+
slab = virt_to_slab(object);
576579

577580
/* Piggy-back on kmalloc() instrumentation to poison the redzone. */
578-
if (unlikely(!PageSlab(page)))
581+
if (unlikely(!slab))
579582
return __kasan_kmalloc_large(object, size, flags);
580583
else
581-
return ____kasan_kmalloc(page->slab_cache, object, size, flags);
584+
return ____kasan_kmalloc(slab->slab_cache, object, size, flags);
582585
}
583586

584587
bool __kasan_check_byte(const void *address, unsigned long ip)

mm/kasan/generic.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,16 +330,16 @@ DEFINE_ASAN_SET_SHADOW(f8);
330330

331331
static void __kasan_record_aux_stack(void *addr, bool can_alloc)
332332
{
333-
struct page *page = kasan_addr_to_page(addr);
333+
struct slab *slab = kasan_addr_to_slab(addr);
334334
struct kmem_cache *cache;
335335
struct kasan_alloc_meta *alloc_meta;
336336
void *object;
337337

338-
if (is_kfence_address(addr) || !(page && PageSlab(page)))
338+
if (is_kfence_address(addr) || !slab)
339339
return;
340340

341-
cache = page->slab_cache;
342-
object = nearest_obj(cache, page_slab(page), addr);
341+
cache = slab->slab_cache;
342+
object = nearest_obj(cache, slab, addr);
343343
alloc_meta = kasan_get_alloc_meta(cache, object);
344344
if (!alloc_meta)
345345
return;

mm/kasan/kasan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ bool kasan_report(unsigned long addr, size_t size,
265265
void kasan_report_invalid_free(void *object, unsigned long ip);
266266

267267
struct page *kasan_addr_to_page(const void *addr);
268+
struct slab *kasan_addr_to_slab(const void *addr);
268269

269270
depot_stack_handle_t kasan_save_stack(gfp_t flags, bool can_alloc);
270271
void kasan_set_track(struct kasan_track *track, gfp_t flags);

mm/kasan/quarantine.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static unsigned long quarantine_batch_size;
117117

118118
static struct kmem_cache *qlink_to_cache(struct qlist_node *qlink)
119119
{
120-
return virt_to_head_page(qlink)->slab_cache;
120+
return virt_to_slab(qlink)->slab_cache;
121121
}
122122

123123
static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache)

mm/kasan/report.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ struct page *kasan_addr_to_page(const void *addr)
150150
return NULL;
151151
}
152152

153+
struct slab *kasan_addr_to_slab(const void *addr)
154+
{
155+
if ((addr >= (void *)PAGE_OFFSET) &&
156+
(addr < high_memory))
157+
return virt_to_slab(addr);
158+
return NULL;
159+
}
160+
153161
static void describe_object_addr(struct kmem_cache *cache, void *object,
154162
const void *addr)
155163
{
@@ -248,8 +256,9 @@ static void print_address_description(void *addr, u8 tag)
248256
pr_err("\n");
249257

250258
if (page && PageSlab(page)) {
251-
struct kmem_cache *cache = page->slab_cache;
252-
void *object = nearest_obj(cache, page_slab(page), addr);
259+
struct slab *slab = page_slab(page);
260+
struct kmem_cache *cache = slab->slab_cache;
261+
void *object = nearest_obj(cache, slab, addr);
253262

254263
describe_object(cache, object, addr, tag);
255264
}

mm/kasan/report_tags.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ const char *kasan_get_bug_type(struct kasan_access_info *info)
1212
#ifdef CONFIG_KASAN_TAGS_IDENTIFY
1313
struct kasan_alloc_meta *alloc_meta;
1414
struct kmem_cache *cache;
15-
struct page *page;
15+
struct slab *slab;
1616
const void *addr;
1717
void *object;
1818
u8 tag;
1919
int i;
2020

2121
tag = get_tag(info->access_addr);
2222
addr = kasan_reset_tag(info->access_addr);
23-
page = kasan_addr_to_page(addr);
24-
if (page && PageSlab(page)) {
25-
cache = page->slab_cache;
26-
object = nearest_obj(cache, page_slab(page), (void *)addr);
23+
slab = kasan_addr_to_slab(addr);
24+
if (slab) {
25+
cache = slab->slab_cache;
26+
object = nearest_obj(cache, slab, (void *)addr);
2727
alloc_meta = kasan_get_alloc_meta(cache, object);
2828

2929
if (alloc_meta) {

mm/slab.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2604,7 +2604,7 @@ static struct slab *cache_grow_begin(struct kmem_cache *cachep,
26042604
* page_address() in the latter returns a non-tagged pointer,
26052605
* as it should be for slab pages.
26062606
*/
2607-
kasan_poison_slab(slab_page(slab));
2607+
kasan_poison_slab(slab);
26082608

26092609
/* Get slab management. */
26102610
freelist = alloc_slabmgmt(cachep, slab, offset,

mm/slub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1961,7 +1961,7 @@ static struct slab *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
19611961

19621962
slab->slab_cache = s;
19631963

1964-
kasan_poison_slab(slab_page(slab));
1964+
kasan_poison_slab(slab);
19651965

19661966
start = slab_address(slab);
19671967

0 commit comments

Comments
 (0)