This is the second patch for the Kasan advanced check feature. The advanced check would need access mode to make decision. Signed-off-by: Wengang Wang <wen.gang.wang@xxxxxxxxxx> diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index 060ed72..4501422 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -122,7 +122,7 @@ void kasan_unpoison_stack_above_sp_to(const void *watermark) * depending on memory access size X. */ -static __always_inline bool memory_is_poisoned_1(unsigned long addr) +static __always_inline bool memory_is_poisoned_1(unsigned long addr, bool write) { s8 shadow_value = *(s8 *)kasan_mem_to_shadow((void *)addr); @@ -136,7 +136,8 @@ static __always_inline bool memory_is_poisoned_1(unsigned long addr) } static __always_inline bool memory_is_poisoned_2_4_8(unsigned long addr, - unsigned long size) + unsigned long size, + bool write) { u8 *shadow_addr = (u8 *)kasan_mem_to_shadow((void *)addr); @@ -146,25 +147,27 @@ static __always_inline bool memory_is_poisoned_2_4_8(unsigned long addr, */ if (unlikely(((addr + size - 1) & KASAN_SHADOW_MASK) < size - 1)) return KASAN_GET_POISON(*shadow_addr) || - memory_is_poisoned_1(addr + size - 1); + memory_is_poisoned_1(addr + size - 1, write); - return memory_is_poisoned_1(addr + size - 1); + return memory_is_poisoned_1(addr + size - 1, write); } -static __always_inline bool memory_is_poisoned_16(unsigned long addr) +static __always_inline bool memory_is_poisoned_16(unsigned long addr, + bool write) { u16 *shadow_addr = (u16 *)kasan_mem_to_shadow((void *)addr); /* Unaligned 16-bytes access maps into 3 shadow bytes. */ if (unlikely(!IS_ALIGNED(addr, KASAN_SHADOW_SCALE_SIZE))) return KASAN_GET_POISON_16(*shadow_addr) || - memory_is_poisoned_1(addr + 15); + memory_is_poisoned_1(addr + 15, write); return *shadow_addr; } static __always_inline unsigned long bytes_is_nonzero(const u8 *start, - size_t size) + size_t size, + bool write) { while (size) { if (unlikely(KASAN_GET_POISON(*start))) @@ -177,18 +180,19 @@ static __always_inline unsigned long bytes_is_nonzero(const u8 *start, } static __always_inline unsigned long memory_is_nonzero(const void *start, - const void *end) + const void *end, + bool write) { unsigned int words; unsigned long ret; unsigned int prefix = (unsigned long)start % 8; if (end - start <= 16) - return bytes_is_nonzero(start, end - start); + return bytes_is_nonzero(start, end - start, write); if (prefix) { prefix = 8 - prefix; - ret = bytes_is_nonzero(start, prefix); + ret = bytes_is_nonzero(start, prefix, write); if (unlikely(ret)) return ret; start += prefix; @@ -197,21 +201,23 @@ static __always_inline unsigned long memory_is_nonzero(const void *start, words = (end - start) / 8; while (words) { if (unlikely(KASAN_GET_POISON_64(*(u64 *)start))) - return bytes_is_nonzero(start, 8); + return bytes_is_nonzero(start, 8, write); start += 8; words--; } - return bytes_is_nonzero(start, (end - start) % 8); + return bytes_is_nonzero(start, (end - start) % 8, write); } static __always_inline bool memory_is_poisoned_n(unsigned long addr, - size_t size) + size_t size, + bool write) { unsigned long ret; ret = memory_is_nonzero(kasan_mem_to_shadow((void *)addr), - kasan_mem_to_shadow((void *)addr + size - 1) + 1); + kasan_mem_to_shadow((void *)addr + size - 1) + 1, + write); if (unlikely(ret)) { unsigned long last_byte = addr + size - 1; @@ -225,24 +231,25 @@ static __always_inline bool memory_is_poisoned_n(unsigned long addr, return false; } -static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size) +static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size, + bool write) { if (__builtin_constant_p(size)) { switch (size) { case 1: - return memory_is_poisoned_1(addr); + return memory_is_poisoned_1(addr, write); case 2: case 4: case 8: - return memory_is_poisoned_2_4_8(addr, size); + return memory_is_poisoned_2_4_8(addr, size, write); case 16: - return memory_is_poisoned_16(addr); + return memory_is_poisoned_16(addr, write); default: BUILD_BUG(); } } - return memory_is_poisoned_n(addr, size); + return memory_is_poisoned_n(addr, size, write); } static __always_inline void check_memory_region_inline(unsigned long addr, @@ -258,7 +265,7 @@ static __always_inline void check_memory_region_inline(unsigned long addr, return; } - if (likely(!memory_is_poisoned(addr, size))) + if (likely(!memory_is_poisoned(addr, size, write))) return; kasan_report(addr, size, write, ret_ip); -- 2.9.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>