mm/kasan: Kasan global support setting alignment length
1. Similar to asan, supports single byte out of bounds detection 2. Fix the script to address the issue of not supporting the big end Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
parent
0d8b6de03a
commit
469418f3c9
@ -196,7 +196,7 @@ define LINK_ALLSYMS_KASAN
|
|||||||
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
||||||
$(Q) $(call DELFILE, allsyms.tmp))
|
$(Q) $(call DELFILE, allsyms.tmp))
|
||||||
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
||||||
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp
|
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp -a $(CONFIG_MM_KASAN_GLOBAL_ALIGN)
|
||||||
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
||||||
$(Q) $(call DELFILE, kasan_globals.tmp))
|
$(Q) $(call DELFILE, kasan_globals.tmp))
|
||||||
$(Q) $(LD) $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
$(Q) $(LD) $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
||||||
|
@ -171,7 +171,7 @@ define LINK_ALLSYMS_KASAN
|
|||||||
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
||||||
$(Q) $(call DELFILE, allsyms.tmp))
|
$(Q) $(call DELFILE, allsyms.tmp))
|
||||||
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
||||||
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp
|
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp -a $(CONFIG_MM_KASAN_GLOBAL_ALIGN)
|
||||||
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
||||||
$(Q) $(call DELFILE, kasan_globals.tmp))
|
$(Q) $(call DELFILE, kasan_globals.tmp))
|
||||||
$(Q) $(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
$(Q) $(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
||||||
|
@ -173,7 +173,7 @@ define LINK_ALLSYMS_KASAN
|
|||||||
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
||||||
$(Q) $(call DELFILE, allsyms.tmp))
|
$(Q) $(call DELFILE, allsyms.tmp))
|
||||||
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
||||||
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp
|
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp -a $(CONFIG_MM_KASAN_GLOBAL_ALIGN)
|
||||||
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
||||||
$(Q) $(call DELFILE, kasan_globals.tmp))
|
$(Q) $(call DELFILE, kasan_globals.tmp))
|
||||||
$(Q) $(LD) $(LDENTRY) $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
$(Q) $(LD) $(LDENTRY) $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS) \
|
||||||
|
@ -399,7 +399,7 @@ define LINK_ALLSYMS_KASAN
|
|||||||
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
$(Q) $(call COMPILE, allsyms.tmp, allsyms$(OBJEXT), -x c)
|
||||||
$(Q) $(call DELFILE, allsyms.tmp))
|
$(Q) $(call DELFILE, allsyms.tmp))
|
||||||
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
$(if $(CONFIG_MM_KASAN_GLOBAL),
|
||||||
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp
|
$(Q) $(TOPDIR)/tools/kasan_global.py -e $(NUTTX) -o kasan_globals.tmp -a $(CONFIG_MM_KASAN_GLOBAL_ALIGN)
|
||||||
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
$(Q) $(call COMPILE, kasan_globals.tmp, kasan_globals$(OBJEXT) -fno-sanitize=kernel-address, -x c)
|
||||||
$(Q) $(call DELFILE, kasan_globals.tmp))
|
$(Q) $(call DELFILE, kasan_globals.tmp))
|
||||||
$(if $(CONFIG_HAVE_CXX),\
|
$(if $(CONFIG_HAVE_CXX),\
|
||||||
|
@ -341,6 +341,14 @@ config MM_KASAN_GLOBAL
|
|||||||
KEEP ( *(. data. rel. local.. LASAN0))
|
KEEP ( *(. data. rel. local.. LASAN0))
|
||||||
}", used to extract data generated by the compiler
|
}", used to extract data generated by the compiler
|
||||||
|
|
||||||
|
if MM_KASAN_GLOBAL
|
||||||
|
|
||||||
|
config MM_KASAN_GLOBAL_ALIGN
|
||||||
|
int "KASan global alignment"
|
||||||
|
default 32
|
||||||
|
|
||||||
|
endif # MM_KASAN_GLOBAL
|
||||||
|
|
||||||
config MM_KASAN_DISABLE_READ_PANIC
|
config MM_KASAN_DISABLE_READ_PANIC
|
||||||
bool "Disable panic on kasan read error"
|
bool "Disable panic on kasan read error"
|
||||||
default n
|
default n
|
||||||
|
@ -40,8 +40,6 @@
|
|||||||
#define KASAN_GLOBAL_LAST_WORD_MASK(end) \
|
#define KASAN_GLOBAL_LAST_WORD_MASK(end) \
|
||||||
(UINTPTR_MAX >> (-(end) & (KASAN_BITS_PER_WORD - 1)))
|
(UINTPTR_MAX >> (-(end) & (KASAN_BITS_PER_WORD - 1)))
|
||||||
|
|
||||||
#define KASAN_GLOBAL_SHADOW_SCALE (32)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -77,7 +75,7 @@ kasan_global_mem_to_shadow(FAR const void *ptr, size_t size,
|
|||||||
{
|
{
|
||||||
DEBUGASSERT(addr + size <= g_global_region[i]->end);
|
DEBUGASSERT(addr + size <= g_global_region[i]->end);
|
||||||
addr -= g_global_region[i]->begin;
|
addr -= g_global_region[i]->begin;
|
||||||
addr /= KASAN_GLOBAL_SHADOW_SCALE;
|
addr /= CONFIG_MM_KASAN_GLOBAL_ALIGN;
|
||||||
*bit = addr % KASAN_BITS_PER_WORD;
|
*bit = addr % KASAN_BITS_PER_WORD;
|
||||||
return (FAR uintptr_t *)
|
return (FAR uintptr_t *)
|
||||||
&g_global_region[i]->shadow[addr / KASAN_BITS_PER_WORD];
|
&g_global_region[i]->shadow[addr / KASAN_BITS_PER_WORD];
|
||||||
@ -101,15 +99,15 @@ kasan_global_is_poisoned(FAR const void *addr, size_t size)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size <= KASAN_GLOBAL_SHADOW_SCALE)
|
if (size <= CONFIG_MM_KASAN_GLOBAL_ALIGN)
|
||||||
{
|
{
|
||||||
return ((*p >> bit) & 1);
|
return ((*p >> bit) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD;
|
nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD;
|
||||||
mask = KASAN_GLOBAL_FIRST_WORD_MASK(bit);
|
mask = KASAN_GLOBAL_FIRST_WORD_MASK(bit);
|
||||||
size = ALIGN_UP(size, KASAN_GLOBAL_SHADOW_SCALE);
|
size = ALIGN_UP(size, CONFIG_MM_KASAN_GLOBAL_ALIGN);
|
||||||
size /= KASAN_GLOBAL_SHADOW_SCALE;
|
size /= CONFIG_MM_KASAN_GLOBAL_ALIGN;
|
||||||
|
|
||||||
while (size >= nbit)
|
while (size >= nbit)
|
||||||
{
|
{
|
||||||
|
@ -29,9 +29,6 @@ from elftools.elf.elffile import ELFFile
|
|||||||
|
|
||||||
debug = False
|
debug = False
|
||||||
|
|
||||||
# N-byte aligned shadow area 1 bit
|
|
||||||
KASAN_GLOBAL_ALIGN = 32
|
|
||||||
|
|
||||||
# The maximum gap that two data segments can tolerate
|
# The maximum gap that two data segments can tolerate
|
||||||
KASAN_MAX_DATA_GAP = 1 << 16
|
KASAN_MAX_DATA_GAP = 1 << 16
|
||||||
|
|
||||||
@ -68,10 +65,11 @@ KASAN_GLOBAL_STRUCT_64 = Struct(
|
|||||||
|
|
||||||
# Global configuration information
|
# Global configuration information
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self, outpath, elf, ldscript):
|
def __init__(self, outpath, elf, ldscript, align):
|
||||||
self.outpath = outpath
|
self.outpath = outpath
|
||||||
self.elf = elf
|
self.elf = elf
|
||||||
self.ldscript = ldscript
|
self.ldscript = ldscript
|
||||||
|
self.align = align
|
||||||
|
|
||||||
if self.elf is None or os.path.exists(self.elf) is False:
|
if self.elf is None or os.path.exists(self.elf) is False:
|
||||||
self.elf = None
|
self.elf = None
|
||||||
@ -97,43 +95,73 @@ class Config:
|
|||||||
|
|
||||||
|
|
||||||
class KASanRegion:
|
class KASanRegion:
|
||||||
def __init__(self, start, end) -> None:
|
def __init__(self, start, end, align, endian, bitwides) -> None:
|
||||||
self.start = start
|
self.start = start
|
||||||
self.end = end
|
self.end = end
|
||||||
self.size = int((end - start) // KASAN_GLOBAL_ALIGN // 8) + 1
|
self.align = align
|
||||||
self.shadow = bytearray(b"\x00" * self.size)
|
self.endian = endian
|
||||||
|
self.bitwides = bitwides
|
||||||
|
self.size = int((end - start) // self.align // self.bitwides) + 1
|
||||||
|
self.__shadow = [0] * self.size
|
||||||
|
|
||||||
def mark_bit(self, index, nbits):
|
def shadow(self) -> bytearray:
|
||||||
self.shadow[index] |= 1 << nbits
|
ret = bytearray()
|
||||||
|
for i in self.__shadow:
|
||||||
|
for j in range(self.bitwides // 8):
|
||||||
|
if self.endian == "little":
|
||||||
|
ret.append((i >> (j * 8)) & 0xFF)
|
||||||
|
else:
|
||||||
|
ret.append((i >> ((self.bitwides // 8 - j - 1) * 8)) & 0xFF)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def mark_bit(self, index, nbit, nbits):
|
||||||
|
for i in range(nbits):
|
||||||
|
self.__shadow[index] |= 1 << nbit
|
||||||
|
nbit += 1
|
||||||
|
if nbit == self.bitwides:
|
||||||
|
index += 1
|
||||||
|
nbit = 0
|
||||||
|
|
||||||
def poison(self, dict):
|
def poison(self, dict):
|
||||||
dict_size = dict["size"]
|
dict_size = dict["size"]
|
||||||
if dict_size % 32:
|
if dict_size % self.align:
|
||||||
dict_size = int((dict_size + 31) // 32) * 32
|
dict_size = int((dict_size + self.align - 1) // self.align) * self.align
|
||||||
|
|
||||||
|
distance = (dict["beg"] + dict_size - self.start) // self.align
|
||||||
|
|
||||||
|
# Index of the marked shadow area
|
||||||
|
index = int(distance // self.bitwides)
|
||||||
|
|
||||||
|
# The X-th bit of the specific byte marked
|
||||||
|
nbit = distance % self.bitwides
|
||||||
|
|
||||||
|
# Number of digits to be marked
|
||||||
|
nbits = (dict["size_with_redzone"] - dict_size) // self.align
|
||||||
|
|
||||||
distance = (dict["beg"] + dict_size - self.start) // KASAN_GLOBAL_ALIGN
|
|
||||||
index = int(distance // 8)
|
|
||||||
nbits = distance % 8
|
|
||||||
if debug:
|
if debug:
|
||||||
print(
|
print(
|
||||||
"regin: %08x addr: %08x size: %d bits: %d || poison index: %d nbits: %d"
|
"regin: %08x addr: %08x size: %d bits: %d || poison index: %d nbit: %d nbits: %d"
|
||||||
% (
|
% (
|
||||||
self.start,
|
self.start,
|
||||||
dict["beg"],
|
dict["beg"],
|
||||||
dict["size"],
|
dict["size"],
|
||||||
int(dict["size_with_redzone"] // KASAN_GLOBAL_ALIGN),
|
int(dict["size_with_redzone"] // self.align),
|
||||||
index,
|
index,
|
||||||
|
nbit,
|
||||||
nbits,
|
nbits,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Using 32bytes: with 1bit alignment,
|
# Using 32bytes: with 1bit alignment,
|
||||||
# only one bit of inaccessible area exists for each pair of global variables.
|
# only one bit of inaccessible area exists for each pair of global variables.
|
||||||
self.mark_bit(index, nbits)
|
self.mark_bit(index, nbit, nbits)
|
||||||
|
|
||||||
|
|
||||||
class KASanInfo:
|
class KASanInfo:
|
||||||
def __init__(self) -> None:
|
def __init__(self, align, endian, bitwides) -> None:
|
||||||
|
self.align = align
|
||||||
|
self.endian = endian
|
||||||
|
self.bitwides = bitwides
|
||||||
# Record the starting position of the merged data block
|
# Record the starting position of the merged data block
|
||||||
self.data_sections = []
|
self.data_sections = []
|
||||||
# Record the kasan region corresponding to each data block
|
# Record the kasan region corresponding to each data block
|
||||||
@ -158,13 +186,15 @@ class KASanInfo:
|
|||||||
end = i[1]
|
end = i[1]
|
||||||
if debug:
|
if debug:
|
||||||
print("KAsan Shadow Block: %08x ---- %08x" % (start, end))
|
print("KAsan Shadow Block: %08x ---- %08x" % (start, end))
|
||||||
self.regions.append(KASanRegion(start, end))
|
self.regions.append(
|
||||||
|
KASanRegion(start, end, self.align, self.endian, self.bitwides)
|
||||||
|
)
|
||||||
|
|
||||||
def mark_shadow(self, dict):
|
def mark_shadow(self, dict):
|
||||||
for i in self.regions:
|
for i in self.regions:
|
||||||
start = i.start
|
start = i.start
|
||||||
end = i.end
|
end = i.end
|
||||||
if start <= dict["beg"] and dict["beg"] <= end:
|
if start <= dict["beg"] and dict["beg"] + dict["size_with_redzone"] <= end:
|
||||||
i.poison(dict)
|
i.poison(dict)
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -227,10 +257,11 @@ def create_kasan_file(config: Config, region_list=[]):
|
|||||||
% (long_to_bytestring(config.bitwides, config.endian, region.end))
|
% (long_to_bytestring(config.bitwides, config.endian, region.end))
|
||||||
)
|
)
|
||||||
|
|
||||||
for j in range(len(region.shadow)):
|
shadow = region.shadow()
|
||||||
|
for j in range(len(shadow)):
|
||||||
if j % 8 == 0:
|
if j % 8 == 0:
|
||||||
file.write("\n")
|
file.write("\n")
|
||||||
file.write("0x%02x, " % (region.shadow[j]))
|
file.write("0x%02x, " % (shadow[j]))
|
||||||
|
|
||||||
file.write("\n};")
|
file.write("\n};")
|
||||||
|
|
||||||
@ -253,6 +284,7 @@ def parse_args() -> Config:
|
|||||||
global debug
|
global debug
|
||||||
parser = argparse.ArgumentParser(description="Build kasan global variable region")
|
parser = argparse.ArgumentParser(description="Build kasan global variable region")
|
||||||
parser.add_argument("-o", "--outpath", help="outpath")
|
parser.add_argument("-o", "--outpath", help="outpath")
|
||||||
|
parser.add_argument("-a", "--align", default=32, type=int, help="alignment")
|
||||||
parser.add_argument("-d", "--ldscript", help="ld script path(Only support sim)")
|
parser.add_argument("-d", "--ldscript", help="ld script path(Only support sim)")
|
||||||
parser.add_argument("-e", "--elffile", help="elffile")
|
parser.add_argument("-e", "--elffile", help="elffile")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -264,10 +296,11 @@ def parse_args() -> Config:
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
debug = args.debug
|
debug = args.debug
|
||||||
return Config(args.outpath, args.elffile, args.ldscript)
|
return Config(args.outpath, args.elffile, args.ldscript, args.align)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
config = parse_args()
|
config = parse_args()
|
||||||
if config.elf is None:
|
if config.elf is None:
|
||||||
handle_error(config)
|
handle_error(config)
|
||||||
@ -298,7 +331,7 @@ def main():
|
|||||||
dict_list = sorted(dict_list, key=lambda item: item["beg"])
|
dict_list = sorted(dict_list, key=lambda item: item["beg"])
|
||||||
|
|
||||||
# Merge all global variables to obtain several segments of the distribution range
|
# Merge all global variables to obtain several segments of the distribution range
|
||||||
kasan = KASanInfo()
|
kasan = KASanInfo(config.align, config.endian, config.bitwides)
|
||||||
for i in dict_list:
|
for i in dict_list:
|
||||||
kasan.merge_ranges(i)
|
kasan.merge_ranges(i)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user