1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 20b24beccSAndrey Ryabinin #ifndef _LINUX_KASAN_H 30b24beccSAndrey Ryabinin #define _LINUX_KASAN_H 40b24beccSAndrey Ryabinin 50b24beccSAndrey Ryabinin #include <linux/types.h> 60b24beccSAndrey Ryabinin 70b24beccSAndrey Ryabinin struct kmem_cache; 80b24beccSAndrey Ryabinin struct page; 9a5af5aa8SAndrey Ryabinin struct vm_struct; 105be9b730SMasami Hiramatsu struct task_struct; 110b24beccSAndrey Ryabinin 120b24beccSAndrey Ryabinin #ifdef CONFIG_KASAN 130b24beccSAndrey Ryabinin 14d5750edfSAndrey Konovalov #include <linux/linkage.h> 1565fddcfcSMike Rapoport #include <asm/kasan.h> 160b24beccSAndrey Ryabinin 1783c4e7a0SPatricia Alfonso /* kasan_data struct is used in KUnit tests for KASAN expected failures */ 1883c4e7a0SPatricia Alfonso struct kunit_kasan_expectation { 1983c4e7a0SPatricia Alfonso bool report_expected; 2083c4e7a0SPatricia Alfonso bool report_found; 2183c4e7a0SPatricia Alfonso }; 2283c4e7a0SPatricia Alfonso 23d5750edfSAndrey Konovalov #endif 24d5750edfSAndrey Konovalov 25d5750edfSAndrey Konovalov #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 26d5750edfSAndrey Konovalov 27d5750edfSAndrey Konovalov #include <linux/pgtable.h> 28d5750edfSAndrey Konovalov 29d5750edfSAndrey Konovalov /* Software KASAN implementations use shadow memory. */ 30d5750edfSAndrey Konovalov 31d5750edfSAndrey Konovalov #ifdef CONFIG_KASAN_SW_TAGS 32d5750edfSAndrey Konovalov #define KASAN_SHADOW_INIT 0xFF 33d5750edfSAndrey Konovalov #else 34d5750edfSAndrey Konovalov #define KASAN_SHADOW_INIT 0 35d5750edfSAndrey Konovalov #endif 36d5750edfSAndrey Konovalov 379577dd74SAndrey Konovalov extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; 389577dd74SAndrey Konovalov extern pte_t kasan_early_shadow_pte[PTRS_PER_PTE]; 399577dd74SAndrey Konovalov extern pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD]; 409577dd74SAndrey Konovalov extern pud_t kasan_early_shadow_pud[PTRS_PER_PUD]; 419577dd74SAndrey Konovalov extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D]; 4269786cdbSAndrey Ryabinin 439577dd74SAndrey Konovalov int kasan_populate_early_shadow(const void *shadow_start, 4469786cdbSAndrey Ryabinin const void *shadow_end); 4569786cdbSAndrey Ryabinin 460b24beccSAndrey Ryabinin static inline void *kasan_mem_to_shadow(const void *addr) 470b24beccSAndrey Ryabinin { 480b24beccSAndrey Ryabinin return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT) 490b24beccSAndrey Ryabinin + KASAN_SHADOW_OFFSET; 500b24beccSAndrey Ryabinin } 510b24beccSAndrey Ryabinin 52d5750edfSAndrey Konovalov int kasan_add_zero_shadow(void *start, unsigned long size); 53d5750edfSAndrey Konovalov void kasan_remove_zero_shadow(void *start, unsigned long size); 54d5750edfSAndrey Konovalov 55d5750edfSAndrey Konovalov #else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ 56d5750edfSAndrey Konovalov 57d5750edfSAndrey Konovalov static inline int kasan_add_zero_shadow(void *start, unsigned long size) 58d5750edfSAndrey Konovalov { 59d5750edfSAndrey Konovalov return 0; 60d5750edfSAndrey Konovalov } 61d5750edfSAndrey Konovalov static inline void kasan_remove_zero_shadow(void *start, 62d5750edfSAndrey Konovalov unsigned long size) 63d5750edfSAndrey Konovalov {} 64d5750edfSAndrey Konovalov 65d5750edfSAndrey Konovalov #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ 66d5750edfSAndrey Konovalov 67d5750edfSAndrey Konovalov #ifdef CONFIG_KASAN 68d5750edfSAndrey Konovalov 690b24beccSAndrey Ryabinin /* Enable reporting bugs after kasan_disable_current() */ 70af8601adSIngo Molnar extern void kasan_enable_current(void); 710b24beccSAndrey Ryabinin 720b24beccSAndrey Ryabinin /* Disable reporting bugs for current task */ 73af8601adSIngo Molnar extern void kasan_disable_current(void); 740b24beccSAndrey Ryabinin 75*cebd0eb2SAndrey Konovalov void kasan_unpoison_range(const void *address, size_t size); 760b24beccSAndrey Ryabinin 77e3ae1163SMark Rutland void kasan_unpoison_task_stack(struct task_struct *task); 78e3ae1163SMark Rutland 79b8c73fc2SAndrey Ryabinin void kasan_alloc_pages(struct page *page, unsigned int order); 80b8c73fc2SAndrey Ryabinin void kasan_free_pages(struct page *page, unsigned int order); 81b8c73fc2SAndrey Ryabinin 82be4a7988SAlexey Dobriyan void kasan_cache_create(struct kmem_cache *cache, unsigned int *size, 83d50112edSAlexey Dobriyan slab_flags_t *flags); 847ed2f9e6SAlexander Potapenko 850316bec2SAndrey Ryabinin void kasan_poison_slab(struct page *page); 860316bec2SAndrey Ryabinin void kasan_unpoison_object_data(struct kmem_cache *cache, void *object); 870316bec2SAndrey Ryabinin void kasan_poison_object_data(struct kmem_cache *cache, void *object); 8866afc7f1SAndrey Konovalov void * __must_check kasan_init_slab_obj(struct kmem_cache *cache, 8966afc7f1SAndrey Konovalov const void *object); 900316bec2SAndrey Ryabinin 9166afc7f1SAndrey Konovalov void * __must_check kasan_kmalloc_large(const void *ptr, size_t size, 9266afc7f1SAndrey Konovalov gfp_t flags); 93ee3ce779SDmitry Vyukov void kasan_kfree_large(void *ptr, unsigned long ip); 946860f634SDmitry Vyukov void kasan_poison_kfree(void *ptr, unsigned long ip); 9566afc7f1SAndrey Konovalov void * __must_check kasan_kmalloc(struct kmem_cache *s, const void *object, 9666afc7f1SAndrey Konovalov size_t size, gfp_t flags); 9766afc7f1SAndrey Konovalov void * __must_check kasan_krealloc(const void *object, size_t new_size, 98505f5dcbSAlexander Potapenko gfp_t flags); 990316bec2SAndrey Ryabinin 10066afc7f1SAndrey Konovalov void * __must_check kasan_slab_alloc(struct kmem_cache *s, void *object, 10166afc7f1SAndrey Konovalov gfp_t flags); 102ee3ce779SDmitry Vyukov bool kasan_slab_free(struct kmem_cache *s, void *object, unsigned long ip); 1030316bec2SAndrey Ryabinin 1047ed2f9e6SAlexander Potapenko struct kasan_cache { 1057ed2f9e6SAlexander Potapenko int alloc_meta_offset; 1067ed2f9e6SAlexander Potapenko int free_meta_offset; 1077ed2f9e6SAlexander Potapenko }; 1087ed2f9e6SAlexander Potapenko 1090d4ca4c9SMarco Elver size_t __ksize(const void *); 1100d4ca4c9SMarco Elver static inline void kasan_unpoison_slab(const void *ptr) 1110d4ca4c9SMarco Elver { 112*cebd0eb2SAndrey Konovalov kasan_unpoison_range(ptr, __ksize(ptr)); 1130d4ca4c9SMarco Elver } 11480a9201aSAlexander Potapenko size_t kasan_metadata_size(struct kmem_cache *cache); 1159b75a867SAndrey Ryabinin 116b0845ce5SMark Rutland bool kasan_save_enable_multi_shot(void); 117b0845ce5SMark Rutland void kasan_restore_multi_shot(bool enabled); 118b0845ce5SMark Rutland 1190b24beccSAndrey Ryabinin #else /* CONFIG_KASAN */ 1200b24beccSAndrey Ryabinin 121*cebd0eb2SAndrey Konovalov static inline void kasan_unpoison_range(const void *address, size_t size) {} 1220b24beccSAndrey Ryabinin 123e3ae1163SMark Rutland static inline void kasan_unpoison_task_stack(struct task_struct *task) {} 124e3ae1163SMark Rutland 1250b24beccSAndrey Ryabinin static inline void kasan_enable_current(void) {} 1260b24beccSAndrey Ryabinin static inline void kasan_disable_current(void) {} 1270b24beccSAndrey Ryabinin 128b8c73fc2SAndrey Ryabinin static inline void kasan_alloc_pages(struct page *page, unsigned int order) {} 129b8c73fc2SAndrey Ryabinin static inline void kasan_free_pages(struct page *page, unsigned int order) {} 130b8c73fc2SAndrey Ryabinin 1317ed2f9e6SAlexander Potapenko static inline void kasan_cache_create(struct kmem_cache *cache, 132be4a7988SAlexey Dobriyan unsigned int *size, 133d50112edSAlexey Dobriyan slab_flags_t *flags) {} 1347ed2f9e6SAlexander Potapenko 1350316bec2SAndrey Ryabinin static inline void kasan_poison_slab(struct page *page) {} 1360316bec2SAndrey Ryabinin static inline void kasan_unpoison_object_data(struct kmem_cache *cache, 1370316bec2SAndrey Ryabinin void *object) {} 1380316bec2SAndrey Ryabinin static inline void kasan_poison_object_data(struct kmem_cache *cache, 1390316bec2SAndrey Ryabinin void *object) {} 1400116523cSAndrey Konovalov static inline void *kasan_init_slab_obj(struct kmem_cache *cache, 1410116523cSAndrey Konovalov const void *object) 1420116523cSAndrey Konovalov { 1430116523cSAndrey Konovalov return (void *)object; 1440116523cSAndrey Konovalov } 1450316bec2SAndrey Ryabinin 1460116523cSAndrey Konovalov static inline void *kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) 1470116523cSAndrey Konovalov { 1480116523cSAndrey Konovalov return ptr; 1490116523cSAndrey Konovalov } 150ee3ce779SDmitry Vyukov static inline void kasan_kfree_large(void *ptr, unsigned long ip) {} 1516860f634SDmitry Vyukov static inline void kasan_poison_kfree(void *ptr, unsigned long ip) {} 1520116523cSAndrey Konovalov static inline void *kasan_kmalloc(struct kmem_cache *s, const void *object, 1530116523cSAndrey Konovalov size_t size, gfp_t flags) 1540116523cSAndrey Konovalov { 1550116523cSAndrey Konovalov return (void *)object; 1560116523cSAndrey Konovalov } 1570116523cSAndrey Konovalov static inline void *kasan_krealloc(const void *object, size_t new_size, 1580116523cSAndrey Konovalov gfp_t flags) 1590116523cSAndrey Konovalov { 1600116523cSAndrey Konovalov return (void *)object; 1610116523cSAndrey Konovalov } 1620316bec2SAndrey Ryabinin 1630116523cSAndrey Konovalov static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object, 1640116523cSAndrey Konovalov gfp_t flags) 1650116523cSAndrey Konovalov { 1660116523cSAndrey Konovalov return object; 1670116523cSAndrey Konovalov } 168ee3ce779SDmitry Vyukov static inline bool kasan_slab_free(struct kmem_cache *s, void *object, 169ee3ce779SDmitry Vyukov unsigned long ip) 17055834c59SAlexander Potapenko { 17155834c59SAlexander Potapenko return false; 17255834c59SAlexander Potapenko } 1730316bec2SAndrey Ryabinin 1749b75a867SAndrey Ryabinin static inline void kasan_unpoison_slab(const void *ptr) { } 17580a9201aSAlexander Potapenko static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; } 1769b75a867SAndrey Ryabinin 1770b24beccSAndrey Ryabinin #endif /* CONFIG_KASAN */ 1780b24beccSAndrey Ryabinin 1792bd926b4SAndrey Konovalov #ifdef CONFIG_KASAN_GENERIC 1802bd926b4SAndrey Konovalov 1812bd926b4SAndrey Konovalov void kasan_cache_shrink(struct kmem_cache *cache); 1822bd926b4SAndrey Konovalov void kasan_cache_shutdown(struct kmem_cache *cache); 18326e760c9SWalter Wu void kasan_record_aux_stack(void *ptr); 1842bd926b4SAndrey Konovalov 1852bd926b4SAndrey Konovalov #else /* CONFIG_KASAN_GENERIC */ 1862bd926b4SAndrey Konovalov 1872bd926b4SAndrey Konovalov static inline void kasan_cache_shrink(struct kmem_cache *cache) {} 1882bd926b4SAndrey Konovalov static inline void kasan_cache_shutdown(struct kmem_cache *cache) {} 18926e760c9SWalter Wu static inline void kasan_record_aux_stack(void *ptr) {} 1902bd926b4SAndrey Konovalov 1912bd926b4SAndrey Konovalov #endif /* CONFIG_KASAN_GENERIC */ 1922bd926b4SAndrey Konovalov 193080eb83fSAndrey Konovalov #ifdef CONFIG_KASAN_SW_TAGS 194080eb83fSAndrey Konovalov 1953c9e3aa1SAndrey Konovalov void kasan_init_tags(void); 1963c9e3aa1SAndrey Konovalov 1973c9e3aa1SAndrey Konovalov void *kasan_reset_tag(const void *addr); 1983c9e3aa1SAndrey Konovalov 1998cceeff4SWalter Wu bool kasan_report(unsigned long addr, size_t size, 20041eea9cdSAndrey Konovalov bool is_write, unsigned long ip); 20141eea9cdSAndrey Konovalov 2023c9e3aa1SAndrey Konovalov #else /* CONFIG_KASAN_SW_TAGS */ 2033c9e3aa1SAndrey Konovalov 2043c9e3aa1SAndrey Konovalov static inline void kasan_init_tags(void) { } 2053c9e3aa1SAndrey Konovalov 2063c9e3aa1SAndrey Konovalov static inline void *kasan_reset_tag(const void *addr) 2073c9e3aa1SAndrey Konovalov { 2083c9e3aa1SAndrey Konovalov return (void *)addr; 2093c9e3aa1SAndrey Konovalov } 2103c9e3aa1SAndrey Konovalov 211080eb83fSAndrey Konovalov #endif /* CONFIG_KASAN_SW_TAGS */ 212080eb83fSAndrey Konovalov 2133c5c3cfbSDaniel Axtens #ifdef CONFIG_KASAN_VMALLOC 2143b1a4a86SAndrey Konovalov 215d98c9e83SAndrey Ryabinin int kasan_populate_vmalloc(unsigned long addr, unsigned long size); 216d98c9e83SAndrey Ryabinin void kasan_poison_vmalloc(const void *start, unsigned long size); 217d98c9e83SAndrey Ryabinin void kasan_unpoison_vmalloc(const void *start, unsigned long size); 2183c5c3cfbSDaniel Axtens void kasan_release_vmalloc(unsigned long start, unsigned long end, 2193c5c3cfbSDaniel Axtens unsigned long free_region_start, 2203c5c3cfbSDaniel Axtens unsigned long free_region_end); 2213b1a4a86SAndrey Konovalov 2223b1a4a86SAndrey Konovalov #else /* CONFIG_KASAN_VMALLOC */ 2233b1a4a86SAndrey Konovalov 224d98c9e83SAndrey Ryabinin static inline int kasan_populate_vmalloc(unsigned long start, 225d98c9e83SAndrey Ryabinin unsigned long size) 2263c5c3cfbSDaniel Axtens { 2273c5c3cfbSDaniel Axtens return 0; 2283c5c3cfbSDaniel Axtens } 2293c5c3cfbSDaniel Axtens 230d98c9e83SAndrey Ryabinin static inline void kasan_poison_vmalloc(const void *start, unsigned long size) 231d98c9e83SAndrey Ryabinin { } 232d98c9e83SAndrey Ryabinin static inline void kasan_unpoison_vmalloc(const void *start, unsigned long size) 233d98c9e83SAndrey Ryabinin { } 2343c5c3cfbSDaniel Axtens static inline void kasan_release_vmalloc(unsigned long start, 2353c5c3cfbSDaniel Axtens unsigned long end, 2363c5c3cfbSDaniel Axtens unsigned long free_region_start, 2373c5c3cfbSDaniel Axtens unsigned long free_region_end) {} 2383b1a4a86SAndrey Konovalov 2393b1a4a86SAndrey Konovalov #endif /* CONFIG_KASAN_VMALLOC */ 2403b1a4a86SAndrey Konovalov 2413b1a4a86SAndrey Konovalov #if defined(CONFIG_KASAN) && !defined(CONFIG_KASAN_VMALLOC) 2423b1a4a86SAndrey Konovalov 2433b1a4a86SAndrey Konovalov /* 2443b1a4a86SAndrey Konovalov * These functions provide a special case to support backing module 2453b1a4a86SAndrey Konovalov * allocations with real shadow memory. With KASAN vmalloc, the special 2463b1a4a86SAndrey Konovalov * case is unnecessary, as the work is handled in the generic case. 2473b1a4a86SAndrey Konovalov */ 2483b1a4a86SAndrey Konovalov int kasan_module_alloc(void *addr, size_t size); 2493b1a4a86SAndrey Konovalov void kasan_free_shadow(const struct vm_struct *vm); 2503b1a4a86SAndrey Konovalov 2513b1a4a86SAndrey Konovalov #else /* CONFIG_KASAN && !CONFIG_KASAN_VMALLOC */ 2523b1a4a86SAndrey Konovalov 2533b1a4a86SAndrey Konovalov static inline int kasan_module_alloc(void *addr, size_t size) { return 0; } 2543b1a4a86SAndrey Konovalov static inline void kasan_free_shadow(const struct vm_struct *vm) {} 2553b1a4a86SAndrey Konovalov 2563b1a4a86SAndrey Konovalov #endif /* CONFIG_KASAN && !CONFIG_KASAN_VMALLOC */ 2573c5c3cfbSDaniel Axtens 2582f004eeaSJann Horn #ifdef CONFIG_KASAN_INLINE 2592f004eeaSJann Horn void kasan_non_canonical_hook(unsigned long addr); 2602f004eeaSJann Horn #else /* CONFIG_KASAN_INLINE */ 2612f004eeaSJann Horn static inline void kasan_non_canonical_hook(unsigned long addr) { } 2622f004eeaSJann Horn #endif /* CONFIG_KASAN_INLINE */ 2632f004eeaSJann Horn 2640b24beccSAndrey Ryabinin #endif /* LINUX_KASAN_H */ 265