diff options
author | android-build-prod (mdb) <android-build-team-robot@google.com> | 2018-10-12 02:16:12 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-10-12 02:16:12 +0000 |
commit | 5a210f91fc61527bffad2ed04d848fc5faf32f7c (patch) | |
tree | c2c1e6d8f45fc5c7e67efda4c6e7d809c90b1902 | |
parent | cb8ed207d2bb6113a80fc7f27cd0beb8897f5192 (diff) | |
parent | dac3816fbec7a66d1265f60397b63ca441744183 (diff) | |
download | bionic-master-cuttlefish-testing-release.tar.gz |
Merge "Snap for 5061196 from 391af2cefea88abe7eccff8edd0ae06c653bef5e to master-cuttlefish-testing-release" into master-cuttlefish-testing-releasemaster-cuttlefish-testing-release
-rw-r--r-- | libc/bionic/libc_init_dynamic.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/poll.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/sigaction.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/signal.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/sigprocmask.cpp | 9 | ||||
-rw-r--r-- | libc/include/bits/sysconf.h | 1 | ||||
-rw-r--r-- | libc/private/bionic_globals.h | 5 | ||||
-rw-r--r-- | libc/private/sigrtmin.h | 28 | ||||
-rw-r--r-- | linker/linker.cpp | 46 | ||||
-rw-r--r-- | linker/linker.h | 2 | ||||
-rw-r--r-- | linker/linker_logger.cpp | 4 | ||||
-rw-r--r-- | linker/linker_main.cpp | 212 | ||||
-rw-r--r-- | linker/linker_main.h | 2 | ||||
-rw-r--r-- | linker/linker_phdr.h | 1 | ||||
-rw-r--r-- | tests/Android.bp | 2 | ||||
-rw-r--r-- | tests/SignalUtils.h | 9 | ||||
-rw-r--r-- | tests/dl_test.cpp | 48 | ||||
-rw-r--r-- | tests/libs/Android.bp | 16 | ||||
-rw-r--r-- | tests/libs/Android.build.dlext_testzip.mk | 4 | ||||
-rw-r--r-- | tests/libs/exec_linker_helper.cpp | 43 | ||||
-rw-r--r-- | tests/libs/exec_linker_helper_lib.cpp | 34 | ||||
-rw-r--r-- | tests/setjmp_test.cpp | 2 | ||||
-rw-r--r-- | tests/signal_test.cpp | 235 | ||||
-rw-r--r-- | tests/spawn_test.cpp | 19 | ||||
-rw-r--r-- | tests/unistd_test.cpp | 2 | ||||
-rw-r--r-- | tests/utils.h | 12 |
26 files changed, 532 insertions, 220 deletions
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 0def359d0..5f763546c 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -133,7 +133,9 @@ __noreturn void __libc_init(void* raw_args, __cxa_atexit(__libc_fini,structors->fini_array,nullptr); } - exit(slingshot(args.argc, args.argv, args.envp)); + exit(slingshot(args.argc - __libc_shared_globals->initial_linker_arg_count, + args.argv + __libc_shared_globals->initial_linker_arg_count, + args.envp)); } extern "C" uint32_t android_get_application_target_sdk_version(); diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp index 3df8b1889..41b26571b 100644 --- a/libc/bionic/poll.cpp +++ b/libc/bionic/poll.cpp @@ -71,7 +71,7 @@ int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* sigset64_t mutable_ss; sigset64_t* mutable_ss_ptr = nullptr; if (ss != nullptr) { - mutable_ss = filter_reserved_signals(*ss); + mutable_ss = filter_reserved_signals(*ss, SIG_SETMASK); mutable_ss_ptr = &mutable_ss; } @@ -121,7 +121,7 @@ int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_f sigset64_t mutable_ss; sigset64_t* mutable_ss_ptr = nullptr; if (ss != nullptr) { - mutable_ss = filter_reserved_signals(*ss); + mutable_ss = filter_reserved_signals(*ss, SIG_SETMASK); mutable_ss_ptr = &mutable_ss; } diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp index fb57d1c5e..42dcccdf6 100644 --- a/libc/bionic/sigaction.cpp +++ b/libc/bionic/sigaction.cpp @@ -43,7 +43,7 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga if (bionic_new_action != nullptr) { kernel_new_action.sa_flags = bionic_new_action->sa_flags; kernel_new_action.sa_handler = bionic_new_action->sa_handler; - kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask); + kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask, SIG_SETMASK); #if defined(SA_RESTORER) kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; #if defined(__aarch64__) @@ -122,7 +122,7 @@ int sigaction64(int signal, const struct sigaction64* bionic_new, struct sigacti kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; } #endif - kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask); + kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask, SIG_SETMASK); } return __rt_sigaction(signal, diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp index 175182b7a..d6be09a6f 100644 --- a/libc/bionic/signal.cpp +++ b/libc/bionic/signal.cpp @@ -263,7 +263,7 @@ int sigsuspend64(const sigset64_t* set) { sigset64_t mutable_set; sigset64_t* mutable_set_ptr = nullptr; if (set) { - mutable_set = filter_reserved_signals(*set); + mutable_set = filter_reserved_signals(*set, SIG_SETMASK); mutable_set_ptr = &mutable_set; } return __rt_sigsuspend(mutable_set_ptr, sizeof(*set)); @@ -279,7 +279,7 @@ int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeo sigset64_t mutable_set; sigset64_t* mutable_set_ptr = nullptr; if (set) { - mutable_set = filter_reserved_signals(*set); + mutable_set = filter_reserved_signals(*set, SIG_SETMASK); mutable_set_ptr = &mutable_set; } return __rt_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set)); diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp index 36866f36f..5f70f328f 100644 --- a/libc/bionic/sigprocmask.cpp +++ b/libc/bionic/sigprocmask.cpp @@ -26,6 +26,7 @@ * SUCH DAMAGE. */ +#include <errno.h> #include <signal.h> #include "private/sigrtmin.h" @@ -65,10 +66,16 @@ int sigprocmask(int how, int sigprocmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) __attribute__((__noinline__)) { + // how is only checked for validity if new_set is provided. + if (new_set && how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) { + errno = EINVAL; + return -1; + } + sigset64_t mutable_new_set; sigset64_t* mutable_new_set_ptr = nullptr; if (new_set) { - mutable_new_set = filter_reserved_signals(*new_set); + mutable_new_set = filter_reserved_signals(*new_set, how); mutable_new_set_ptr = &mutable_new_set; } return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set)); diff --git a/libc/include/bits/sysconf.h b/libc/include/bits/sysconf.h index 2cbbb11e9..8607adff1 100644 --- a/libc/include/bits/sysconf.h +++ b/libc/include/bits/sysconf.h @@ -73,6 +73,7 @@ #define _SC_XOPEN_LEGACY 0x0024 #define _SC_ATEXIT_MAX 0x0025 #define _SC_IOV_MAX 0x0026 +#define _SC_UIO_MAXIOV _SC_IOV_MAX #define _SC_PAGESIZE 0x0027 #define _SC_PAGE_SIZE 0x0028 #define _SC_XOPEN_UNIX 0x0029 diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h index eee33c93f..8c005512b 100644 --- a/libc/private/bionic_globals.h +++ b/libc/private/bionic_globals.h @@ -47,6 +47,11 @@ __LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals; // Globals shared between the dynamic linker and libc.so. struct libc_shared_globals { FdTable fd_table; + + // When the linker is invoked on a binary (e.g. `linker64 /system/bin/date`), + // record the number of arguments passed to the linker itself rather than to + // the program it's loading. Typically 0, sometimes 1. + int initial_linker_arg_count; }; __LIBC_HIDDEN__ extern libc_shared_globals* __libc_shared_globals; diff --git a/libc/private/sigrtmin.h b/libc/private/sigrtmin.h index ea8673db8..431a1dd95 100644 --- a/libc/private/sigrtmin.h +++ b/libc/private/sigrtmin.h @@ -32,6 +32,8 @@ #include <signal.h> +#include "bionic_macros.h" + // Realtime signals reserved for internal use: // 32 (__SIGRTMIN + 0) POSIX timers // 33 (__SIGRTMIN + 1) libbacktrace @@ -42,9 +44,29 @@ // in <android/legacy_signal_inlines.h> to match. #define __SIGRT_RESERVED 4 -static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset) { - for (int signo = __SIGRTMIN; signo < __SIGRTMIN + __SIGRT_RESERVED; ++signo) { - sigdelset64(&sigset, signo); +static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) { + int (*block)(sigset64_t*, int); + int (*unblock)(sigset64_t*, int); + switch (how) { + case SIG_BLOCK: + __BIONIC_FALLTHROUGH; + case SIG_SETMASK: + block = sigaddset64; + unblock = sigdelset64; + break; + + case SIG_UNBLOCK: + block = sigdelset64; + unblock = sigaddset64; + break; } + + // The POSIX timer signal must be blocked. + block(&sigset, __SIGRTMIN + 0); + + // Everything else must remain unblocked. + unblock(&sigset, __SIGRTMIN + 1); + unblock(&sigset, __SIGRTMIN + 2); + unblock(&sigset, __SIGRTMIN + 3); return sigset; } diff --git a/linker/linker.cpp b/linker/linker.cpp index 277b82382..b605ed9ff 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -289,7 +289,7 @@ void NamespaceListAllocator::free(LinkedListEntry<android_namespace_t>* entry) { } soinfo* soinfo_alloc(android_namespace_t* ns, const char* name, - struct stat* file_stat, off64_t file_offset, + const struct stat* file_stat, off64_t file_offset, uint32_t rtld_flags) { if (strlen(name) >= PATH_MAX) { async_safe_fatal("library name \"%s\" too long", name); @@ -1011,6 +1011,28 @@ static bool format_path(char* buf, size_t buf_size, const char* path, const char return true; } +static int open_library_at_path(ZipArchiveCache* zip_archive_cache, + const char* path, off64_t* file_offset, + std::string* realpath) { + int fd = -1; + if (strstr(path, kZipFileSeparator) != nullptr) { + fd = open_library_in_zipfile(zip_archive_cache, path, file_offset, realpath); + } + + if (fd == -1) { + fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)); + if (fd != -1) { + *file_offset = 0; + if (!realpath_fd(fd, realpath)) { + PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", path); + *realpath = path; + } + } + } + + return fd; +} + static int open_library_on_paths(ZipArchiveCache* zip_archive_cache, const char* name, off64_t* file_offset, const std::vector<std::string>& paths, @@ -1021,22 +1043,7 @@ static int open_library_on_paths(ZipArchiveCache* zip_archive_cache, continue; } - int fd = -1; - if (strstr(buf, kZipFileSeparator) != nullptr) { - fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset, realpath); - } - - if (fd == -1) { - fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC)); - if (fd != -1) { - *file_offset = 0; - if (!realpath_fd(fd, realpath)) { - PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", buf); - *realpath = buf; - } - } - } - + int fd = open_library_at_path(zip_archive_cache, buf, file_offset, realpath); if (fd != -1) { return fd; } @@ -1098,6 +1105,11 @@ static int open_library(android_namespace_t* ns, return fd; } +int open_executable(const char* path, off64_t* file_offset, std::string* realpath) { + ZipArchiveCache zip_archive_cache; + return open_library_at_path(&zip_archive_cache, path, file_offset, realpath); +} + const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) { #if !defined(__LP64__) // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029 diff --git a/linker/linker.h b/linker/linker.h index 7aa7e5fc8..dd45f6721 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -103,6 +103,8 @@ soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si); soinfo* find_containing_library(const void* p); +int open_executable(const char* path, off64_t* file_offset, std::string* realpath); + void do_android_get_LD_LIBRARY_PATH(char*, size_t); void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); void* do_dlopen(const char* name, diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp index 4c6603b6a..d0e507218 100644 --- a/linker/linker_logger.cpp +++ b/linker/linker_logger.cpp @@ -106,8 +106,8 @@ void LinkerLogger::ResetState() { static CachedProperty debug_ld_all("debug.ld.all"); flags_ |= ParseProperty(debug_ld_all.Get()); - // Ignore processes started without argv (http://b/33276926). - if (g_argv[0] == nullptr) { + // Safeguard against a NULL g_argv. Ignore processes started without argv (http://b/33276926). + if (g_argv == nullptr || g_argv[0] == nullptr) { return; } diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index c5e0b9635..f7c496a25 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -35,10 +35,12 @@ #include "linker_phdr.h" #include "linker_utils.h" +#include "private/bionic_auxv.h" #include "private/bionic_globals.h" #include "private/bionic_tls.h" #include "private/KernelArgumentBlock.h" +#include "android-base/unique_fd.h" #include "android-base/strings.h" #include "android-base/stringprintf.h" #ifdef __ANDROID__ @@ -52,7 +54,7 @@ extern void __libc_init_globals(KernelArgumentBlock&); extern void __libc_init_AT_SECURE(KernelArgumentBlock&); -extern "C" void _start(); +__LIBC_HIDDEN__ extern "C" void _start(); static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); @@ -182,22 +184,41 @@ static void init_link_map_head(soinfo& info, const char* linker_path) { extern "C" int __system_properties_init(void); -static const char* get_executable_path() { - static std::string executable_path; - if (executable_path.empty()) { - if (!is_init()) { - char path[PATH_MAX]; - ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path)); - if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) { - async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno)); - } - executable_path = std::string(path, path_len); - } else { - executable_path = "/init"; +struct ExecutableInfo { + std::string path; + struct stat file_stat; + const ElfW(Phdr)* phdr; + size_t phdr_count; + ElfW(Addr) entry_point; +}; + +static ExecutableInfo get_executable_info(KernelArgumentBlock& args) { + ExecutableInfo result = {}; + + if (is_init()) { + // /proc fs is not mounted when init starts. Therefore we can't use + // /proc/self/exe for init. + stat("/init", &result.file_stat); + result.path = "/init"; + } else { + // Stat "/proc/self/exe" instead of executable_path because + // the executable could be unlinked by this point and it should + // not cause a crash (see http://b/31084669) + if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &result.file_stat)) != 0) { + async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno)); + } + char path[PATH_MAX]; + ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path)); + if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) { + async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno)); } + result.path = std::string(path, path_len); } - return executable_path.c_str(); + result.phdr = reinterpret_cast<const ElfW(Phdr)*>(args.getauxval(AT_PHDR)); + result.phdr_count = args.getauxval(AT_PHNUM); + result.entry_point = args.getauxval(AT_ENTRY); + return result; } #if defined(__LP64__) @@ -206,21 +227,62 @@ static char kLinkerPath[] = "/system/bin/linker64"; static char kLinkerPath[] = "/system/bin/linker"; #endif -static void __linker_cannot_link(const char* argv0) { - async_safe_format_fd(STDERR_FILENO, - "CANNOT LINK EXECUTABLE \"%s\": %s\n", - argv0, - linker_get_error_buffer()); - - async_safe_format_log(ANDROID_LOG_FATAL, - "linker", - "CANNOT LINK EXECUTABLE \"%s\": %s", - argv0, - linker_get_error_buffer()); +__printflike(1, 2) +static void __linker_error(const char* fmt, ...) { + va_list ap; + + va_start(ap, fmt); + async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap); + va_end(ap); + + va_start(ap, fmt); + async_safe_format_log_va_list(ANDROID_LOG_FATAL, "linker", fmt, ap); + va_end(ap); + _exit(EXIT_FAILURE); } -static ElfW(Addr) linker_main(KernelArgumentBlock& args) { +static void __linker_cannot_link(const char* argv0) { + __linker_error("CANNOT LINK EXECUTABLE \"%s\": %s\n", + argv0, + linker_get_error_buffer()); +} + +// Load an executable. Normally the kernel has already loaded the executable when the linker +// starts. The linker can be invoked directly on an executable, though, and then the linker must +// load it. This function doesn't load dependencies or resolve relocations. +static ExecutableInfo load_executable(const char* orig_path) { + ExecutableInfo result = {}; + + if (orig_path[0] != '/') { + __linker_error("error: expected absolute path: \"%s\"\n", orig_path); + } + + off64_t file_offset; + android::base::unique_fd fd(open_executable(orig_path, &file_offset, &result.path)); + if (fd.get() == -1) { + __linker_error("error: unable to open file \"%s\"\n", orig_path); + } + + if (TEMP_FAILURE_RETRY(fstat(fd.get(), &result.file_stat)) == -1) { + __linker_error("error: unable to stat \"%s\": %s\n", result.path.c_str(), strerror(errno)); + } + + ElfReader elf_reader; + if (!elf_reader.Read(result.path.c_str(), fd.get(), file_offset, result.file_stat.st_size)) { + __linker_error("error: %s\n", linker_get_error_buffer()); + } + if (!elf_reader.Load(nullptr)) { + __linker_error("error: %s\n", linker_get_error_buffer()); + } + + result.phdr = elf_reader.loaded_phdr(); + result.phdr_count = elf_reader.phdr_count(); + result.entry_point = elf_reader.entry_point(); + return result; +} + +static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) { ProtectedDataGuard guard; #if TIMING @@ -274,31 +336,25 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args) { } } - struct stat file_stat; - // Stat "/proc/self/exe" instead of executable_path because - // the executable could be unlinked by this point and it should - // not cause a crash (see http://b/31084669) - if (!is_init()) { - if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) { - async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno)); - } - } else { - // /proc fs is not mounted when init starts. Therefore we can't use - // /proc/self/exe for init. - stat("/init", &file_stat); - } + const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) : + get_executable_info(args); + + // Assign to a static variable for the sake of the debug map, which needs + // a C-style string to last until the program exits. + static std::string exe_path = exe_info.path; // Initialize the main exe's soinfo. - const char* executable_path = get_executable_path(); - soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL); + soinfo* si = soinfo_alloc(&g_default_namespace, + exe_path.c_str(), &exe_info.file_stat, + 0, RTLD_GLOBAL); somain = si; - si->phdr = reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR)); - si->phnum = args.getauxval(AT_PHNUM); + si->phdr = exe_info.phdr; + si->phnum = exe_info.phdr_count; get_elf_base_from_phdr(si->phdr, si->phnum, &si->base, &si->load_bias); si->size = phdr_table_get_load_size(si->phdr, si->phnum); si->dynamic = nullptr; si->set_main_executable(); - init_link_map_head(*si, executable_path); + init_link_map_head(*si, exe_path.c_str()); // Register the main executable and the linker upfront to have // gdb aware of them before loading the rest of the dependency @@ -336,7 +392,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args) { parse_LD_LIBRARY_PATH(ldpath_env); parse_LD_PRELOAD(ldpreload_env); - std::vector<android_namespace_t*> namespaces = init_default_namespaces(executable_path); + std::vector<android_namespace_t*> namespaces = init_default_namespaces(exe_path.c_str()); if (!si->prelink_image()) __linker_cannot_link(g_argv[0]); @@ -437,7 +493,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args) { fflush(stdout); #endif - ElfW(Addr) entry = args.getauxval(AT_ENTRY); + ElfW(Addr) entry = exe_info.entry_point; TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry)); return entry; } @@ -502,12 +558,22 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) { __libc_init_sysinfo(args); #endif + // When the linker is run by itself (rather than as an interpreter for + // another program), AT_BASE is 0. ElfW(Addr) linker_addr = args.getauxval(AT_BASE); if (linker_addr == 0) { - // When the linker is run by itself (rather than as an interpreter for - // another program), AT_BASE is 0. In that case, the AT_PHDR and AT_PHNUM - // aux values describe the linker, so use the phdr to find the linker's - // base address. + // Detect an attempt to run the linker on itself (e.g. + // `linker64 /system/bin/linker64`). If the kernel loaded this instance of + // the linker, then AT_ENTRY will refer to &_start. If it doesn't, then + // something else must have loaded this instance of the linker. It's + // simpler if we only allow one copy of the linker to be loaded at a time. + if (args.getauxval(AT_ENTRY) != reinterpret_cast<uintptr_t>(&_start)) { + // The first linker already relocated this one and set up TLS, so we don't + // need further libc initialization. + __linker_error("error: linker cannot load itself\n"); + } + // Otherwise, the AT_PHDR and AT_PHNUM aux values describe this linker + // instance, so use the phdr to find the linker's base address. ElfW(Addr) load_bias; get_elf_base_from_phdr( reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR)), args.getauxval(AT_PHNUM), @@ -565,28 +631,38 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) // Initialize the linker's static libc's globals __libc_init_globals(args); - // store argc/argv/envp to use them for calling constructors - g_argc = args.argc; - g_argv = args.argv; - g_envp = args.envp; - // Initialize the linker's own global variables tmp_linker_so.call_constructors(); - // If the linker is not acting as PT_INTERP entry_point is equal to - // _start. Which means that the linker is running as an executable and - // already linked by PT_INTERP. - // - // This happens when user tries to run 'adb shell /system/bin/linker' - // see also https://code.google.com/p/android/issues/detail?id=63174 - ElfW(Addr) entry_point = args.getauxval(AT_ENTRY); - if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) { - async_safe_format_fd(STDOUT_FILENO, - "This is %s, the helper program for dynamic executables.\n", - args.argv[0]); - exit(0); + // When the linker is run directly rather than acting as PT_INTERP, parse + // arguments and determine the executable to load. When it's instead acting + // as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the + // linker's _start. + const char* exe_to_load = nullptr; + if (args.getauxval(AT_ENTRY) == reinterpret_cast<uintptr_t>(&_start)) { + if (args.argc <= 1 || !strcmp(args.argv[1], "--help")) { + async_safe_format_fd(STDOUT_FILENO, + "Usage: %s program [arguments...]\n" + " %s path.zip!/program [arguments...]\n" + "\n" + "A helper program for linking dynamic executables. Typically, the kernel loads\n" + "this program because it's the PT_INTERP of a dynamic executable.\n" + "\n" + "This program can also be run directly to load and run a dynamic executable. The\n" + "executable can be inside a zip file if it's stored uncompressed and at a\n" + "page-aligned offset.\n", + args.argv[0], args.argv[0]); + exit(0); + } + exe_to_load = args.argv[1]; + __libc_shared_globals->initial_linker_arg_count = 1; } + // store argc/argv/envp to use them for calling constructors + g_argc = args.argc - __libc_shared_globals->initial_linker_arg_count; + g_argv = args.argv + __libc_shared_globals->initial_linker_arg_count; + g_envp = args.envp; + // Initialize static variables. Note that in order to // get correct libdl_info we need to call constructors // before get_libdl_info(). @@ -595,7 +671,7 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) init_link_map_head(*solinker, kLinkerPath); args.abort_message_ptr = &g_abort_message; - ElfW(Addr) start_address = linker_main(args); + ElfW(Addr) start_address = linker_main(args, exe_to_load); INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address)); diff --git a/linker/linker_main.h b/linker/linker_main.h index b37b9472f..47d4bdb3e 100644 --- a/linker/linker_main.h +++ b/linker/linker_main.h @@ -50,7 +50,7 @@ class ElfReader; std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path); soinfo* soinfo_alloc(android_namespace_t* ns, const char* name, - struct stat* file_stat, off64_t file_offset, + const struct stat* file_stat, off64_t file_offset, uint32_t rtld_flags); bool find_libraries(android_namespace_t* ns, diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index 9b9ce94e6..0eee08933 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -54,6 +54,7 @@ class ElfReader { const ElfW(Dyn)* dynamic() const { return dynamic_; } const char* get_string(ElfW(Word) index) const; bool is_mapped_by_caller() const { return mapped_by_caller_; } + ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; } private: bool ReadElfHeader(); diff --git a/tests/Android.bp b/tests/Android.bp index 5ba6b3dad..4ad51da20 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -466,6 +466,8 @@ cc_test { required: [ "cfi_test_helper", "cfi_test_helper2", + "exec_linker_helper", + "exec_linker_helper_lib", "libtest_dt_runpath_a", "libtest_dt_runpath_b", "libtest_dt_runpath_c", diff --git a/tests/SignalUtils.h b/tests/SignalUtils.h index ece28ba16..a2faf0a78 100644 --- a/tests/SignalUtils.h +++ b/tests/SignalUtils.h @@ -55,3 +55,12 @@ class SignalMaskRestorer { private: sigset64_t old_mask_; }; + +// uint64_t equivalents of sigsetops. +static inline void SignalSetAdd(uint64_t* sigset, int signo) { + *sigset |= 1ULL << (signo - 1); +} + +static inline void SignalSetDel(uint64_t* sigset, int signo) { + *sigset &= ~(1ULL << (signo - 1)); +} diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp index 44fab0161..cb98caede 100644 --- a/tests/dl_test.cpp +++ b/tests/dl_test.cpp @@ -79,21 +79,61 @@ TEST(dl, lib_does_not_preempt_global_protected) { ASSERT_EQ(3370318, lib_global_protected_get_serial()); } -TEST(dl, exec_linker) { #if defined(__BIONIC__) #if defined(__LP64__) static constexpr const char* kPathToLinker = "/system/bin/linker64"; #else static constexpr const char* kPathToLinker = "/system/bin/linker"; #endif +#endif + +TEST(dl, exec_linker) { +#if defined(__BIONIC__) + std::string usage_prefix = std::string("Usage: ") + kPathToLinker; + ExecTestHelper eth; + eth.SetArgs({ kPathToLinker, nullptr }); + eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, nullptr); + ASSERT_EQ(0u, eth.GetOutput().find(usage_prefix)) << "Test output:\n" << eth.GetOutput(); +#endif +} + +TEST(dl, exec_linker_load_file) { +#if defined(__BIONIC__) + std::string helper = GetTestlibRoot() + + "/exec_linker_helper/exec_linker_helper"; + std::string expected_output = + "ctor: argc=1 argv[0]=" + helper + "\n" + + "main: argc=1 argv[0]=" + helper + "\n" + + "helper_func called\n"; ExecTestHelper eth; - std::string expected_output = std::string("This is ") + kPathToLinker + - ", the helper program for dynamic executables.\n"; - eth.SetArgs( { kPathToLinker, nullptr }); + eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr }); eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str()); #endif } +TEST(dl, exec_linker_load_from_zip) { +#if defined(__BIONIC__) + std::string helper = GetTestlibRoot() + + "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip!/libdir/exec_linker_helper"; + std::string expected_output = + "ctor: argc=1 argv[0]=" + helper + "\n" + + "main: argc=1 argv[0]=" + helper + "\n" + + "helper_func called\n"; + ExecTestHelper eth; + eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr }); + eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str()); +#endif +} + +TEST(dl, exec_linker_load_self) { +#if defined(__BIONIC__) + std::string error_message = "error: linker cannot load itself\n"; + ExecTestHelper eth; + eth.SetArgs({ kPathToLinker, kPathToLinker, nullptr }); + eth.Run([&]() { execve(kPathToLinker, eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str()); +#endif +} + TEST(dl, preinit_system_calls) { #if defined(__BIONIC__) std::string helper = GetTestlibRoot() + diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp index 2d35c510d..5c4eb4285 100644 --- a/tests/libs/Android.bp +++ b/tests/libs/Android.bp @@ -852,3 +852,19 @@ cc_test_library { defaults: ["bionic_testlib_defaults"], srcs: ["ld_config_test_helper_lib3.cpp"], } + +cc_test { + name: "exec_linker_helper", + host_supported: false, + defaults: ["bionic_testlib_defaults"], + srcs: ["exec_linker_helper.cpp"], + shared_libs: ["exec_linker_helper_lib"], + ldflags: ["-Wl,--rpath,${ORIGIN}/.."], +} + +cc_test_library { + name: "exec_linker_helper_lib", + host_supported: false, + defaults: ["bionic_testlib_defaults"], + srcs: ["exec_linker_helper_lib.cpp"], +} diff --git a/tests/libs/Android.build.dlext_testzip.mk b/tests/libs/Android.build.dlext_testzip.mk index 62ed4c7e3..19fd64b61 100644 --- a/tests/libs/Android.build.dlext_testzip.mk +++ b/tests/libs/Android.build.dlext_testzip.mk @@ -32,7 +32,9 @@ include $(BUILD_SYSTEM)/base_rules.mk my_shared_libs := \ $(call intermediates-dir-for,SHARED_LIBRARIES,libdlext_test_zip,,,$(bionic_2nd_arch_prefix))/libdlext_test_zip.so \ - $(call intermediates-dir-for,SHARED_LIBRARIES,libatest_simple_zip,,,$(bionic_2nd_arch_prefix))/libatest_simple_zip.so + $(call intermediates-dir-for,SHARED_LIBRARIES,libatest_simple_zip,,,$(bionic_2nd_arch_prefix))/libatest_simple_zip.so \ + $(call intermediates-dir-for,NATIVE_TESTS,exec_linker_helper,,,$(bionic_2nd_arch_prefix))/exec_linker_helper \ + $(call intermediates-dir-for,SHARED_LIBRARIES,exec_linker_helper_lib,,,$(bionic_2nd_arch_prefix))/exec_linker_helper_lib.so $(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBS := $(my_shared_libs) $(LOCAL_BUILT_MODULE): $(my_shared_libs) $(BIONIC_TESTS_ZIPALIGN) diff --git a/tests/libs/exec_linker_helper.cpp b/tests/libs/exec_linker_helper.cpp new file mode 100644 index 000000000..01a61e091 --- /dev/null +++ b/tests/libs/exec_linker_helper.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdio.h> + +extern "C" void _start(); +const char* helper_func(); + +__attribute__((constructor)) +static void ctor(int argc, char* argv[]) { + printf("ctor: argc=%d argv[0]=%s\n", argc, argv[0]); +} + +int main(int argc, char* argv[]) { + printf("main: argc=%d argv[0]=%s\n", argc, argv[0]); + printf("%s\n", helper_func()); + return 0; +} diff --git a/tests/libs/exec_linker_helper_lib.cpp b/tests/libs/exec_linker_helper_lib.cpp new file mode 100644 index 000000000..b46f48272 --- /dev/null +++ b/tests/libs/exec_linker_helper_lib.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// Verify that the linker can find exec_linker_helper_lib.so using the +// executable's $ORIGIN runpath, even when the executable is inside a zip file. + +const char* helper_func() { + return "helper_func called"; +} diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp index 05339a627..dde0be162 100644 --- a/tests/setjmp_test.cpp +++ b/tests/setjmp_test.cpp @@ -74,6 +74,8 @@ struct SigSets { sigset64_t ss; sigemptyset64(&ss); sigaddset64(&ss, SIGUSR1 + offset); + // TIMER_SIGNAL. + sigaddset64(&ss, __SIGRTMIN); sigaddset64(&ss, SIGRTMIN + offset); return ss; } diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 52a097bf3..dd27aef33 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -22,6 +22,7 @@ #include <thread> +#include <android-base/macros.h> #include <gtest/gtest.h> #include "SignalUtils.h" @@ -339,6 +340,17 @@ TEST(signal, sigaction64_SIGRTMIN) { static void ClearSignalMask() { uint64_t sigset = 0; + SignalSetAdd(&sigset, __SIGRTMIN); + if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) { + abort(); + } +} + +static void FillSignalMask() { + uint64_t sigset = ~0ULL; + for (int signo = __SIGRTMIN + 1; signo < SIGRTMIN; ++signo) { + SignalSetDel(&sigset, signo); + } if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) { abort(); } @@ -352,40 +364,27 @@ static uint64_t GetSignalMask() { return sigset; } -enum class SignalMaskFunctionType { - RtAware, - RtNonaware, -}; - -#if defined(__LP64__) || !defined(__BIONIC__) -constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtAware; -#else -constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtNonaware; -#endif - -static void TestSignalMaskFiltered(uint64_t sigset, SignalMaskFunctionType type) { - for (int signo = 1; signo <= 64; ++signo) { +static void TestSignalMaskFiltered(uint64_t sigset) { +#if defined(__BIONIC__) + for (int signo = __SIGRTMIN; signo < SIGRTMIN; ++signo) { bool signal_blocked = sigset & (1ULL << (signo - 1)); - if (signo == SIGKILL || signo == SIGSTOP) { - // SIGKILL and SIGSTOP shouldn't be blocked. - EXPECT_EQ(false, signal_blocked) << "signal " << signo; - } else if (signo < __SIGRTMIN) { - // Everything else should be blocked. + if (signo == __SIGRTMIN) { + // TIMER_SIGNAL must be blocked. EXPECT_EQ(true, signal_blocked) << "signal " << signo; - } else if (signo >= __SIGRTMIN && signo < SIGRTMIN) { - // Reserved signals must not be blocked. + } else { + // The other reserved signals must not be blocked. EXPECT_EQ(false, signal_blocked) << "signal " << signo; - } else if (type == SignalMaskFunctionType::RtAware) { - // Realtime signals should be blocked, unless we blocked using a non-rt aware function. - EXPECT_EQ(true, signal_blocked) << "signal " << signo; } } +#else + UNUSED(sigset); +#endif } -static void TestSignalMaskFunction(std::function<void()> fn, SignalMaskFunctionType fn_type) { +static void TestSignalMaskFunction(std::function<void()> fn) { ClearSignalMask(); fn(); - TestSignalMaskFiltered(GetSignalMask(), fn_type); + TestSignalMaskFiltered(GetSignalMask()); } TEST(signal, sigaction_filter) { @@ -397,7 +396,7 @@ TEST(signal, sigaction_filter) { sigaction(SIGUSR1, &sa, nullptr); raise(SIGUSR1); ASSERT_NE(0ULL, sigset); - TestSignalMaskFiltered(sigset, sigset_type); + TestSignalMaskFiltered(sigset); } TEST(signal, sigaction64_filter) { @@ -409,111 +408,135 @@ TEST(signal, sigaction64_filter) { sigaction64(SIGUSR1, &sa, nullptr); raise(SIGUSR1); ASSERT_NE(0ULL, sigset); - TestSignalMaskFiltered(sigset, SignalMaskFunctionType::RtAware); + TestSignalMaskFiltered(sigset); } TEST(signal, sigprocmask_setmask_filter) { - TestSignalMaskFunction( - []() { - sigset_t sigset_libc; - sigfillset(&sigset_libc); - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr)); - }, - sigset_type); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr)); + }); } TEST(signal, sigprocmask64_setmask_filter) { - TestSignalMaskFunction( - []() { - sigset64_t sigset_libc; - sigfillset64(&sigset_libc); - ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr)); - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr)); + }); } TEST(signal, pthread_sigmask_setmask_filter) { - TestSignalMaskFunction( - []() { - sigset_t sigset_libc; - sigfillset(&sigset_libc); - ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr)); - }, - sigset_type); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr)); + }); } TEST(signal, pthread_sigmask64_setmask_filter) { - TestSignalMaskFunction( - []() { - sigset64_t sigset_libc; - sigfillset64(&sigset_libc); - ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr)); - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr)); + }); } TEST(signal, sigprocmask_block_filter) { - TestSignalMaskFunction( - []() { - sigset_t sigset_libc; - sigfillset(&sigset_libc); - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr)); - }, - sigset_type); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr)); + }); } TEST(signal, sigprocmask64_block_filter) { - TestSignalMaskFunction( - []() { - sigset64_t sigset_libc; - sigfillset64(&sigset_libc); - ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr)); - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr)); + }); } TEST(signal, pthread_sigmask_block_filter) { - TestSignalMaskFunction( - []() { - sigset_t sigset_libc; - sigfillset(&sigset_libc); - ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr)); - }, - sigset_type); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr)); + }); } TEST(signal, pthread_sigmask64_block_filter) { - TestSignalMaskFunction( - []() { - sigset64_t sigset_libc; - sigfillset64(&sigset_libc); - ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr)); - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + ClearSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr)); + }); +} + +TEST(signal, sigprocmask_unblock_filter) { + TestSignalMaskFunction([]() { + FillSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, sigprocmask(SIG_UNBLOCK, &sigset_libc, nullptr)); + }); +} + +TEST(signal, sigprocmask64_unblock_filter) { + TestSignalMaskFunction([]() { + FillSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, sigprocmask64(SIG_UNBLOCK, &sigset_libc, nullptr)); + }); +} + +TEST(signal, pthread_sigmask_unblock_filter) { + TestSignalMaskFunction([]() { + FillSignalMask(); + sigset_t sigset_libc; + sigfillset(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigset_libc, nullptr)); + }); +} + +TEST(signal, pthread_sigmask64_unblock_filter) { + TestSignalMaskFunction([]() { + FillSignalMask(); + sigset64_t sigset_libc; + sigfillset64(&sigset_libc); + ASSERT_EQ(0, pthread_sigmask64(SIG_UNBLOCK, &sigset_libc, nullptr)); + }); } // glibc filters out signals via sigfillset, not the actual underlying functions. TEST(signal, sigset_filter) { #if defined(__BIONIC__) - TestSignalMaskFunction( - []() { - for (int i = 1; i <= 64; ++i) { - sigset(i, SIG_HOLD); - } - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + for (int i = 1; i <= 64; ++i) { + sigset(i, SIG_HOLD); + } + }); #endif } TEST(signal, sighold_filter) { #if defined(__BIONIC__) - TestSignalMaskFunction( - []() { - for (int i = 1; i <= 64; ++i) { - sighold(i); - } - }, - SignalMaskFunctionType::RtAware); + TestSignalMaskFunction([]() { + for (int i = 1; i <= 64; ++i) { + sighold(i); + } + }); #endif } @@ -525,23 +548,17 @@ extern "C" int sigsetmask(int); TEST(signal, sigblock_filter) { #if defined(__BIONIC__) - TestSignalMaskFunction( - []() { - int mask = ~0U; - ASSERT_EQ(0, sigblock(mask)); - }, - SignalMaskFunctionType::RtNonaware); + TestSignalMaskFunction([]() { + sigblock(~0U); + }); #endif } TEST(signal, sigsetmask_filter) { #if defined(__BIONIC__) - TestSignalMaskFunction( - []() { - int mask = ~0U; - ASSERT_EQ(0, sigsetmask(mask)); - }, - SignalMaskFunctionType::RtNonaware); + TestSignalMaskFunction([]() { + sigsetmask(~0U); + }); #endif } diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp index a5e7e56f3..04b66d398 100644 --- a/tests/spawn_test.cpp +++ b/tests/spawn_test.cpp @@ -396,7 +396,13 @@ TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGMASK) { // Check that's what happens... ProcStatus ps = {}; GetChildStatus(&sa, &ps); - EXPECT_EQ(static_cast<uint64_t>(1 << (SIGALRM - 1)), ps.sigblk); + + // TIMER_SIGNAL should also be blocked. + uint64_t expected_blocked = 0; + SignalSetAdd(&expected_blocked, SIGALRM); + SignalSetAdd(&expected_blocked, __SIGRTMIN + 0); + EXPECT_EQ(expected_blocked, ps.sigblk); + EXPECT_EQ(static_cast<uint64_t>(0), ps.sigign); ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); @@ -421,8 +427,15 @@ TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGDEF) { // Check that's what happens... ProcStatus ps = {}; GetChildStatus(&sa, &ps); - EXPECT_EQ(static_cast<uint64_t>(0), ps.sigblk); - EXPECT_EQ(static_cast<uint64_t>(1 << (SIGCONT - 1)), ps.sigign); + + // TIMER_SIGNAL should be blocked. + uint64_t expected_blocked = 0; + SignalSetAdd(&expected_blocked, __SIGRTMIN + 0); + EXPECT_EQ(expected_blocked, ps.sigblk); + + uint64_t expected_ignored = 0; + SignalSetAdd(&expected_ignored, SIGCONT); + EXPECT_EQ(expected_ignored, ps.sigign); ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); } diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index 1f7f55508..da083dea7 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -886,6 +886,8 @@ TEST(UNISTD_TEST, sysconf) { VerifySysconf(_SC_XOPEN_VERSION, "_SC_XOPEN_VERSION", [](long v){return v == _XOPEN_VERSION && errno == 0;}); VERIFY_SYSCONF_POSITIVE(_SC_ATEXIT_MAX); VERIFY_SYSCONF_POSITIVE(_SC_IOV_MAX); + VERIFY_SYSCONF_POSITIVE(_SC_UIO_MAXIOV); + EXPECT_EQ(sysconf(_SC_IOV_MAX), sysconf(_SC_UIO_MAXIOV)); VERIFY_SYSCONF_POSITIVE(_SC_PAGESIZE); VERIFY_SYSCONF_POSITIVE(_SC_PAGE_SIZE); VerifySysconf(_SC_PAGE_SIZE, "_SC_PAGE_SIZE", diff --git a/tests/utils.h b/tests/utils.h index f07bd587e..c8656dcd6 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -184,6 +184,9 @@ class ExecTestHelper { char** GetEnv() { return const_cast<char**>(env_.data()); } + const std::string& GetOutput() { + return output_; + } void SetArgs(const std::vector<const char*>& args) { args_ = args; @@ -212,24 +215,25 @@ class ExecTestHelper { // Parent. close(fds[1]); - std::string output; + output_.clear(); char buf[BUFSIZ]; ssize_t bytes_read; while ((bytes_read = TEMP_FAILURE_RETRY(read(fds[0], buf, sizeof(buf)))) > 0) { - output.append(buf, bytes_read); + output_.append(buf, bytes_read); } close(fds[0]); - std::string error_msg("Test output:\n" + output); + std::string error_msg("Test output:\n" + output_); AssertChildExited(pid, expected_exit_status, &error_msg); if (expected_output != nullptr) { - ASSERT_EQ(expected_output, output); + ASSERT_EQ(expected_output, output_); } } private: std::vector<const char*> args_; std::vector<const char*> env_; + std::string output_; }; #endif |