arch/x86: Add support for ASan to memory functions

Compiler's instrumentation cannot insert asan memory checks in
case of memory functions like memset, memcpy and memmove as they
are written in assembly.

So, we need to manually check the memory state before performing
each of these operations to ensure that ASan is triggered in case
of bad access.

Change-Id: I2030437636c77aea7cccda8efe050df4b77c15c7
Signed-off-by: Harshit Sharma <harshitsharmajs@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44307
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
This commit is contained in:
Harshit Sharma 2020-08-08 17:51:59 -07:00 committed by Patrick Georgi
parent c29c12376f
commit 51593dd0c6
5 changed files with 26 additions and 1 deletions

View File

@ -1,11 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <string.h>
#include <stdbool.h>
#include <asan.h>
void *memcpy(void *dest, const void *src, size_t n)
{
unsigned long d0, d1, d2;
#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)src, n, false, _RET_IP_);
check_memory_region((unsigned long)dest, n, true, _RET_IP_);
#endif
asm volatile(
#ifdef __x86_64__
"rep ; movsd\n\t"

View File

@ -4,12 +4,20 @@
*/
#include <string.h>
#include <stdbool.h>
#include <asan.h>
void *memmove(void *dest, const void *src, size_t n)
{
int d0, d1, d2, d3, d4, d5;
char *ret = dest;
#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)src, n, false, _RET_IP_);
check_memory_region((unsigned long)dest, n, true, _RET_IP_);
#endif
__asm__ __volatile__(
/* Handle more 16bytes in loop */
"cmp $0x10, %0\n\t"

View File

@ -4,6 +4,8 @@
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <asan.h>
typedef uint32_t op_t;
@ -12,6 +14,11 @@ void *memset(void *dstpp, int c, size_t len)
int d0;
unsigned long int dstp = (unsigned long int) dstpp;
#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)dstpp, len, true, _RET_IP_);
#endif
/* This explicit register allocation improves code very much indeed. */
register op_t x asm("ax");

View File

@ -57,6 +57,8 @@ void asan_unpoison_shadow(const void *address, size_t size);
void asan_report(unsigned long addr, size_t size, bool is_write,
unsigned long ip);
void asan_init(void);
void check_memory_region(unsigned long addr, size_t size, bool write,
unsigned long ret_ip);
uintptr_t __asan_shadow_offset(uintptr_t addr);
void __asan_register_globals(struct asan_global *globals, size_t size);

View File

@ -260,7 +260,7 @@ static __always_inline void check_memory_region_inline(unsigned long addr,
asan_report(addr, size, write, ret_ip);
}
static void check_memory_region(unsigned long addr, size_t size, bool write,
void check_memory_region(unsigned long addr, size_t size, bool write,
unsigned long ret_ip)
{
check_memory_region_inline(addr, size, write, ret_ip);