aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2018-10-12 02:16:12 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-10-12 02:16:12 +0000
commit5a210f91fc61527bffad2ed04d848fc5faf32f7c (patch)
treec2c1e6d8f45fc5c7e67efda4c6e7d809c90b1902
parentcb8ed207d2bb6113a80fc7f27cd0beb8897f5192 (diff)
parentdac3816fbec7a66d1265f60397b63ca441744183 (diff)
downloadbionic-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.cpp4
-rw-r--r--libc/bionic/poll.cpp4
-rw-r--r--libc/bionic/sigaction.cpp4
-rw-r--r--libc/bionic/signal.cpp4
-rw-r--r--libc/bionic/sigprocmask.cpp9
-rw-r--r--libc/include/bits/sysconf.h1
-rw-r--r--libc/private/bionic_globals.h5
-rw-r--r--libc/private/sigrtmin.h28
-rw-r--r--linker/linker.cpp46
-rw-r--r--linker/linker.h2
-rw-r--r--linker/linker_logger.cpp4
-rw-r--r--linker/linker_main.cpp212
-rw-r--r--linker/linker_main.h2
-rw-r--r--linker/linker_phdr.h1
-rw-r--r--tests/Android.bp2
-rw-r--r--tests/SignalUtils.h9
-rw-r--r--tests/dl_test.cpp48
-rw-r--r--tests/libs/Android.bp16
-rw-r--r--tests/libs/Android.build.dlext_testzip.mk4
-rw-r--r--tests/libs/exec_linker_helper.cpp43
-rw-r--r--tests/libs/exec_linker_helper_lib.cpp34
-rw-r--r--tests/setjmp_test.cpp2
-rw-r--r--tests/signal_test.cpp235
-rw-r--r--tests/spawn_test.cpp19
-rw-r--r--tests/unistd_test.cpp2
-rw-r--r--tests/utils.h12
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