From 16c173935fd0a787d90ddb58bdd4ed0d00505e98 Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Mon, 31 Jul 2017 21:30:47 -0700 Subject: [PATCH] libc fortify: make unistd.h use diagnose_if Also: - remove a NULL check. The bug that's been working around has been fixed since clang r298431, and our compiler is built from r300080, and - unwrap some function prototypes, per b/36984245. If you're interested, here's what a new error versus an old one looks like: https://drive.google.com/file/d/0B-8OBPboNJ_4MVdlYXdJbUFBYUk/view Bug: 12231437 Test: m checkbuild on bullhead internal master; CtsBionicTestCases show no new failures. Change-Id: Ibafe61198988b4c8bee8391bcdf01bcbc04233de --- libc/include/bits/fortify/unistd.h | 154 ++++++++--------------------- tests/fortify_compilation_test.cpp | 10 +- 2 files changed, 44 insertions(+), 120 deletions(-) diff --git a/libc/include/bits/fortify/unistd.h b/libc/include/bits/fortify/unistd.h index 5df67b496..ea5c89d34 100644 --- a/libc/include/bits/fortify/unistd.h +++ b/libc/include/bits/fortify/unistd.h @@ -60,34 +60,21 @@ ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTROD #endif #if defined(__clang__) -#define __error_if_overflows_ssizet(what) \ - __enable_if(what > SSIZE_MAX, #what " must be <= SSIZE_MAX") \ - __errorattr(#what " must be <= SSIZE_MAX") +#define __error_if_overflows_ssizet(what, fn) \ + __clang_error_if((what) > SSIZE_MAX, "in call to '" #fn "', '" #what "' must be <= SSIZE_MAX") -#define __enable_if_no_overflow_ssizet(what) \ - __enable_if((what) <= SSIZE_MAX, "enabled if " #what " <= SSIZE_MAX") - -#define __error_if_overflows_objectsize(what, objsize) \ - __enable_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && \ - (what) > (objsize), \ - "'" #what "' bytes overflows the given object") \ - __errorattr("'" #what "' bytes overflows the given object") - -__BIONIC_ERROR_FUNCTION_VISIBILITY -char* getcwd(char* buf, size_t size) __overloadable - __error_if_overflows_objectsize(size, __bos(buf)); +#define __error_if_overflows_objectsize(what, objsize, fn) \ + __clang_error_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && (what) > (objsize), \ + "in call to '" #fn "', '" #what "' bytes overflows the given object") #if __ANDROID_API__ >= __ANDROID_API_N__ __BIONIC_FORTIFY_INLINE -char* getcwd(char* const __pass_object_size buf, size_t size) __overloadable { +char* getcwd(char* const __pass_object_size buf, size_t size) + __overloadable + __error_if_overflows_objectsize(size, __bos(buf), getcwd) { size_t bos = __bos(buf); - /* - * Clang responds bos==0 if buf==NULL - * (https://llvm.org/bugs/show_bug.cgi?id=23277). Given that NULL is a valid - * value, we need to handle that. - */ - if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE || buf == NULL) { + if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { return __call_bypassing_fortify(getcwd)(buf, size); } @@ -96,18 +83,11 @@ char* getcwd(char* const __pass_object_size buf, size_t size) __overloadable { #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */ #if __ANDROID_API__ >= __ANDROID_API_M__ -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, - off_t offset) __overloadable { +ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, off_t offset) + __overloadable + __error_if_overflows_ssizet(count, pread) + __error_if_overflows_objectsize(count, __bos0(buf), pread) { size_t bos = __bos0(buf); if (count == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -117,18 +97,11 @@ ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos); } -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, - off64_t offset) __overloadable { +ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, off64_t offset) + __overloadable + __error_if_overflows_ssizet(count, pread64) + __error_if_overflows_objectsize(count, __bos0(buf), pread64) { size_t bos = __bos0(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -140,20 +113,11 @@ ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, #endif /* __ANDROID_API__ >= __ANDROID_API_M__ */ #if __ANDROID_API__ >= __ANDROID_API_N__ -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) - __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) - __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, - off_t offset) __overloadable { +ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, off_t offset) + __overloadable + __error_if_overflows_ssizet(count, pwrite) + __error_if_overflows_objectsize(count, __bos0(buf), pwrite) { size_t bos = __bos0(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -163,20 +127,11 @@ ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos); } -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset) - __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset) - __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, - size_t count, off64_t offset) __overloadable { +ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, size_t count, off64_t offset) + __overloadable + __error_if_overflows_ssizet(count, pwrite64) + __error_if_overflows_objectsize(count, __bos0(buf), pwrite64) { size_t bos = __bos0(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -188,18 +143,11 @@ ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */ #if __ANDROID_API__ >= __ANDROID_API_L__ -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t read(int fd, void* buf, size_t count) __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t read(int fd, void* buf, size_t count) __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count) - __overloadable { + __overloadable + __error_if_overflows_ssizet(count, read) + __error_if_overflows_objectsize(count, __bos0(buf), read) { size_t bos = __bos0(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -211,18 +159,11 @@ ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count) #endif /* __ANDROID_API__ >= __ANDROID_API_L__ */ #if __ANDROID_API__ >= __ANDROID_API_N__ -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t write(int fd, const void* buf, size_t count) __overloadable - __error_if_overflows_ssizet(count); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t write(int fd, const void* buf, size_t count) __overloadable - __enable_if_no_overflow_ssizet(count) - __error_if_overflows_objectsize(count, __bos0(buf)); - __BIONIC_FORTIFY_INLINE ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count) - __overloadable { + __overloadable + __error_if_overflows_ssizet(count, write) + __error_if_overflows_objectsize(count, __bos0(buf), write) { size_t bos = __bos0(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -234,18 +175,11 @@ ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count) #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */ #if __ANDROID_API__ >= __ANDROID_API_M__ -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t readlink(const char* path, char* buf, size_t size) __overloadable - __error_if_overflows_ssizet(size); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t readlink(const char* path, char* buf, size_t size) __overloadable - __enable_if_no_overflow_ssizet(size) - __error_if_overflows_objectsize(size, __bos(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t readlink(const char* path, char* const __pass_object_size buf, - size_t size) __overloadable { +ssize_t readlink(const char* path, char* const __pass_object_size buf, size_t size) + __overloadable + __error_if_overflows_ssizet(size, readlink) + __error_if_overflows_objectsize(size, __bos(buf), readlink) { size_t bos = __bos(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { @@ -255,21 +189,11 @@ ssize_t readlink(const char* path, char* const __pass_object_size buf, return __readlink_chk(path, buf, size, bos); } -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size) - __overloadable - __error_if_overflows_ssizet(size); - -__BIONIC_ERROR_FUNCTION_VISIBILITY -ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size) - __overloadable - __enable_if_no_overflow_ssizet(size) - __error_if_overflows_objectsize(size, __bos(buf)); - __BIONIC_FORTIFY_INLINE -ssize_t readlinkat(int dirfd, const char* path, - char* const __pass_object_size buf, size_t size) - __overloadable { +ssize_t readlinkat(int dirfd, const char* path, char* const __pass_object_size buf, size_t size) + __overloadable + __error_if_overflows_ssizet(size, readlinkat) + __error_if_overflows_objectsize(size, __bos(buf), readlinkat) { size_t bos = __bos(buf); if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) { diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp index 51074b2bc..bb2b7706c 100644 --- a/tests/fortify_compilation_test.cpp +++ b/tests/fortify_compilation_test.cpp @@ -199,7 +199,7 @@ void test_read() { char buf[4]; // NOLINTNEXTLINE(whitespace/line_length) // GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination - // CLANG: error: call to unavailable function 'read': 'count' bytes overflows the given object + // CLANG: error: in call to 'read', 'count' bytes overflows the given object read(0, buf, 6); } @@ -268,7 +268,7 @@ void test_getcwd() { char buf[4]; // NOLINTNEXTLINE(whitespace/line_length) // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination - // CLANG: error: call to unavailable function 'getcwd': 'size' bytes overflows the given object + // CLANG: error: in call to 'getcwd', 'size' bytes overflows the given object getcwd(buf, 5); } @@ -276,7 +276,7 @@ void test_pwrite64_size() { char buf[4] = {0}; // NOLINTNEXTLINE(whitespace/line_length) // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination - // CLANG: error: call to unavailable function 'pwrite64': 'count' bytes overflows the given object + // CLANG: error: in call to 'pwrite64', 'count' bytes overflows the given object pwrite64(STDOUT_FILENO, buf, 5, 0); } @@ -292,7 +292,7 @@ void test_pwrite64_too_big() { char buf[4] = {0}; // NOLINTNEXTLINE(whitespace/line_length) // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX - // CLANG: error: call to unavailable function 'pwrite64': count must be <= SSIZE_MAX + // CLANG: error: in call to 'pwrite64', 'count' must be <= SSIZE_MAX pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0); } @@ -300,7 +300,7 @@ void test_write_size() { char buf[4] = {0}; // NOLINTNEXTLINE(whitespace/line_length) // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination - // CLANG: error: call to unavailable function 'write': 'count' bytes overflows the given object + // CLANG: error: in call to 'write', 'count' bytes overflows the given object write(STDOUT_FILENO, buf, 5); }