From 24a67ef8265e5873c0967ded296a9e57ed9f2914 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 25 May 2023 14:19:21 -0400 Subject: sanity: Add wrappers for sanitizer interfaces --- src/config.h | 9 ------ src/dir.c | 12 ++------ src/fsade.c | 9 +++--- src/parse.c | 1 + src/sanity.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/stat.c | 18 ++++++------ src/xregex.c | 8 ++---- 7 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 src/sanity.h diff --git a/src/config.h b/src/config.h index f06300e..dbe3c74 100644 --- a/src/config.h +++ b/src/config.h @@ -191,15 +191,6 @@ static inline size_t flex_sizeof_impl(size_t align, size_t min, size_t offset, s return ret; } -/** - * Initialize a variable, unless sanitizers would detect uninitialized uses. - */ -#if __has_feature(memory_sanitizer) -# define uninit(var, value) var -#else -# define uninit(var, value) value -#endif - // Wrappers for attributes /** diff --git a/src/dir.c b/src/dir.c index d9ee63b..01d26db 100644 --- a/src/dir.c +++ b/src/dir.c @@ -5,6 +5,7 @@ #include "bfstd.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -18,18 +19,13 @@ #endif #if BFS_GETDENTS -# if __has_feature(memory_sanitizer) -# include -# endif # if __linux__ # include # endif /** getdents() syscall wrapper. */ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { -#if __has_feature(memory_sanitizer) - __msan_allocated_memory(buf, size); -#endif + sanitize_uninit(buf, size); #if __linux__ && __GLIBC__ && !__GLIBC_PREREQ(2, 30) ssize_t ret = syscall(SYS_getdents64, fd, buf, size); @@ -39,11 +35,9 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { ssize_t ret = getdents(fd, buf, size); #endif -#if __has_feature(memory_sanitizer) if (ret > 0) { - __msan_unpoison(buf, ret); + sanitize_init(buf, ret); } -#endif return ret; } diff --git a/src/fsade.c b/src/fsade.c index 4d67940..ba89b60 100644 --- a/src/fsade.c +++ b/src/fsade.c @@ -159,13 +159,12 @@ static int bfs_check_acl_type(acl_t acl, acl_type_t type) { #if __FreeBSD__ int trivial; + int ret = acl_is_trivial_np(acl, &trivial); -#if __has_feature(memory_sanitizer) - // msan seems to be missing an interceptor for acl_is_trivial_np() - trivial = 0; -#endif + // msan seems to be missing an interceptor for acl_is_trivial_np() + sanitize_init(&trivial); - if (acl_is_trivial_np(acl, &trivial) < 0) { + if (ret < 0) { return -1; } else if (trivial) { return 0; diff --git a/src/parse.c b/src/parse.c index 1a04e68..59a1e7d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -24,6 +24,7 @@ #include "opt.h" #include "printf.h" #include "pwcache.h" +#include "sanity.h" #include "stat.h" #include "typo.h" #include "xregex.h" diff --git a/src/sanity.h b/src/sanity.h new file mode 100644 index 0000000..5696036 --- /dev/null +++ b/src/sanity.h @@ -0,0 +1,89 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +/** + * Sanitizer interface. + */ + +#ifndef BFS_SANITY_H +#define BFS_SANITY_H + +#include "config.h" +#include + +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define SANITIZE_ADDRESS true +#endif + +#if __has_feature(memory_sanitizer) || defined(__SANITIZE_MEMORY__) +# define SANITIZE_MEMORY true +#endif + +#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) +# define SANITIZE_THREAD true +#endif + +// Call macro(ptr, size) or macro(ptr, sizeof(*ptr)) +#define SANITIZE_CALL(...) \ + SANITIZE_CALL_(__VA_ARGS__, ) + +#define SANITIZE_CALL_(macro, ptr, ...) \ + SANITIZE_CALL__(macro, ptr, __VA_ARGS__ sizeof(*(ptr)), ) + +#define SANITIZE_CALL__(macro, ptr, size, ...) \ + macro(ptr, size) + +#if SANITIZE_ADDRESS +# include + +/** + * sanitize_alloc(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as allocated. + */ +#define sanitize_alloc(...) SANITIZE_CALL(__asan_unpoison_memory_region, __VA_ARGS__) + +/** + * sanitize_free(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as free. + */ +#define sanitize_free(...) SANITIZE_CALL(__asan_poison_memory_region, __VA_ARGS__) + +#else +# define sanitize_alloc sanitize_uninit +# define sanitize_free sanitize_uninit +#endif + +#if SANITIZE_MEMORY +# include + +/** + * sanitize_init(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as initialized. + */ +#define sanitize_init(...) SANITIZE_CALL(__msan_unpoison, __VA_ARGS__) + +/** + * sanitize_uninit(ptr, size = sizeof(*ptr)) + * + * Mark a memory region as uninitialized. + */ +#define sanitize_uninit(...) SANITIZE_CALL(__msan_allocated_memory, __VA_ARGS__) + +#else +# define sanitize_init(...) +# define sanitize_uninit(...) +#endif + +/** + * Initialize a variable, unless sanitizers would detect uninitialized uses. + */ +#if SANITIZE_MEMORY +# define uninit(var, value) var +#else +# define uninit(var, value) value +#endif + +#endif // BFS_SANITY_H diff --git a/src/stat.c b/src/stat.c index 590a1d6..3f70e6c 100644 --- a/src/stat.c +++ b/src/stat.c @@ -5,6 +5,7 @@ #include "bfstd.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -132,17 +133,18 @@ static int bfs_stat_impl(int at_fd, const char *at_path, int at_flags, struct bf * Wrapper for the statx() system call, which had no glibc wrapper prior to 2.28. */ static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int mask, struct statx *buf) { -#if __has_feature(memory_sanitizer) - // -fsanitize=memory doesn't know about statx(), so tell it the memory - // got initialized - memset(buf, 0, sizeof(*buf)); -#endif - #if BFS_LIBC_STATX - return statx(at_fd, at_path, at_flags, mask, buf); + int ret = statx(at_fd, at_path, at_flags, mask, buf); #else - return syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); + int ret = syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); #endif + + if (ret == 0) { + // -fsanitize=memory doesn't know about statx() + sanitize_init(buf); + } + + return ret; } /** diff --git a/src/xregex.c b/src/xregex.c index 1143f23..ce59ff5 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -4,6 +4,7 @@ #include "xregex.h" #include "config.h" #include "diag.h" +#include "sanity.h" #include #include #include @@ -175,13 +176,10 @@ int bfs_regcomp(struct bfs_regex **preg, const char *pattern, enum bfs_regex_typ cflags |= REG_ICASE; } -#if __has_feature(memory_sanitizer) - // https://github.com/google/sanitizers/issues/1496 - memset(®ex->impl, 0, sizeof(regex->impl)); -#endif - regex->err = regcomp(®ex->impl, pattern, cflags); if (regex->err != 0) { + // https://github.com/google/sanitizers/issues/1496 + sanitize_init(®ex->impl); return -1; } #endif -- cgit v1.2.3