#ifndef _LINUX_KASAN_H
#define _LINUX_KASAN_H
#include <linux/bug.h>
#include <linux/kasan-enabled.h>
#include <linux/kasan-tags.h>
#include <linux/kernel.h>
#include <linux/static_key.h>
#include <linux/types.h>
struct kmem_cache;
struct page;
struct slab;
struct vm_struct;
struct task_struct;
#ifdef CONFIG_KASAN
#include <linux/linkage.h>
#include <asm/kasan.h>
#endif
kasan_vmalloc_flags_t;
#define KASAN_VMALLOC_NONE …
#define KASAN_VMALLOC_INIT …
#define KASAN_VMALLOC_VM_ALLOC …
#define KASAN_VMALLOC_PROT_NORMAL …
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
#include <linux/pgtable.h>
#ifdef CONFIG_KASAN_SW_TAGS
#define KASAN_SHADOW_INIT …
#else
#define KASAN_SHADOW_INIT …
#endif
#ifndef PTE_HWTABLE_PTRS
#define PTE_HWTABLE_PTRS …
#endif
extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
extern pte_t kasan_early_shadow_pte[MAX_PTRS_PER_PTE + PTE_HWTABLE_PTRS];
extern pmd_t kasan_early_shadow_pmd[MAX_PTRS_PER_PMD];
extern pud_t kasan_early_shadow_pud[MAX_PTRS_PER_PUD];
extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D];
int kasan_populate_early_shadow(const void *shadow_start,
const void *shadow_end);
#ifndef kasan_mem_to_shadow
static inline void *kasan_mem_to_shadow(const void *addr)
{
return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
+ KASAN_SHADOW_OFFSET;
}
#endif
int kasan_add_zero_shadow(void *start, unsigned long size);
void kasan_remove_zero_shadow(void *start, unsigned long size);
extern void kasan_enable_current(void);
extern void kasan_disable_current(void);
#else
static inline int kasan_add_zero_shadow(void *start, unsigned long size)
{ … }
static inline void kasan_remove_zero_shadow(void *start,
unsigned long size)
{ … }
static inline void kasan_enable_current(void) { … }
static inline void kasan_disable_current(void) { … }
#endif
#ifdef CONFIG_KASAN_HW_TAGS
#else
#endif
static inline bool kasan_has_integrated_init(void)
{ … }
#ifdef CONFIG_KASAN
void __kasan_unpoison_range(const void *addr, size_t size);
static __always_inline void kasan_unpoison_range(const void *addr, size_t size)
{
if (kasan_enabled())
__kasan_unpoison_range(addr, size);
}
void __kasan_poison_pages(struct page *page, unsigned int order, bool init);
static __always_inline void kasan_poison_pages(struct page *page,
unsigned int order, bool init)
{
if (kasan_enabled())
__kasan_poison_pages(page, order, init);
}
bool __kasan_unpoison_pages(struct page *page, unsigned int order, bool init);
static __always_inline bool kasan_unpoison_pages(struct page *page,
unsigned int order, bool init)
{
if (kasan_enabled())
return __kasan_unpoison_pages(page, order, init);
return false;
}
void __kasan_poison_slab(struct slab *slab);
static __always_inline void kasan_poison_slab(struct slab *slab)
{
if (kasan_enabled())
__kasan_poison_slab(slab);
}
void __kasan_unpoison_new_object(struct kmem_cache *cache, void *object);
static __always_inline void kasan_unpoison_new_object(struct kmem_cache *cache,
void *object)
{
if (kasan_enabled())
__kasan_unpoison_new_object(cache, object);
}
void __kasan_poison_new_object(struct kmem_cache *cache, void *object);
static __always_inline void kasan_poison_new_object(struct kmem_cache *cache,
void *object)
{
if (kasan_enabled())
__kasan_poison_new_object(cache, object);
}
void * __must_check __kasan_init_slab_obj(struct kmem_cache *cache,
const void *object);
static __always_inline void * __must_check kasan_init_slab_obj(
struct kmem_cache *cache, const void *object)
{
if (kasan_enabled())
return __kasan_init_slab_obj(cache, object);
return (void *)object;
}
bool __kasan_slab_free(struct kmem_cache *s, void *object,
unsigned long ip, bool init);
static __always_inline bool kasan_slab_free(struct kmem_cache *s,
void *object, bool init)
{
if (kasan_enabled())
return __kasan_slab_free(s, object, _RET_IP_, init);
return false;
}
void __kasan_kfree_large(void *ptr, unsigned long ip);
static __always_inline void kasan_kfree_large(void *ptr)
{
if (kasan_enabled())
__kasan_kfree_large(ptr, _RET_IP_);
}
void * __must_check __kasan_slab_alloc(struct kmem_cache *s,
void *object, gfp_t flags, bool init);
static __always_inline void * __must_check kasan_slab_alloc(
struct kmem_cache *s, void *object, gfp_t flags, bool init)
{
if (kasan_enabled())
return __kasan_slab_alloc(s, object, flags, init);
return object;
}
void * __must_check __kasan_kmalloc(struct kmem_cache *s, const void *object,
size_t size, gfp_t flags);
static __always_inline void * __must_check kasan_kmalloc(struct kmem_cache *s,
const void *object, size_t size, gfp_t flags)
{
if (kasan_enabled())
return __kasan_kmalloc(s, object, size, flags);
return (void *)object;
}
void * __must_check __kasan_kmalloc_large(const void *ptr,
size_t size, gfp_t flags);
static __always_inline void * __must_check kasan_kmalloc_large(const void *ptr,
size_t size, gfp_t flags)
{
if (kasan_enabled())
return __kasan_kmalloc_large(ptr, size, flags);
return (void *)ptr;
}
void * __must_check __kasan_krealloc(const void *object,
size_t new_size, gfp_t flags);
static __always_inline void * __must_check kasan_krealloc(const void *object,
size_t new_size, gfp_t flags)
{
if (kasan_enabled())
return __kasan_krealloc(object, new_size, flags);
return (void *)object;
}
bool __kasan_mempool_poison_pages(struct page *page, unsigned int order,
unsigned long ip);
static __always_inline bool kasan_mempool_poison_pages(struct page *page,
unsigned int order)
{
if (kasan_enabled())
return __kasan_mempool_poison_pages(page, order, _RET_IP_);
return true;
}
void __kasan_mempool_unpoison_pages(struct page *page, unsigned int order,
unsigned long ip);
static __always_inline void kasan_mempool_unpoison_pages(struct page *page,
unsigned int order)
{
if (kasan_enabled())
__kasan_mempool_unpoison_pages(page, order, _RET_IP_);
}
bool __kasan_mempool_poison_object(void *ptr, unsigned long ip);
static __always_inline bool kasan_mempool_poison_object(void *ptr)
{
if (kasan_enabled())
return __kasan_mempool_poison_object(ptr, _RET_IP_);
return true;
}
void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long ip);
static __always_inline void kasan_mempool_unpoison_object(void *ptr,
size_t size)
{
if (kasan_enabled())
__kasan_mempool_unpoison_object(ptr, size, _RET_IP_);
}
bool __kasan_check_byte(const void *addr, unsigned long ip);
static __always_inline bool kasan_check_byte(const void *addr)
{
if (kasan_enabled())
return __kasan_check_byte(addr, _RET_IP_);
return true;
}
#else
static inline void kasan_unpoison_range(const void *address, size_t size) { … }
static inline void kasan_poison_pages(struct page *page, unsigned int order,
bool init) { … }
static inline bool kasan_unpoison_pages(struct page *page, unsigned int order,
bool init)
{ … }
static inline void kasan_poison_slab(struct slab *slab) { … }
static inline void kasan_unpoison_new_object(struct kmem_cache *cache,
void *object) { … }
static inline void kasan_poison_new_object(struct kmem_cache *cache,
void *object) { … }
static inline void *kasan_init_slab_obj(struct kmem_cache *cache,
const void *object)
{ … }
static inline bool kasan_slab_free(struct kmem_cache *s, void *object, bool init)
{ … }
static inline void kasan_kfree_large(void *ptr) { … }
static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object,
gfp_t flags, bool init)
{ … }
static inline void *kasan_kmalloc(struct kmem_cache *s, const void *object,
size_t size, gfp_t flags)
{ … }
static inline void *kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags)
{ … }
static inline void *kasan_krealloc(const void *object, size_t new_size,
gfp_t flags)
{ … }
static inline bool kasan_mempool_poison_pages(struct page *page, unsigned int order)
{ … }
static inline void kasan_mempool_unpoison_pages(struct page *page, unsigned int order) { … }
static inline bool kasan_mempool_poison_object(void *ptr)
{ … }
static inline void kasan_mempool_unpoison_object(void *ptr, size_t size) { … }
static inline bool kasan_check_byte(const void *address)
{ … }
#endif
#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
void kasan_unpoison_task_stack(struct task_struct *task);
asmlinkage void kasan_unpoison_task_stack_below(const void *watermark);
#else
static inline void kasan_unpoison_task_stack(struct task_struct *task) { … }
static inline void kasan_unpoison_task_stack_below(const void *watermark) { … }
#endif
#ifdef CONFIG_KASAN_GENERIC
struct kasan_cache {
int alloc_meta_offset;
int free_meta_offset;
};
size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object);
void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
slab_flags_t *flags);
void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);
void kasan_record_aux_stack(void *ptr);
void kasan_record_aux_stack_noalloc(void *ptr);
#else
static inline size_t kasan_metadata_size(struct kmem_cache *cache,
bool in_object)
{ … }
static inline void kasan_cache_create(struct kmem_cache *cache,
unsigned int *size,
slab_flags_t *flags) { … }
static inline void kasan_cache_shrink(struct kmem_cache *cache) { … }
static inline void kasan_cache_shutdown(struct kmem_cache *cache) { … }
static inline void kasan_record_aux_stack(void *ptr) { … }
static inline void kasan_record_aux_stack_noalloc(void *ptr) { … }
#endif
#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
static inline void *kasan_reset_tag(const void *addr)
{
return (void *)arch_kasan_reset_tag(addr);
}
bool kasan_report(const void *addr, size_t size,
bool is_write, unsigned long ip);
#else
static inline void *kasan_reset_tag(const void *addr)
{ … }
#endif
#ifdef CONFIG_KASAN_HW_TAGS
void kasan_report_async(void);
#endif
#ifdef CONFIG_KASAN_SW_TAGS
void __init kasan_init_sw_tags(void);
#else
static inline void kasan_init_sw_tags(void) { … }
#endif
#ifdef CONFIG_KASAN_HW_TAGS
void kasan_init_hw_tags_cpu(void);
void __init kasan_init_hw_tags(void);
#else
static inline void kasan_init_hw_tags_cpu(void) { … }
static inline void kasan_init_hw_tags(void) { … }
#endif
#ifdef CONFIG_KASAN_VMALLOC
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
void kasan_populate_early_vm_area_shadow(void *start, unsigned long size);
int kasan_populate_vmalloc(unsigned long addr, unsigned long size);
void kasan_release_vmalloc(unsigned long start, unsigned long end,
unsigned long free_region_start,
unsigned long free_region_end);
#else
static inline void kasan_populate_early_vm_area_shadow(void *start,
unsigned long size)
{ }
static inline int kasan_populate_vmalloc(unsigned long start,
unsigned long size)
{
return 0;
}
static inline void kasan_release_vmalloc(unsigned long start,
unsigned long end,
unsigned long free_region_start,
unsigned long free_region_end) { }
#endif
void *__kasan_unpoison_vmalloc(const void *start, unsigned long size,
kasan_vmalloc_flags_t flags);
static __always_inline void *kasan_unpoison_vmalloc(const void *start,
unsigned long size,
kasan_vmalloc_flags_t flags)
{
if (kasan_enabled())
return __kasan_unpoison_vmalloc(start, size, flags);
return (void *)start;
}
void __kasan_poison_vmalloc(const void *start, unsigned long size);
static __always_inline void kasan_poison_vmalloc(const void *start,
unsigned long size)
{
if (kasan_enabled())
__kasan_poison_vmalloc(start, size);
}
#else
static inline void kasan_populate_early_vm_area_shadow(void *start,
unsigned long size) { … }
static inline int kasan_populate_vmalloc(unsigned long start,
unsigned long size)
{ … }
static inline void kasan_release_vmalloc(unsigned long start,
unsigned long end,
unsigned long free_region_start,
unsigned long free_region_end) { … }
static inline void *kasan_unpoison_vmalloc(const void *start,
unsigned long size,
kasan_vmalloc_flags_t flags)
{ … }
static inline void kasan_poison_vmalloc(const void *start, unsigned long size)
{ … }
#endif
#if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \
!defined(CONFIG_KASAN_VMALLOC)
int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask);
void kasan_free_module_shadow(const struct vm_struct *vm);
#else
static inline int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask) { … }
static inline void kasan_free_module_shadow(const struct vm_struct *vm) { … }
#endif
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
void kasan_non_canonical_hook(unsigned long addr);
#else
static inline void kasan_non_canonical_hook(unsigned long addr) { … }
#endif
#endif