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 55d73b4936SAndrey Konovalov /* Enable reporting bugs after kasan_disable_current() */ 56d73b4936SAndrey Konovalov extern void kasan_enable_current(void); 57d73b4936SAndrey Konovalov 58d73b4936SAndrey Konovalov /* Disable reporting bugs for current task */ 59d73b4936SAndrey Konovalov extern void kasan_disable_current(void); 60d73b4936SAndrey Konovalov 61d5750edfSAndrey Konovalov #else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ 62d5750edfSAndrey Konovalov 63d5750edfSAndrey Konovalov static inline int kasan_add_zero_shadow(void *start, unsigned long size) 64d5750edfSAndrey Konovalov { 65d5750edfSAndrey Konovalov return 0; 66d5750edfSAndrey Konovalov } 67d5750edfSAndrey Konovalov static inline void kasan_remove_zero_shadow(void *start, 68d5750edfSAndrey Konovalov unsigned long size) 69d5750edfSAndrey Konovalov {} 70d5750edfSAndrey Konovalov 71d73b4936SAndrey Konovalov static inline void kasan_enable_current(void) {} 72d73b4936SAndrey Konovalov static inline void kasan_disable_current(void) {} 73d73b4936SAndrey Konovalov 74d5750edfSAndrey Konovalov #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */ 75d5750edfSAndrey Konovalov 76d5750edfSAndrey Konovalov #ifdef CONFIG_KASAN 77d5750edfSAndrey Konovalov 78cebd0eb2SAndrey Konovalov void kasan_unpoison_range(const void *address, size_t size); 790b24beccSAndrey Ryabinin 80b8c73fc2SAndrey Ryabinin void kasan_alloc_pages(struct page *page, unsigned int order); 81b8c73fc2SAndrey Ryabinin void kasan_free_pages(struct page *page, unsigned int order); 82b8c73fc2SAndrey Ryabinin 83be4a7988SAlexey Dobriyan void kasan_cache_create(struct kmem_cache *cache, unsigned int *size, 84d50112edSAlexey Dobriyan slab_flags_t *flags); 857ed2f9e6SAlexander Potapenko 860316bec2SAndrey Ryabinin void kasan_poison_slab(struct page *page); 870316bec2SAndrey Ryabinin void kasan_unpoison_object_data(struct kmem_cache *cache, void *object); 880316bec2SAndrey Ryabinin void kasan_poison_object_data(struct kmem_cache *cache, void *object); 8966afc7f1SAndrey Konovalov void * __must_check kasan_init_slab_obj(struct kmem_cache *cache, 9066afc7f1SAndrey Konovalov const void *object); 910316bec2SAndrey Ryabinin 9266afc7f1SAndrey Konovalov void * __must_check kasan_kmalloc_large(const void *ptr, size_t size, 9366afc7f1SAndrey Konovalov gfp_t flags); 94ee3ce779SDmitry Vyukov void kasan_kfree_large(void *ptr, unsigned long ip); 956860f634SDmitry Vyukov void kasan_poison_kfree(void *ptr, unsigned long ip); 9666afc7f1SAndrey Konovalov void * __must_check kasan_kmalloc(struct kmem_cache *s, const void *object, 9766afc7f1SAndrey Konovalov size_t size, gfp_t flags); 9866afc7f1SAndrey Konovalov void * __must_check kasan_krealloc(const void *object, size_t new_size, 99505f5dcbSAlexander Potapenko gfp_t flags); 1000316bec2SAndrey Ryabinin 10166afc7f1SAndrey Konovalov void * __must_check kasan_slab_alloc(struct kmem_cache *s, void *object, 10266afc7f1SAndrey Konovalov gfp_t flags); 103ee3ce779SDmitry Vyukov bool kasan_slab_free(struct kmem_cache *s, void *object, unsigned long ip); 1040316bec2SAndrey Ryabinin 1057ed2f9e6SAlexander Potapenko struct kasan_cache { 1067ed2f9e6SAlexander Potapenko int alloc_meta_offset; 1077ed2f9e6SAlexander Potapenko int free_meta_offset; 1087ed2f9e6SAlexander Potapenko }; 1097ed2f9e6SAlexander Potapenko 1100d4ca4c9SMarco Elver size_t __ksize(const void *); 1110d4ca4c9SMarco Elver static inline void kasan_unpoison_slab(const void *ptr) 1120d4ca4c9SMarco Elver { 113cebd0eb2SAndrey Konovalov kasan_unpoison_range(ptr, __ksize(ptr)); 1140d4ca4c9SMarco Elver } 11580a9201aSAlexander Potapenko size_t kasan_metadata_size(struct kmem_cache *cache); 1169b75a867SAndrey Ryabinin 117b0845ce5SMark Rutland bool kasan_save_enable_multi_shot(void); 118b0845ce5SMark Rutland void kasan_restore_multi_shot(bool enabled); 119b0845ce5SMark Rutland 1200b24beccSAndrey Ryabinin #else /* CONFIG_KASAN */ 1210b24beccSAndrey Ryabinin 122cebd0eb2SAndrey Konovalov static inline void kasan_unpoison_range(const void *address, size_t size) {} 1230b24beccSAndrey Ryabinin 124b8c73fc2SAndrey Ryabinin static inline void kasan_alloc_pages(struct page *page, unsigned int order) {} 125b8c73fc2SAndrey Ryabinin static inline void kasan_free_pages(struct page *page, unsigned int order) {} 126b8c73fc2SAndrey Ryabinin 1277ed2f9e6SAlexander Potapenko static inline void kasan_cache_create(struct kmem_cache *cache, 128be4a7988SAlexey Dobriyan unsigned int *size, 129d50112edSAlexey Dobriyan slab_flags_t *flags) {} 1307ed2f9e6SAlexander Potapenko 1310316bec2SAndrey Ryabinin static inline void kasan_poison_slab(struct page *page) {} 1320316bec2SAndrey Ryabinin static inline void kasan_unpoison_object_data(struct kmem_cache *cache, 1330316bec2SAndrey Ryabinin void *object) {} 1340316bec2SAndrey Ryabinin static inline void kasan_poison_object_data(struct kmem_cache *cache, 1350316bec2SAndrey Ryabinin void *object) {} 1360116523cSAndrey Konovalov static inline void *kasan_init_slab_obj(struct kmem_cache *cache, 1370116523cSAndrey Konovalov const void *object) 1380116523cSAndrey Konovalov { 1390116523cSAndrey Konovalov return (void *)object; 1400116523cSAndrey Konovalov } 1410316bec2SAndrey Ryabinin 1420116523cSAndrey Konovalov static inline void *kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) 1430116523cSAndrey Konovalov { 1440116523cSAndrey Konovalov return ptr; 1450116523cSAndrey Konovalov } 146ee3ce779SDmitry Vyukov static inline void kasan_kfree_large(void *ptr, unsigned long ip) {} 1476860f634SDmitry Vyukov static inline void kasan_poison_kfree(void *ptr, unsigned long ip) {} 1480116523cSAndrey Konovalov static inline void *kasan_kmalloc(struct kmem_cache *s, const void *object, 1490116523cSAndrey Konovalov size_t size, gfp_t flags) 1500116523cSAndrey Konovalov { 1510116523cSAndrey Konovalov return (void *)object; 1520116523cSAndrey Konovalov } 1530116523cSAndrey Konovalov static inline void *kasan_krealloc(const void *object, size_t new_size, 1540116523cSAndrey Konovalov gfp_t flags) 1550116523cSAndrey Konovalov { 1560116523cSAndrey Konovalov return (void *)object; 1570116523cSAndrey Konovalov } 1580316bec2SAndrey Ryabinin 1590116523cSAndrey Konovalov static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object, 1600116523cSAndrey Konovalov gfp_t flags) 1610116523cSAndrey Konovalov { 1620116523cSAndrey Konovalov return object; 1630116523cSAndrey Konovalov } 164ee3ce779SDmitry Vyukov static inline bool kasan_slab_free(struct kmem_cache *s, void *object, 165ee3ce779SDmitry Vyukov unsigned long ip) 16655834c59SAlexander Potapenko { 16755834c59SAlexander Potapenko return false; 16855834c59SAlexander Potapenko } 1690316bec2SAndrey Ryabinin 1709b75a867SAndrey Ryabinin static inline void kasan_unpoison_slab(const void *ptr) { } 17180a9201aSAlexander Potapenko static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; } 1729b75a867SAndrey Ryabinin 1730b24beccSAndrey Ryabinin #endif /* CONFIG_KASAN */ 1740b24beccSAndrey Ryabinin 175d56a9ef8SAndrey Konovalov #if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK 176d56a9ef8SAndrey Konovalov void kasan_unpoison_task_stack(struct task_struct *task); 177d56a9ef8SAndrey Konovalov #else 178d56a9ef8SAndrey Konovalov static inline void kasan_unpoison_task_stack(struct task_struct *task) {} 179d56a9ef8SAndrey Konovalov #endif 180d56a9ef8SAndrey Konovalov 1812bd926b4SAndrey Konovalov #ifdef CONFIG_KASAN_GENERIC 1822bd926b4SAndrey Konovalov 1832bd926b4SAndrey Konovalov void kasan_cache_shrink(struct kmem_cache *cache); 1842bd926b4SAndrey Konovalov void kasan_cache_shutdown(struct kmem_cache *cache); 18526e760c9SWalter Wu void kasan_record_aux_stack(void *ptr); 1862bd926b4SAndrey Konovalov 1872bd926b4SAndrey Konovalov #else /* CONFIG_KASAN_GENERIC */ 1882bd926b4SAndrey Konovalov 1892bd926b4SAndrey Konovalov static inline void kasan_cache_shrink(struct kmem_cache *cache) {} 1902bd926b4SAndrey Konovalov static inline void kasan_cache_shutdown(struct kmem_cache *cache) {} 19126e760c9SWalter Wu static inline void kasan_record_aux_stack(void *ptr) {} 1922bd926b4SAndrey Konovalov 1932bd926b4SAndrey Konovalov #endif /* CONFIG_KASAN_GENERIC */ 1942bd926b4SAndrey Konovalov 1952e903b91SAndrey Konovalov #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS) 1963c9e3aa1SAndrey Konovalov 197*c0054c56SAndrey Konovalov static inline void *kasan_reset_tag(const void *addr) 198*c0054c56SAndrey Konovalov { 199*c0054c56SAndrey Konovalov return (void *)arch_kasan_reset_tag(addr); 200*c0054c56SAndrey Konovalov } 2013c9e3aa1SAndrey Konovalov 2028cceeff4SWalter Wu bool kasan_report(unsigned long addr, size_t size, 20341eea9cdSAndrey Konovalov bool is_write, unsigned long ip); 20441eea9cdSAndrey Konovalov 2052e903b91SAndrey Konovalov #else /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */ 2063c9e3aa1SAndrey Konovalov 2073c9e3aa1SAndrey Konovalov static inline void *kasan_reset_tag(const void *addr) 2083c9e3aa1SAndrey Konovalov { 2093c9e3aa1SAndrey Konovalov return (void *)addr; 2103c9e3aa1SAndrey Konovalov } 2113c9e3aa1SAndrey Konovalov 2122e903b91SAndrey Konovalov #endif /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS*/ 2132e903b91SAndrey Konovalov 2142e903b91SAndrey Konovalov #ifdef CONFIG_KASAN_SW_TAGS 2152e903b91SAndrey Konovalov void __init kasan_init_sw_tags(void); 2162e903b91SAndrey Konovalov #else 2172e903b91SAndrey Konovalov static inline void kasan_init_sw_tags(void) { } 2182e903b91SAndrey Konovalov #endif 2192e903b91SAndrey Konovalov 2202e903b91SAndrey Konovalov #ifdef CONFIG_KASAN_HW_TAGS 2212e903b91SAndrey Konovalov void kasan_init_hw_tags_cpu(void); 2222e903b91SAndrey Konovalov void __init kasan_init_hw_tags(void); 2232e903b91SAndrey Konovalov #else 2242e903b91SAndrey Konovalov static inline void kasan_init_hw_tags_cpu(void) { } 2252e903b91SAndrey Konovalov static inline void kasan_init_hw_tags(void) { } 2262e903b91SAndrey Konovalov #endif 227080eb83fSAndrey Konovalov 2283c5c3cfbSDaniel Axtens #ifdef CONFIG_KASAN_VMALLOC 2293b1a4a86SAndrey Konovalov 230d98c9e83SAndrey Ryabinin int kasan_populate_vmalloc(unsigned long addr, unsigned long size); 231d98c9e83SAndrey Ryabinin void kasan_poison_vmalloc(const void *start, unsigned long size); 232d98c9e83SAndrey Ryabinin void kasan_unpoison_vmalloc(const void *start, unsigned long size); 2333c5c3cfbSDaniel Axtens void kasan_release_vmalloc(unsigned long start, unsigned long end, 2343c5c3cfbSDaniel Axtens unsigned long free_region_start, 2353c5c3cfbSDaniel Axtens unsigned long free_region_end); 2363b1a4a86SAndrey Konovalov 2373b1a4a86SAndrey Konovalov #else /* CONFIG_KASAN_VMALLOC */ 2383b1a4a86SAndrey Konovalov 239d98c9e83SAndrey Ryabinin static inline int kasan_populate_vmalloc(unsigned long start, 240d98c9e83SAndrey Ryabinin unsigned long size) 2413c5c3cfbSDaniel Axtens { 2423c5c3cfbSDaniel Axtens return 0; 2433c5c3cfbSDaniel Axtens } 2443c5c3cfbSDaniel Axtens 245d98c9e83SAndrey Ryabinin static inline void kasan_poison_vmalloc(const void *start, unsigned long size) 246d98c9e83SAndrey Ryabinin { } 247d98c9e83SAndrey Ryabinin static inline void kasan_unpoison_vmalloc(const void *start, unsigned long size) 248d98c9e83SAndrey Ryabinin { } 2493c5c3cfbSDaniel Axtens static inline void kasan_release_vmalloc(unsigned long start, 2503c5c3cfbSDaniel Axtens unsigned long end, 2513c5c3cfbSDaniel Axtens unsigned long free_region_start, 2523c5c3cfbSDaniel Axtens unsigned long free_region_end) {} 2533b1a4a86SAndrey Konovalov 2543b1a4a86SAndrey Konovalov #endif /* CONFIG_KASAN_VMALLOC */ 2553b1a4a86SAndrey Konovalov 2560fea6e9aSAndrey Konovalov #if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \ 2570fea6e9aSAndrey Konovalov !defined(CONFIG_KASAN_VMALLOC) 2583b1a4a86SAndrey Konovalov 2593b1a4a86SAndrey Konovalov /* 2603b1a4a86SAndrey Konovalov * These functions provide a special case to support backing module 2613b1a4a86SAndrey Konovalov * allocations with real shadow memory. With KASAN vmalloc, the special 2623b1a4a86SAndrey Konovalov * case is unnecessary, as the work is handled in the generic case. 2633b1a4a86SAndrey Konovalov */ 2643b1a4a86SAndrey Konovalov int kasan_module_alloc(void *addr, size_t size); 2653b1a4a86SAndrey Konovalov void kasan_free_shadow(const struct vm_struct *vm); 2663b1a4a86SAndrey Konovalov 2670fea6e9aSAndrey Konovalov #else /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */ 2683b1a4a86SAndrey Konovalov 2693b1a4a86SAndrey Konovalov static inline int kasan_module_alloc(void *addr, size_t size) { return 0; } 2703b1a4a86SAndrey Konovalov static inline void kasan_free_shadow(const struct vm_struct *vm) {} 2713b1a4a86SAndrey Konovalov 2720fea6e9aSAndrey Konovalov #endif /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */ 2733c5c3cfbSDaniel Axtens 2742f004eeaSJann Horn #ifdef CONFIG_KASAN_INLINE 2752f004eeaSJann Horn void kasan_non_canonical_hook(unsigned long addr); 2762f004eeaSJann Horn #else /* CONFIG_KASAN_INLINE */ 2772f004eeaSJann Horn static inline void kasan_non_canonical_hook(unsigned long addr) { } 2782f004eeaSJann Horn #endif /* CONFIG_KASAN_INLINE */ 2792f004eeaSJann Horn 2800b24beccSAndrey Ryabinin #endif /* LINUX_KASAN_H */ 281