From 2a54e5ecd0a96398e8d7d9b1629ecf8fb1633a2b Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 13 Sep 2012 10:52:52 -0700 Subject: [PATCH 1/2] Add tests for Android-specific stubs Also fix problem with multi-user IDs that the home directory was returned as "/data" instead of "/" unlike all the other uids. Change-Id: I914d22052e5a86552989f8969b85aadbc748c65d --- libc/bionic/stubs.cpp | 30 +++++++++---- tests/Android.mk | 1 + tests/stubs_test.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 tests/stubs_test.cpp diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp index a539b34ae..fb1a8e41f 100644 --- a/libc/bionic/stubs.cpp +++ b/libc/bionic/stubs.cpp @@ -264,10 +264,8 @@ static unsigned app_id_from_name(const char* name) { return (unsigned)(appid + userid*AID_USER); } -static void print_app_uid_name(uid_t uid, char* buffer, int bufferlen) { - uid_t appid = uid % AID_USER; - uid_t userid = uid / AID_USER; - +static void print_app_name_from_appid_userid(const uid_t appid, + const uid_t userid, char* buffer, const int bufferlen) { if (appid < AID_ISOLATED_START) { if (appid < AID_APP) { for (size_t n = 0; n < android_id_count; n++) { @@ -283,6 +281,12 @@ static void print_app_uid_name(uid_t uid, char* buffer, int bufferlen) { } } +static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) { + const uid_t appid = uid % AID_USER; + const uid_t userid = uid / AID_USER; + return print_app_name_from_appid_userid(appid, userid, buffer, bufferlen); +} + // Translate a uid into the corresponding name. // 0 to AID_APP-1 -> "system", "radio", etc. // AID_APP to AID_ISOLATED_START-1 -> u0_a1234 @@ -297,10 +301,18 @@ static passwd* app_id_to_passwd(uid_t uid, stubs_state_t* state) { return NULL; } - print_app_uid_name(uid, state->app_name_buffer_, - sizeof(state->app_name_buffer_)); + const uid_t appid = uid % AID_USER; + const uid_t userid = uid / AID_USER; + + print_app_name_from_appid_userid(appid, userid, state->app_name_buffer_, + sizeof(state->app_name_buffer_)); + + if (appid < AID_APP) { + snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/"); + } else { + snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data"); + } - snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data"); snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh"); pw->pw_name = state->app_name_buffer_; @@ -320,8 +332,8 @@ static group* app_id_to_group(gid_t gid, stubs_state_t* state) { return NULL; } - print_app_uid_name(gid, state->group_name_buffer_, - sizeof(state->group_name_buffer_)); + print_app_name_from_uid(gid, state->group_name_buffer_, + sizeof(state->group_name_buffer_)); group* gr = &state->group_; gr->gr_name = state->group_name_buffer_; diff --git a/tests/Android.mk b/tests/Android.mk index 6d30ebb03..be47585ab 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -23,6 +23,7 @@ test_src_files = \ pthread_test.cpp \ regex_test.cpp \ string_test.cpp \ + stubs_test.cpp \ test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction test_dynamic_src_files = \ diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp new file mode 100644 index 000000000..079779ef3 --- /dev/null +++ b/tests/stubs_test.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#if __BIONIC__ + +#define CHECK_GETPWNAM_FOR(username, uid, uid_type) \ + SCOPED_TRACE(username); \ + ASSERT_NO_FATAL_FAILURE(check_getpwnam(username, uid, uid_type)); + +typedef enum { + TYPE_SYSTEM, + TYPE_APP +} uid_type_t; + +static void check_getpwnam(const char* username, int uid, uid_type_t uid_type) { + errno = 0; + passwd* pwd = getpwuid(uid); + ASSERT_TRUE(pwd != NULL); + ASSERT_EQ(errno, 0); + EXPECT_STREQ(username, pwd->pw_name); + EXPECT_EQ(uid, pwd->pw_uid); + EXPECT_EQ(uid, pwd->pw_gid); + + if (uid_type == TYPE_SYSTEM) { + EXPECT_STREQ("/", pwd->pw_dir); + } else if (uid_type == TYPE_APP) { + EXPECT_STREQ("/data", pwd->pw_dir); + } + + EXPECT_STREQ("/system/bin/sh", pwd->pw_shell); +} + +TEST(getpwnam, system_id_root) { + CHECK_GETPWNAM_FOR("root", 0, TYPE_SYSTEM); +} + +TEST(getpwnam, system_id_system) { + CHECK_GETPWNAM_FOR("system", 1000, TYPE_SYSTEM); +} + +TEST(getpwnam, app_id_radio) { + CHECK_GETPWNAM_FOR("radio", 1001, TYPE_SYSTEM); +} + +TEST(getpwnam, app_id_nobody) { + CHECK_GETPWNAM_FOR("nobody", 9999, TYPE_SYSTEM); +} + +TEST(getpwnam, app_id_u0_a0) { + CHECK_GETPWNAM_FOR("u0_a0", 10000, TYPE_APP); +} + +TEST(getpwnam, app_id_u0_a1234) { + CHECK_GETPWNAM_FOR("u0_a1234", 11234, TYPE_APP); +} + +TEST(getpwnam, app_id_u0_a9999) { + CHECK_GETPWNAM_FOR("u0_a9999", 19999, TYPE_APP); +} + +// nonsensical, but expected +TEST(getpwnam, app_id_u1_root) { + CHECK_GETPWNAM_FOR("u1_root", 100000, TYPE_SYSTEM); +} + +TEST(getpwnam, app_id_u1_radio) { + CHECK_GETPWNAM_FOR("u1_radio", 101001, TYPE_SYSTEM); +} + +TEST(getpwnam, app_id_u1_a0) { + CHECK_GETPWNAM_FOR("u1_a0", 110000, TYPE_APP); +} + +TEST(getpwnam, app_id_u1_i0) { + CHECK_GETPWNAM_FOR("u1_i0", 199000, TYPE_APP); +} + +#endif /* __BIONIC__ */ From 8a05a01de75d78a45d646115b20b2a3e3c12ba9e Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Thu, 13 Sep 2012 14:31:50 -0700 Subject: [PATCH 2/2] Print out shared app gids correctly For applications that share resources across users such as forward-locked applications, print out their group name correctly. Change-Id: I06ee0b67e4325cfa415ffd7a03e301700399a66d --- libc/bionic/stubs.cpp | 19 ++++++++++--------- tests/stubs_test.cpp | 8 ++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp index fb1a8e41f..1cab7d32f 100644 --- a/libc/bionic/stubs.cpp +++ b/libc/bionic/stubs.cpp @@ -266,18 +266,19 @@ static unsigned app_id_from_name(const char* name) { static void print_app_name_from_appid_userid(const uid_t appid, const uid_t userid, char* buffer, const int bufferlen) { - if (appid < AID_ISOLATED_START) { - if (appid < AID_APP) { - for (size_t n = 0; n < android_id_count; n++) { - if (android_ids[n].aid == appid) { - snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name); - return; - } + if (appid >= AID_ISOLATED_START) { + snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START); + } else if (userid == 0 && appid >= AID_SHARED_GID_START) { + snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START); + } else if (appid < AID_APP) { + for (size_t n = 0; n < android_id_count; n++) { + if (android_ids[n].aid == appid) { + snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name); + return; } } - snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP); } else { - snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START); + snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP); } } diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp index 079779ef3..d2d0ad837 100644 --- a/tests/stubs_test.cpp +++ b/tests/stubs_test.cpp @@ -68,6 +68,14 @@ TEST(getpwnam, app_id_nobody) { CHECK_GETPWNAM_FOR("nobody", 9999, TYPE_SYSTEM); } +TEST(getpwnam, app_id_all_a0) { + CHECK_GETPWNAM_FOR("all_a0", 50000, TYPE_APP); +} + +TEST(getpwnam, app_id_u1_a40000) { + CHECK_GETPWNAM_FOR("u1_a40000", 150000, TYPE_APP); +} + TEST(getpwnam, app_id_u0_a0) { CHECK_GETPWNAM_FOR("u0_a0", 10000, TYPE_APP); }