Merge "Export some symbols for vendor libmemunreachable"
diff --git a/libc/Android.bp b/libc/Android.bp
index 1da7262..57d4039 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1582,12 +1582,6 @@
"tz_version", // Version metadata for tzdata to help debugging.
],
- // Leave the symbols in the shared library so that stack unwinders can produce
- // meaningful name resolution.
- strip: {
- keep_symbols: true,
- },
-
// Do not pack libc.so relocations; see http://b/20645321 for details.
pack_relocations: false,
@@ -1628,9 +1622,23 @@
static: {
srcs: [":libc_sources_static_arm"],
},
+
+ // Arm 32 bit does not produce complete exidx unwind information
+ // so keep the .debug_frame which is relatively small and does
+ // include needed unwind information.
+ // See b/132992102 for details.
+ strip: {
+ keep_symbols_and_debug_frame: true,
+ },
},
arm64: {
version_script: ":libc.arm64.map",
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
x86: {
// TODO: This is to work around b/24465209. Remove after root cause is fixed.
@@ -1638,9 +1646,21 @@
ldflags: ["-Wl,--hash-style=both"],
version_script: ":libc.x86.map",
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
x86_64: {
version_script: ":libc.x86_64.map",
+
+ // Leave the symbols in the shared library so that stack unwinders can produce
+ // meaningful name resolution.
+ strip: {
+ keep_symbols: true,
+ },
},
},
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index c6e09a2..bd5c27d 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -58,85 +58,31 @@
// functions to share state, but <grp.h> functions can't clobber <passwd.h>
// functions' state and vice versa.
#include "bionic/pthread_internal.h"
-static group_state_t* get_group_tls_buffer() {
- return &__get_bionic_tls().group;
-}
-
-static passwd_state_t* get_passwd_tls_buffer() {
- return &__get_bionic_tls().passwd;
-}
static void init_group_state(group_state_t* state) {
memset(state, 0, sizeof(group_state_t) - sizeof(state->getgrent_idx));
+ state->group_.gr_name = state->group_name_buffer_;
state->group_.gr_mem = state->group_members_;
+ state->group_.gr_mem[0] = state->group_.gr_name;
}
-static group_state_t* __group_state() {
- group_state_t* result = get_group_tls_buffer();
- if (result != nullptr) {
- init_group_state(result);
- }
+static group_state_t* get_group_tls_buffer() {
+ auto result = &__get_bionic_tls().group;
+ init_group_state(result);
return result;
}
-static int do_getpw_r(int by_name, const char* name, uid_t uid,
- passwd* dst, char* buf, size_t byte_count,
- passwd** result) {
- // getpwnam_r and getpwuid_r don't modify errno, but library calls we
- // make might.
- ErrnoRestorer errno_restorer;
- *result = nullptr;
-
- // Our implementation of getpwnam(3) and getpwuid(3) use thread-local
- // storage, so we can call them as long as we copy everything out
- // before returning.
- const passwd* src = by_name ? getpwnam(name) : getpwuid(uid); // NOLINT: see above.
-
- // POSIX allows failure to find a match to be considered a non-error.
- // Reporting success (0) but with *result NULL is glibc's behavior.
- if (src == nullptr) {
- return (errno == ENOENT) ? 0 : errno;
- }
-
- // Work out where our strings will go in 'buf', and whether we've got
- // enough space.
- size_t required_byte_count = 0;
- dst->pw_name = buf;
- required_byte_count += strlen(src->pw_name) + 1;
- dst->pw_dir = buf + required_byte_count;
- required_byte_count += strlen(src->pw_dir) + 1;
- dst->pw_shell = buf + required_byte_count;
- required_byte_count += strlen(src->pw_shell) + 1;
- if (byte_count < required_byte_count) {
- return ERANGE;
- }
-
- // Copy the strings.
- snprintf(buf, byte_count, "%s%c%s%c%s", src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
-
- // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic.
- // Note: On LP32, we define pw_gecos to pw_passwd since they're both NULL.
- dst->pw_passwd = nullptr;
-#if defined(__LP64__)
- dst->pw_gecos = nullptr;
-#endif
-
- // Copy the integral fields.
- dst->pw_gid = src->pw_gid;
- dst->pw_uid = src->pw_uid;
-
- *result = dst;
- return 0;
+static void init_passwd_state(passwd_state_t* state) {
+ memset(state, 0, sizeof(passwd_state_t) - sizeof(state->getpwent_idx));
+ state->passwd_.pw_name = state->name_buffer_;
+ state->passwd_.pw_dir = state->dir_buffer_;
+ state->passwd_.pw_shell = state->sh_buffer_;
}
-int getpwnam_r(const char* name, passwd* pwd,
- char* buf, size_t byte_count, passwd** result) {
- return do_getpw_r(1, name, -1, pwd, buf, byte_count, result);
-}
-
-int getpwuid_r(uid_t uid, passwd* pwd,
- char* buf, size_t byte_count, passwd** result) {
- return do_getpw_r(0, nullptr, uid, pwd, buf, byte_count, result);
+static passwd_state_t* get_passwd_tls_buffer() {
+ auto result = &__get_bionic_tls().passwd;
+ init_passwd_state(result);
+ return result;
}
static passwd* android_iinfo_to_passwd(passwd_state_t* state,
@@ -146,11 +92,8 @@
snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
passwd* pw = &state->passwd_;
- pw->pw_name = state->name_buffer_;
pw->pw_uid = iinfo->aid;
pw->pw_gid = iinfo->aid;
- pw->pw_dir = state->dir_buffer_;
- pw->pw_shell = state->sh_buffer_;
return pw;
}
@@ -159,9 +102,7 @@
snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name);
group* gr = &state->group_;
- gr->gr_name = state->group_name_buffer_;
- gr->gr_gid = iinfo->aid;
- gr->gr_mem[0] = gr->gr_name;
+ gr->gr_gid = iinfo->aid;
return gr;
}
@@ -435,9 +376,6 @@
snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/vendor/bin/sh");
passwd* pw = &state->passwd_;
- pw->pw_name = state->name_buffer_;
- pw->pw_dir = state->dir_buffer_;
- pw->pw_shell = state->sh_buffer_;
pw->pw_uid = uid;
pw->pw_gid = uid;
return pw;
@@ -456,9 +394,7 @@
"oem_%u", gid);
group* gr = &state->group_;
- gr->gr_name = state->group_name_buffer_;
- gr->gr_gid = gid;
- gr->gr_mem[0] = gr->gr_name;
+ gr->gr_gid = gid;
return gr;
}
@@ -486,9 +422,6 @@
snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
passwd* pw = &state->passwd_;
- pw->pw_name = state->name_buffer_;
- pw->pw_dir = state->dir_buffer_;
- pw->pw_shell = state->sh_buffer_;
pw->pw_uid = uid;
pw->pw_gid = uid;
return pw;
@@ -505,18 +438,11 @@
print_app_name_from_gid(gid, state->group_name_buffer_, sizeof(state->group_name_buffer_));
group* gr = &state->group_;
- gr->gr_name = state->group_name_buffer_;
- gr->gr_gid = gid;
- gr->gr_mem[0] = gr->gr_name;
+ gr->gr_gid = gid;
return gr;
}
-passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.
- passwd_state_t* state = get_passwd_tls_buffer();
- if (state == nullptr) {
- return nullptr;
- }
-
+passwd* getpwuid_internal(uid_t uid, passwd_state_t* state) {
if (auto* android_id_info = find_android_id_info(uid); android_id_info != nullptr) {
return android_iinfo_to_passwd(state, android_id_info);
}
@@ -529,12 +455,12 @@
return app_id_to_passwd(uid, state);
}
-passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
+passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.
passwd_state_t* state = get_passwd_tls_buffer();
- if (state == nullptr) {
- return nullptr;
- }
+ return getpwuid_internal(uid, state);
+}
+passwd* getpwnam_internal(const char* login, passwd_state_t* state) {
if (auto* android_id_info = find_android_id_info(login); android_id_info != nullptr) {
return android_iinfo_to_passwd(state, android_id_info);
}
@@ -553,6 +479,39 @@
return app_id_to_passwd(app_id_from_name(login, false), state);
}
+passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
+ passwd_state_t* state = get_passwd_tls_buffer();
+ return getpwnam_internal(login, state);
+}
+
+static int getpasswd_r(bool by_name, const char* name, uid_t uid, struct passwd* pwd, char* buf,
+ size_t buflen, struct passwd** result) {
+ ErrnoRestorer errno_restorer;
+ *result = nullptr;
+ char* p =
+ reinterpret_cast<char*>(__BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
+ if (p + sizeof(passwd_state_t) > buf + buflen) {
+ return ERANGE;
+ }
+ passwd_state_t* state = reinterpret_cast<passwd_state_t*>(p);
+ init_passwd_state(state);
+ passwd* retval = (by_name ? getpwnam_internal(name, state) : getpwuid_internal(uid, state));
+ if (retval != nullptr) {
+ *pwd = *retval;
+ *result = pwd;
+ return 0;
+ }
+ return errno;
+}
+
+int getpwnam_r(const char* name, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
+ return getpasswd_r(true, name, -1, pwd, buf, byte_count, result);
+}
+
+int getpwuid_r(uid_t uid, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
+ return getpasswd_r(false, nullptr, uid, pwd, buf, byte_count, result);
+}
+
// All users are in just one group, the one passed in.
int getgrouplist(const char* /*user*/, gid_t group, gid_t* groups, int* ngroups) {
if (*ngroups < 1) {
@@ -590,9 +549,6 @@
passwd* getpwent() {
passwd_state_t* state = get_passwd_tls_buffer();
- if (state == nullptr) {
- return nullptr;
- }
if (state->getpwent_idx < 0) {
return nullptr;
}
@@ -643,10 +599,7 @@
}
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
- group_state_t* state = __group_state();
- if (state == nullptr) {
- return nullptr;
- }
+ group_state_t* state = get_group_tls_buffer();
return getgrgid_internal(gid, state);
}
@@ -670,10 +623,7 @@
}
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
- group_state_t* state = __group_state();
- if (state == nullptr) {
- return nullptr;
- }
+ group_state_t* state = get_group_tls_buffer();
return getgrnam_internal(name, state);
}
@@ -719,9 +669,6 @@
group* getgrent() {
group_state_t* state = get_group_tls_buffer();
- if (state == nullptr) {
- return nullptr;
- }
if (state->getgrent_idx < 0) {
return nullptr;
}
@@ -729,7 +676,6 @@
size_t start = 0;
ssize_t end = android_id_count;
if (state->getgrent_idx < end) {
- init_group_state(state);
return android_iinfo_to_group(state, android_ids + state->getgrent_idx++);
}
@@ -737,7 +683,6 @@
end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
if (state->getgrent_idx < end) {
- init_group_state(state);
return oem_id_to_group(
state->getgrent_idx++ - start + AID_OEM_RESERVED_START, state);
}
@@ -746,7 +691,6 @@
end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
if (state->getgrent_idx < end) {
- init_group_state(state);
return oem_id_to_group(
state->getgrent_idx++ - start + AID_OEM_RESERVED_2_START, state);
}
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index b46839b..ebc357c 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -217,6 +217,89 @@
TEST(pwd, getpwnam_app_id_u1_i0) {
check_get_passwd("u1_i0", 190000, TYPE_APP);
}
+
+TEST(pwd, getpwnam_r_alignment) {
+#if defined(__BIONIC__)
+ passwd pwd_storage;
+ alignas(16) char buf[512];
+ passwd* pwd;
+ int result = getpwnam_r("root", &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_alignment) {
+#if defined(__BIONIC__)
+ passwd pwd_storage;
+ alignas(16) char buf[512];
+ passwd* pwd;
+ int result = getpwuid_r(0, &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_reentrancy) {
+#if defined(__BIONIC__)
+ passwd pwd_storage[2];
+ char buf[2][512];
+ passwd* pwd[3];
+ int result = getpwnam_r("root", &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ pwd[1] = getpwnam("system");
+ ASSERT_NE(nullptr, pwd[1]);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+ result = getpwnam_r("radio", &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_reentrancy) {
+#if defined(__BIONIC__)
+ passwd pwd_storage[2];
+ char buf[2][512];
+ passwd* pwd[3];
+ int result = getpwuid_r(0, &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ pwd[1] = getpwuid(1000);
+ ASSERT_NE(nullptr, pwd[1]);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+ result = getpwuid_r(1001, &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+ ASSERT_EQ(0, result);
+ check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+ check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+ check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_large_enough_suggested_buffer_size) {
+#if defined(__BIONIC__)
+ long size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ ASSERT_GT(size, 0);
+ char buf[size];
+ passwd pwd_storage;
+ passwd* pwd;
+ ASSERT_EQ(0, getpwnam_r("root", &pwd_storage, buf, size, &pwd));
+ check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
#if defined(__BIONIC__)
template <typename T>
static void expect_ids(const T& ids) {
@@ -477,6 +560,32 @@
check_get_group("u1_i0", 190000);
}
+TEST(grp, getgrnam_r_alignment) {
+#if defined(__BIONIC__)
+ group grp_storage;
+ alignas(16) char buf[512];
+ group* grp;
+ int result = getgrnam_r("root", &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+ ASSERT_EQ(0, result);
+ check_group(grp, "root", 0);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(grp, getgrgid_r_alignment) {
+#if defined(__BIONIC__)
+ group grp_storage;
+ alignas(16) char buf[512];
+ group* grp;
+ int result = getgrgid_r(0, &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+ ASSERT_EQ(0, result);
+ check_group(grp, "root", 0);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
TEST(grp, getgrnam_r_reentrancy) {
#if defined(__BIONIC__)
group grp_storage[2];
diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp
index 1fa9e56..6005209 100644
--- a/tests/leak_test.cpp
+++ b/tests/leak_test.cpp
@@ -124,17 +124,22 @@
// http://b/36045112
TEST(pthread_leak, detach) {
LeakChecker lc;
+ constexpr int kThreadCount = 100;
- for (size_t pass = 0; pass < 2; ++pass) {
- constexpr int kThreadCount = 100;
+ // Devices with low power cores/low number of cores can not finish test in time hence decreasing
+ // threads count to 90.
+ // http://b/129924384.
+ int threads_count = (sysconf(_SC_NPROCESSORS_CONF) > 2) ? kThreadCount : (kThreadCount - 10);
+
+ for (size_t pass = 0; pass < 1; ++pass) {
struct thread_data { pthread_barrier_t* barrier; pid_t* tid; } threads[kThreadCount] = {};
pthread_barrier_t barrier;
- ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, kThreadCount + 1), 0);
+ ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, threads_count + 1), 0);
// Start child threads.
pid_t tids[kThreadCount];
- for (int i = 0; i < kThreadCount; ++i) {
+ for (int i = 0; i < threads_count; ++i) {
threads[i] = {&barrier, &tids[i]};
const auto thread_function = +[](void* ptr) -> void* {
thread_data* data = static_cast<thread_data*>(ptr);
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index 0ff6f30..e620ecd 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -112,6 +112,10 @@
}
TEST(stack_unwinding, unwind_through_signal_frame) {
+#if defined(__i386__)
+ GTEST_SKIP() << "Temporarily skip test since it fails on x86 see b/132763120.";
+#endif
+
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler);
UnwindTest();
@@ -119,6 +123,10 @@
// On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore.
TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) {
+#if defined(__i386__)
+ GTEST_SKIP() << "Temporarily skip test since it fails on x86 see b/132763120.";
+#endif
+
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO);
UnwindTest();