2012-09-13 19:52:52 +02:00
|
|
|
/*
|
|
|
|
* 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 <gtest/gtest.h>
|
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
// Below are the header files we want to test.
|
|
|
|
#include <grp.h>
|
2012-09-13 19:52:52 +02:00
|
|
|
#include <pwd.h>
|
2014-11-19 01:14:54 +01:00
|
|
|
|
2012-09-13 19:52:52 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
2014-11-19 01:14:54 +01:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <sys/types.h>
|
2012-09-13 19:52:52 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2017-11-14 17:50:43 +01:00
|
|
|
#include <set>
|
|
|
|
#include <vector>
|
2016-04-06 19:35:48 +02:00
|
|
|
|
2018-05-24 23:44:10 +02:00
|
|
|
#include <android-base/file.h>
|
2017-11-14 17:50:43 +01:00
|
|
|
#include <android-base/strings.h>
|
2016-04-06 19:35:48 +02:00
|
|
|
#include <private/android_filesystem_config.h>
|
|
|
|
|
2018-10-09 20:01:28 +02:00
|
|
|
#if defined(__BIONIC__)
|
2019-02-19 22:23:49 +01:00
|
|
|
#include <android/api-level.h>
|
2018-10-09 20:01:28 +02:00
|
|
|
#include <android-base/properties.h>
|
|
|
|
#endif
|
|
|
|
|
2016-12-14 00:47:25 +01:00
|
|
|
// Generated android_ids array
|
|
|
|
#include "generated_android_ids.h"
|
|
|
|
|
2023-09-21 23:11:19 +02:00
|
|
|
#include "utils.h"
|
|
|
|
|
2017-11-14 17:50:43 +01:00
|
|
|
using android::base::Join;
|
2018-05-24 23:44:10 +02:00
|
|
|
using android::base::ReadFileToString;
|
|
|
|
using android::base::Split;
|
|
|
|
using android::base::StartsWith;
|
2017-11-14 17:50:43 +01:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
using namespace std::literals;
|
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
enum uid_type_t {
|
2018-09-27 22:19:02 +02:00
|
|
|
TYPE_APP,
|
2012-09-13 19:52:52 +02:00
|
|
|
TYPE_SYSTEM,
|
2018-09-27 22:19:02 +02:00
|
|
|
TYPE_VENDOR,
|
2014-11-19 01:14:54 +01:00
|
|
|
};
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
#if defined(__BIONIC__)
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_passwd(const passwd* pwd, const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username) {
|
2018-08-03 02:31:13 +02:00
|
|
|
ASSERT_TRUE(pwd != nullptr);
|
2018-04-05 00:02:55 +02:00
|
|
|
if (check_username) {
|
|
|
|
EXPECT_STREQ(username, pwd->pw_name);
|
|
|
|
}
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_EQ(uid, pwd->pw_uid);
|
|
|
|
EXPECT_EQ(uid, pwd->pw_gid);
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_EQ(nullptr, pwd->pw_passwd);
|
2014-05-09 22:50:53 +02:00
|
|
|
#ifdef __LP64__
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_EQ(nullptr, pwd->pw_gecos);
|
2014-05-09 22:50:53 +02:00
|
|
|
#endif
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2018-09-27 22:19:02 +02:00
|
|
|
if (uid_type == TYPE_APP) {
|
|
|
|
EXPECT_STREQ("/data", pwd->pw_dir);
|
|
|
|
} else {
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_STREQ("/", pwd->pw_dir);
|
2018-09-27 22:19:02 +02:00
|
|
|
}
|
|
|
|
|
2020-07-10 19:40:21 +02:00
|
|
|
// This has changed over time and that causes new GSI + old vendor images testing to fail.
|
|
|
|
// This parameter doesn't matter on Android, so simply ignore its value for older vendor images.
|
|
|
|
if (android::base::GetIntProperty("ro.product.first_api_level", 0) >= 30) {
|
|
|
|
EXPECT_STREQ("/bin/sh", pwd->pw_shell);
|
|
|
|
}
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username) {
|
2014-11-19 01:14:54 +01:00
|
|
|
errno = 0;
|
|
|
|
passwd* pwd = getpwuid(uid);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getpwuid");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_passwd(pwd, username, uid, uid_type, check_username);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getpwnam(const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username) {
|
2014-11-19 01:14:54 +01:00
|
|
|
errno = 0;
|
|
|
|
passwd* pwd = getpwnam(username);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getpwnam");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_passwd(pwd, username, uid, uid_type, check_username);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getpwuid_r(const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username) {
|
2014-11-19 01:14:54 +01:00
|
|
|
passwd pwd_storage;
|
|
|
|
char buf[512];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
errno = 0;
|
2018-08-03 02:31:13 +02:00
|
|
|
passwd* pwd = nullptr;
|
2014-11-19 01:14:54 +01:00
|
|
|
result = getpwuid_r(uid, &pwd_storage, buf, sizeof(buf), &pwd);
|
|
|
|
ASSERT_EQ(0, result);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getpwuid_r");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_passwd(pwd, username, uid, uid_type, check_username);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getpwnam_r(const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username) {
|
2014-11-19 01:14:54 +01:00
|
|
|
passwd pwd_storage;
|
|
|
|
char buf[512];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
errno = 0;
|
2018-08-03 02:31:13 +02:00
|
|
|
passwd* pwd = nullptr;
|
2014-11-19 01:14:54 +01:00
|
|
|
result = getpwnam_r(username, &pwd_storage, buf, sizeof(buf), &pwd);
|
|
|
|
ASSERT_EQ(0, result);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getpwnam_r");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_passwd(pwd, username, uid, uid_type, check_username);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_get_passwd(const char* username, uid_t uid, uid_type_t uid_type,
|
|
|
|
bool check_username = true) {
|
2019-04-25 19:34:07 +02:00
|
|
|
SCOPED_TRACE("username '"s + username + "'");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_getpwuid(username, uid, uid_type, check_username);
|
|
|
|
check_getpwnam(username, uid, uid_type, check_username);
|
|
|
|
check_getpwuid_r(username, uid, uid_type, check_username);
|
|
|
|
check_getpwnam_r(username, uid, uid_type, check_username);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
static void expect_no_passwd_id(uid_t uid) {
|
|
|
|
SCOPED_TRACE("uid '" + std::to_string(uid) + "'");
|
|
|
|
errno = 0;
|
|
|
|
passwd* passwd = nullptr;
|
|
|
|
passwd = getpwuid(uid);
|
|
|
|
EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
|
2023-09-21 23:11:19 +02:00
|
|
|
EXPECT_ERRNO(ENOENT);
|
2019-04-25 19:34:07 +02:00
|
|
|
|
|
|
|
struct passwd passwd_storage;
|
|
|
|
char buf[512];
|
|
|
|
EXPECT_EQ(ENOENT, getpwuid_r(uid, &passwd_storage, buf, sizeof(buf), &passwd));
|
|
|
|
EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void expect_no_passwd_name(const char* username) {
|
|
|
|
SCOPED_TRACE("username '"s + username + "'");
|
|
|
|
errno = 0;
|
|
|
|
passwd* passwd = nullptr;
|
|
|
|
passwd = getpwnam(username);
|
|
|
|
EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
|
2023-09-21 23:11:19 +02:00
|
|
|
EXPECT_ERRNO(ENOENT);
|
2019-04-25 19:34:07 +02:00
|
|
|
|
|
|
|
struct passwd passwd_storage;
|
|
|
|
char buf[512];
|
|
|
|
EXPECT_EQ(ENOENT, getpwnam_r(username, &passwd_storage, buf, sizeof(buf), &passwd));
|
|
|
|
EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
|
|
|
|
}
|
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
#else // !defined(__BIONIC__)
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */,
|
|
|
|
bool /* check_username */) {
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-04-05 00:02:55 +02:00
|
|
|
}
|
|
|
|
|
2018-02-27 23:05:53 +01:00
|
|
|
static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */) {
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-02-27 23:05:53 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
static void expect_no_passwd_id(uid_t /* uid */) {
|
|
|
|
GTEST_SKIP() << "bionic-only test";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void expect_no_passwd_name(const char* /* username */) {
|
|
|
|
GTEST_SKIP() << "bionic-only test";
|
|
|
|
}
|
|
|
|
|
2013-12-21 03:43:21 +01:00
|
|
|
#endif
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_platform_ids) {
|
2014-11-19 01:14:54 +01:00
|
|
|
check_get_passwd("root", 0, TYPE_SYSTEM);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("daemon", 1, TYPE_SYSTEM);
|
|
|
|
check_get_passwd("bin", 2, TYPE_SYSTEM);
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
check_get_passwd("system", 1000, TYPE_SYSTEM);
|
|
|
|
check_get_passwd("radio", 1001, TYPE_SYSTEM);
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("shell", 2000, TYPE_SYSTEM);
|
2015-09-22 20:46:43 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("nobody", 9999, TYPE_SYSTEM);
|
2016-04-05 18:24:59 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_oem_ids) {
|
2018-09-27 22:19:02 +02:00
|
|
|
check_get_passwd("oem_2900", 2900, TYPE_VENDOR, false);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("oem_2945", 2945, TYPE_VENDOR, false);
|
2018-09-27 22:19:02 +02:00
|
|
|
check_get_passwd("oem_2999", 2999, TYPE_VENDOR, false);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("oem_5000", 5000, TYPE_VENDOR, false);
|
|
|
|
check_get_passwd("oem_5454", 5454, TYPE_VENDOR, false);
|
|
|
|
check_get_passwd("oem_5999", 5999, TYPE_VENDOR, false);
|
2015-09-22 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_non_exist) {
|
|
|
|
expect_no_passwd_id(999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(1999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(2899); // End of the system reserved range, unallocated.
|
2012-09-13 23:31:50 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
// These ranges are for GIDs only.
|
|
|
|
expect_no_passwd_id(20000);
|
|
|
|
expect_no_passwd_id(30000);
|
|
|
|
expect_no_passwd_id(40000);
|
|
|
|
expect_no_passwd_id(50000);
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
// These should not be parsed as users, only as groups.
|
|
|
|
expect_no_passwd_name("u0_a9999_cache");
|
|
|
|
expect_no_passwd_name("u0_a9999_ext");
|
|
|
|
expect_no_passwd_name("u0_a9999_ext_cache");
|
|
|
|
expect_no_passwd_name("all_a9999");
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_u0_app_ids) {
|
|
|
|
check_get_passwd("u0_a0", 10000, TYPE_APP);
|
|
|
|
check_get_passwd("u0_a1234", 11234, TYPE_APP);
|
|
|
|
check_get_passwd("u0_a9999", 19999, TYPE_APP);
|
2012-09-13 19:52:52 +02:00
|
|
|
|
2019-01-16 16:25:40 +01:00
|
|
|
check_get_passwd("u0_i1", 90001, TYPE_APP);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_passwd("u0_i4545", 94545, TYPE_APP);
|
|
|
|
check_get_passwd("u0_i9999", 99999, TYPE_APP);
|
2012-09-13 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_app_id_u1_ids) {
|
|
|
|
check_get_passwd("u1_system", 101000, TYPE_SYSTEM);
|
|
|
|
check_get_passwd("u1_radio", 101001, TYPE_SYSTEM);
|
|
|
|
|
|
|
|
check_get_passwd("u1_a0", 110000, TYPE_APP);
|
|
|
|
check_get_passwd("u1_a1234", 111234, TYPE_APP);
|
|
|
|
check_get_passwd("u1_a9999", 119999, TYPE_APP);
|
|
|
|
|
|
|
|
check_get_passwd("u1_i1", 190001, TYPE_APP);
|
|
|
|
check_get_passwd("u1_i4545", 194545, TYPE_APP);
|
|
|
|
check_get_passwd("u1_i9999", 199999, TYPE_APP);
|
2012-09-13 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_app_id_u31_ids) {
|
|
|
|
check_get_passwd("u31_system", 3101000, TYPE_SYSTEM);
|
|
|
|
check_get_passwd("u31_radio", 3101001, TYPE_SYSTEM);
|
|
|
|
|
|
|
|
check_get_passwd("u31_a0", 3110000, TYPE_APP);
|
|
|
|
check_get_passwd("u31_a1234", 3111234, TYPE_APP);
|
|
|
|
check_get_passwd("u31_a9999", 3119999, TYPE_APP);
|
|
|
|
|
|
|
|
check_get_passwd("u31_i1", 3190001, TYPE_APP);
|
|
|
|
check_get_passwd("u31_i4545", 3194545, TYPE_APP);
|
|
|
|
check_get_passwd("u31_i9999", 3199999, TYPE_APP);
|
2012-09-13 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwnam_app_id_not_allowed_platform) {
|
|
|
|
expect_no_passwd_name("u1_root");
|
|
|
|
expect_no_passwd_name("u1_debuggerd");
|
|
|
|
|
|
|
|
expect_no_passwd_name("u31_root");
|
|
|
|
expect_no_passwd_name("u31_debuggerd");
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwuid_app_id_u1_non_exist) {
|
|
|
|
expect_no_passwd_id(100000); // There is no 'root' for secondary users.
|
|
|
|
expect_no_passwd_id(101999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(102900); // The OEM ranges were never allocated to secondary users.
|
|
|
|
expect_no_passwd_id(105000); // The OEM ranges were never allocated to secondary users.
|
|
|
|
|
|
|
|
// These ranges are for GIDs only.
|
|
|
|
expect_no_passwd_id(120000);
|
|
|
|
expect_no_passwd_id(130000);
|
|
|
|
expect_no_passwd_id(140000);
|
|
|
|
expect_no_passwd_id(150000);
|
2012-09-13 19:52:52 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(pwd, getpwuid_app_id_u31_non_exist) {
|
|
|
|
expect_no_passwd_id(3100000); // There is no 'root' for secondary users.
|
|
|
|
expect_no_passwd_id(3101999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(3102900); // The OEM ranges were never allocated to secondary users.
|
|
|
|
expect_no_passwd_id(3105000); // The OEM ranges were never allocated to secondary users.
|
|
|
|
|
|
|
|
// These ranges are for GIDs only.
|
|
|
|
expect_no_passwd_id(3120000);
|
|
|
|
expect_no_passwd_id(3130000);
|
|
|
|
expect_no_passwd_id(3140000);
|
|
|
|
expect_no_passwd_id(3150000);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
pwd/grp: fix pwd _r reentrancy, new tests, clean up
getpwnam_r() and getpwuid_r() clobber the storage used by getpwnam()
and getpwuid(). This isn't likely to be a big issue, but since we do
this right for the group functions, fix this as well as add a test.
Both use more space in buf than is actually required, but well below
their sysconf() suggested values, so we accept that to keep the code
concise.
Add tests for dealing with unaligned input buffers, particularly for
getgrnam_r() and getgrgid_r(), as they require alignment but this
wasn't being tested.
Refactor common initialization code for both passwd and group state
structs.
Remove extraneous null pointer checks; the values they were testing
were offsets of a previous pointer, so guaranteed to never actually be
null. If the underlying pointer is actually null, we're beyond repair
anyway, so accept that we'll crash.
Test: pwd/grp unit tests
Change-Id: I60c4d00e9ab3cf55daf8314c5029fd914025b696
2019-05-15 02:02:28 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-10-09 20:01:28 +02:00
|
|
|
#if defined(__BIONIC__)
|
2017-11-14 17:50:43 +01:00
|
|
|
template <typename T>
|
2019-02-17 18:38:23 +01:00
|
|
|
static void expect_ids(T ids, bool is_group) {
|
2017-11-14 17:50:43 +01:00
|
|
|
std::set<typename T::key_type> expected_ids;
|
|
|
|
// Ensure that all android_ids are iterated through.
|
|
|
|
for (size_t n = 0; n < android_id_count; ++n) {
|
|
|
|
EXPECT_EQ(1U, ids.count(android_ids[n].aid)) << "android_ids[n].aid: " << android_ids[n].aid;
|
|
|
|
expected_ids.emplace(android_ids[n].aid);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto expect_range = [&ids, &expected_ids](uid_t start, uid_t end) {
|
|
|
|
for (size_t n = start; n <= end; ++n) {
|
|
|
|
EXPECT_EQ(1U, ids.count(n)) << "n: " << n;
|
|
|
|
expected_ids.emplace(n);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Ensure that all reserved ranges are iterated through.
|
|
|
|
expect_range(AID_OEM_RESERVED_START, AID_OEM_RESERVED_END);
|
|
|
|
expect_range(AID_OEM_RESERVED_2_START, AID_OEM_RESERVED_2_END);
|
|
|
|
expect_range(AID_APP_START, AID_APP_END);
|
2019-04-25 19:34:07 +02:00
|
|
|
if (is_group) {
|
|
|
|
expect_range(AID_CACHE_GID_START, AID_CACHE_GID_END);
|
|
|
|
expect_range(AID_EXT_GID_START, AID_EXT_GID_END);
|
|
|
|
expect_range(AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END);
|
|
|
|
expect_range(AID_SHARED_GID_START, AID_SHARED_GID_END);
|
|
|
|
}
|
2017-11-14 17:50:43 +01:00
|
|
|
expect_range(AID_ISOLATED_START, AID_ISOLATED_END);
|
|
|
|
|
2020-04-10 19:50:09 +02:00
|
|
|
// Prior to R, we didn't have a mechanism to create vendor AIDs in the system or other non-vendor
|
|
|
|
// partitions, therefore we disabled the rest of these checks for older API levels.
|
2019-12-20 22:26:14 +01:00
|
|
|
if (android::base::GetIntProperty("ro.product.first_api_level", 0) <= 29) {
|
2018-10-09 20:01:28 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-02-17 18:38:23 +01:00
|
|
|
auto allow_range = [&ids](uid_t start, uid_t end) {
|
|
|
|
for (size_t n = start; n <= end; ++n) {
|
|
|
|
ids.erase(n);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
allow_range(AID_SYSTEM_RESERVED_START, AID_SYSTEM_EXT_RESERVED_END);
|
|
|
|
|
2017-11-14 17:50:43 +01:00
|
|
|
// Ensure that no other ids were returned.
|
|
|
|
auto return_differences = [&ids, &expected_ids] {
|
|
|
|
std::vector<typename T::key_type> missing_from_ids;
|
|
|
|
std::set_difference(expected_ids.begin(), expected_ids.end(), ids.begin(), ids.end(),
|
|
|
|
std::inserter(missing_from_ids, missing_from_ids.begin()));
|
|
|
|
std::vector<typename T::key_type> extra_in_ids;
|
|
|
|
std::set_difference(ids.begin(), ids.end(), expected_ids.begin(), expected_ids.end(),
|
|
|
|
std::inserter(extra_in_ids, extra_in_ids.begin()));
|
|
|
|
std::string result;
|
|
|
|
if (!missing_from_ids.empty()) {
|
|
|
|
result += "Missing ids from results: " + Join(missing_from_ids, " ");
|
|
|
|
}
|
|
|
|
if (!extra_in_ids.empty()) {
|
|
|
|
if (!result.empty()) result += ", ";
|
|
|
|
result += "Extra ids in results: " + Join(extra_in_ids, " ");
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
2022-10-27 11:28:24 +02:00
|
|
|
|
2024-02-10 01:39:07 +01:00
|
|
|
// AID_UPROBESTATS (1093) was added in V, but "trunk stable" means
|
|
|
|
// that the 2024Q builds don't have branches like the QPR builds used
|
|
|
|
// to, and are tested with the _previous_ release's CTS.
|
|
|
|
if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
|
|
|
|
#if !defined(AID_UPROBESTATS)
|
|
|
|
#define AID_UPROBESTATS 1093
|
2022-10-27 11:28:24 +02:00
|
|
|
#endif
|
2024-02-10 01:39:07 +01:00
|
|
|
ids.erase(AID_UPROBESTATS);
|
|
|
|
expected_ids.erase(AID_UPROBESTATS);
|
|
|
|
if (getpwuid(AID_UPROBESTATS)) {
|
|
|
|
EXPECT_STREQ(getpwuid(AID_UPROBESTATS)->pw_name, "uprobestats");
|
|
|
|
}
|
2022-10-27 11:28:24 +02:00
|
|
|
}
|
2024-02-10 01:39:07 +01:00
|
|
|
// AID_VIRTUALMACHINE (3013) was added in V, but "trunk stable" means
|
|
|
|
// that the 2024Q builds don't have branches like the QPR builds used
|
|
|
|
// to, and are tested with the _previous_ release's CTS.
|
|
|
|
if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
|
|
|
|
#if !defined(AID_VIRTUALMACHINE)
|
|
|
|
#define AID_VIRTUALMACHINE 3013
|
|
|
|
#endif
|
|
|
|
ids.erase(AID_VIRTUALMACHINE);
|
|
|
|
expected_ids.erase(AID_VIRTUALMACHINE);
|
|
|
|
if (getpwuid(AID_VIRTUALMACHINE)) {
|
|
|
|
EXPECT_STREQ(getpwuid(AID_VIRTUALMACHINE)->pw_name, "virtualmachine");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 17:50:43 +01:00
|
|
|
EXPECT_EQ(expected_ids, ids) << return_differences();
|
|
|
|
}
|
2018-10-09 20:01:28 +02:00
|
|
|
#endif
|
2017-11-14 17:50:43 +01:00
|
|
|
|
2016-12-13 02:32:14 +01:00
|
|
|
TEST(pwd, getpwent_iterate) {
|
2018-02-27 23:05:53 +01:00
|
|
|
#if defined(__BIONIC__)
|
2016-04-06 19:35:48 +02:00
|
|
|
passwd* pwd;
|
2017-11-14 17:50:43 +01:00
|
|
|
std::set<uid_t> uids;
|
2016-04-06 19:35:48 +02:00
|
|
|
|
|
|
|
setpwent();
|
2018-08-03 02:31:13 +02:00
|
|
|
while ((pwd = getpwent()) != nullptr) {
|
|
|
|
ASSERT_TRUE(nullptr != pwd->pw_name);
|
2017-11-14 17:50:43 +01:00
|
|
|
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_EQ(pwd->pw_gid, pwd->pw_uid) << "pwd->pw_uid: " << pwd->pw_uid;
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_EQ(nullptr, pwd->pw_passwd) << "pwd->pw_uid: " << pwd->pw_uid;
|
2016-04-06 19:35:48 +02:00
|
|
|
#ifdef __LP64__
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_TRUE(nullptr == pwd->pw_gecos) << "pwd->pw_uid: " << pwd->pw_uid;
|
2016-04-06 19:35:48 +02:00
|
|
|
#endif
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_TRUE(nullptr != pwd->pw_shell);
|
2017-11-14 17:50:43 +01:00
|
|
|
if (pwd->pw_uid < AID_APP_START || pwd->pw_uid == AID_OVERFLOWUID) {
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_STREQ("/", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
|
2017-11-14 17:50:43 +01:00
|
|
|
} else {
|
|
|
|
EXPECT_STREQ("/data", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
|
|
|
|
}
|
|
|
|
|
Tighten pwd/grp iteration tests.
Previously, these tests would fail if vendors modified
private/android_filesystem_config.h to add their custom AIDs, but we
did not have a good alternative that vendors could use, so we added a
special case to ignore the vendor AID ranges.
We've had a proper solution since P for this range, so it's long past
time to remove this special case.
Test: add system, vendor, odm, product, and system_ext AIDs to
config.fs, ensure that they've taken effect on cuttlefish,
pass these unit tests
Change-Id: I6c9c2bf5e895c25805222da018188b269777171c
2020-04-10 22:00:42 +02:00
|
|
|
EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
|
2017-11-14 17:50:43 +01:00
|
|
|
uids.emplace(pwd->pw_uid);
|
2016-04-06 19:35:48 +02:00
|
|
|
}
|
|
|
|
endpwent();
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
expect_ids(uids, false);
|
2018-02-27 23:05:53 +01:00
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-02-27 23:05:53 +01:00
|
|
|
#endif
|
2016-04-06 19:35:48 +02:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_group(const group* grp, const char* group_name, gid_t gid,
|
|
|
|
bool check_groupname = true) {
|
2018-08-03 02:31:13 +02:00
|
|
|
ASSERT_TRUE(grp != nullptr);
|
2018-04-05 00:02:55 +02:00
|
|
|
if (check_groupname) {
|
|
|
|
EXPECT_STREQ(group_name, grp->gr_name);
|
|
|
|
}
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_EQ(gid, grp->gr_gid);
|
2018-08-03 02:31:13 +02:00
|
|
|
ASSERT_TRUE(grp->gr_mem != nullptr);
|
2018-04-05 00:02:55 +02:00
|
|
|
if (check_groupname) {
|
|
|
|
EXPECT_STREQ(group_name, grp->gr_mem[0]);
|
|
|
|
}
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_TRUE(grp->gr_mem[1] == nullptr);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2015-07-21 04:46:26 +02:00
|
|
|
#if defined(__BIONIC__)
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getgrgid(const char* group_name, gid_t gid, bool check_groupname) {
|
2014-11-19 01:14:54 +01:00
|
|
|
errno = 0;
|
|
|
|
group* grp = getgrgid(gid);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getgrgid");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_group(grp, group_name, gid, check_groupname);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getgrnam(const char* group_name, gid_t gid, bool check_groupname) {
|
2014-11-19 01:14:54 +01:00
|
|
|
errno = 0;
|
|
|
|
group* grp = getgrnam(group_name);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2014-11-19 01:14:54 +01:00
|
|
|
SCOPED_TRACE("getgrnam");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_group(grp, group_name, gid, check_groupname);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getgrgid_r(const char* group_name, gid_t gid, bool check_groupname) {
|
2015-07-21 04:46:26 +02:00
|
|
|
group grp_storage;
|
|
|
|
char buf[512];
|
|
|
|
group* grp;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
|
|
|
|
ASSERT_EQ(0, result);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2015-07-21 04:46:26 +02:00
|
|
|
SCOPED_TRACE("getgrgid_r");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_group(grp, group_name, gid, check_groupname);
|
2015-07-21 04:46:26 +02:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_getgrnam_r(const char* group_name, gid_t gid, bool check_groupname) {
|
2015-07-21 04:46:26 +02:00
|
|
|
group grp_storage;
|
|
|
|
char buf[512];
|
|
|
|
group* grp;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
|
|
|
|
ASSERT_EQ(0, result);
|
2023-09-21 23:11:19 +02:00
|
|
|
ASSERT_ERRNO(0);
|
2015-07-21 04:46:26 +02:00
|
|
|
SCOPED_TRACE("getgrnam_r");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_group(grp, group_name, gid, check_groupname);
|
2015-07-21 04:46:26 +02:00
|
|
|
}
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_get_group(const char* group_name, gid_t gid, bool check_groupname = true) {
|
2019-04-25 19:34:07 +02:00
|
|
|
SCOPED_TRACE("groupname '"s + group_name + "'");
|
2018-04-05 00:02:55 +02:00
|
|
|
check_getgrgid(group_name, gid, check_groupname);
|
|
|
|
check_getgrnam(group_name, gid, check_groupname);
|
|
|
|
check_getgrgid_r(group_name, gid, check_groupname);
|
|
|
|
check_getgrnam_r(group_name, gid, check_groupname);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
static void expect_no_group_id(gid_t gid) {
|
|
|
|
SCOPED_TRACE("gid '" + std::to_string(gid) + "'");
|
|
|
|
errno = 0;
|
|
|
|
group* group = nullptr;
|
|
|
|
group = getgrgid(gid);
|
|
|
|
EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
|
2023-09-21 23:11:19 +02:00
|
|
|
EXPECT_ERRNO(ENOENT);
|
2019-04-25 19:34:07 +02:00
|
|
|
|
|
|
|
struct group group_storage;
|
|
|
|
char buf[512];
|
|
|
|
EXPECT_EQ(ENOENT, getgrgid_r(gid, &group_storage, buf, sizeof(buf), &group));
|
|
|
|
EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void expect_no_group_name(const char* groupname) {
|
|
|
|
SCOPED_TRACE("groupname '"s + groupname + "'");
|
|
|
|
errno = 0;
|
|
|
|
group* group = nullptr;
|
|
|
|
group = getgrnam(groupname);
|
|
|
|
EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
|
2023-09-21 23:11:19 +02:00
|
|
|
EXPECT_ERRNO(ENOENT);
|
2019-04-25 19:34:07 +02:00
|
|
|
|
|
|
|
struct group group_storage;
|
|
|
|
char buf[512];
|
|
|
|
EXPECT_EQ(ENOENT, getgrnam_r(groupname, &group_storage, buf, sizeof(buf), &group));
|
|
|
|
EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
|
|
|
|
}
|
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
#else // !defined(__BIONIC__)
|
|
|
|
|
2018-04-05 00:02:55 +02:00
|
|
|
static void check_get_group(const char*, gid_t, bool) {
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-04-05 00:02:55 +02:00
|
|
|
}
|
|
|
|
|
2015-07-21 04:46:26 +02:00
|
|
|
static void check_get_group(const char*, gid_t) {
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2015-07-21 04:46:26 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
static void expect_no_group_id(gid_t /* gid */) {
|
|
|
|
GTEST_SKIP() << "bionic-only test";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void expect_no_group_name(const char* /* groupname */) {
|
|
|
|
GTEST_SKIP() << "bionic-only test";
|
|
|
|
}
|
|
|
|
|
2014-11-19 01:14:54 +01:00
|
|
|
#endif
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_platform_ids) {
|
2014-11-19 01:14:54 +01:00
|
|
|
check_get_group("root", 0);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("daemon", 1);
|
|
|
|
check_get_group("bin", 2);
|
2014-11-19 01:14:54 +01:00
|
|
|
|
|
|
|
check_get_group("system", 1000);
|
|
|
|
check_get_group("radio", 1001);
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("shell", 2000);
|
2016-04-05 18:24:59 +02:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("nobody", 9999);
|
2016-04-05 18:24:59 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_oem_ids) {
|
2018-04-05 00:02:55 +02:00
|
|
|
check_get_group("oem_2900", 2900, false);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("oem_2945", 2945, false);
|
2018-04-05 00:02:55 +02:00
|
|
|
check_get_group("oem_2999", 2999, false);
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("oem_5000", 5000, false);
|
|
|
|
check_get_group("oem_5454", 5454, false);
|
|
|
|
check_get_group("oem_5999", 5999, false);
|
2015-09-22 20:46:43 +02:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_non_exist) {
|
|
|
|
expect_no_passwd_id(999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(1999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_passwd_id(2899); // End of the system reserved range, unallocated.
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_u0_app_ids) {
|
2014-11-19 01:14:54 +01:00
|
|
|
check_get_group("u0_a0", 10000);
|
|
|
|
check_get_group("u0_a1234", 11234);
|
|
|
|
check_get_group("u0_a9999", 19999);
|
|
|
|
|
2016-12-13 22:03:19 +01:00
|
|
|
check_get_group("u0_a0_cache", 20000);
|
|
|
|
check_get_group("u0_a1234_cache", 21234);
|
|
|
|
check_get_group("u0_a9999_cache", 29999);
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("u0_a0_ext", 30000);
|
|
|
|
check_get_group("u0_a4545_ext", 34545);
|
|
|
|
check_get_group("u0_a9999_ext", 39999);
|
2016-12-13 22:03:19 +01:00
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
check_get_group("u0_a0_ext_cache", 40000);
|
|
|
|
check_get_group("u0_a4545_ext_cache", 44545);
|
|
|
|
check_get_group("u0_a9999_ext_cache", 49999);
|
|
|
|
|
|
|
|
check_get_group("all_a0", 50000);
|
|
|
|
check_get_group("all_a4545", 54545);
|
2014-11-19 01:14:54 +01:00
|
|
|
check_get_group("all_a9999", 59999);
|
|
|
|
|
2019-01-16 16:25:40 +01:00
|
|
|
check_get_group("u0_i1", 90001);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_u1_app_ids) {
|
|
|
|
check_get_group("u1_system", 101000);
|
|
|
|
check_get_group("u1_radio", 101001);
|
|
|
|
|
|
|
|
check_get_group("u1_a0", 110000);
|
|
|
|
check_get_group("u1_a1234", 111234);
|
|
|
|
check_get_group("u1_a9999", 119999);
|
|
|
|
|
|
|
|
check_get_group("u1_a0_cache", 120000);
|
|
|
|
check_get_group("u1_a1234_cache", 121234);
|
|
|
|
check_get_group("u1_a9999_cache", 129999);
|
|
|
|
|
|
|
|
check_get_group("u1_a0_ext", 130000);
|
|
|
|
check_get_group("u1_a4545_ext", 134545);
|
|
|
|
check_get_group("u1_a9999_ext", 139999);
|
|
|
|
|
|
|
|
check_get_group("u1_a0_ext_cache", 140000);
|
|
|
|
check_get_group("u1_a4545_ext_cache", 144545);
|
|
|
|
check_get_group("u1_a9999_ext_cache", 149999);
|
|
|
|
|
|
|
|
check_get_group("u1_i1", 190001);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrnam_u31_app_ids) {
|
|
|
|
check_get_group("u31_system", 3101000);
|
|
|
|
check_get_group("u31_radio", 3101001);
|
|
|
|
|
|
|
|
check_get_group("u31_a0", 3110000);
|
|
|
|
check_get_group("u31_a1234", 3111234);
|
|
|
|
check_get_group("u31_a9999", 3119999);
|
|
|
|
|
|
|
|
check_get_group("u31_a0_cache", 3120000);
|
|
|
|
check_get_group("u31_a1234_cache", 3121234);
|
|
|
|
check_get_group("u31_a9999_cache", 3129999);
|
|
|
|
|
|
|
|
check_get_group("u31_a0_cache", 3120000);
|
|
|
|
check_get_group("u31_a1234_cache", 3121234);
|
|
|
|
check_get_group("u31_a9999_cache", 3129999);
|
|
|
|
|
|
|
|
check_get_group("u31_a0_ext", 3130000);
|
|
|
|
check_get_group("u31_a4545_ext", 3134545);
|
|
|
|
check_get_group("u31_a9999_ext", 3139999);
|
|
|
|
|
|
|
|
check_get_group("u31_a0_ext_cache", 3140000);
|
|
|
|
check_get_group("u31_a4545_ext_cache", 3144545);
|
|
|
|
check_get_group("u31_a9999_ext_cache", 3149999);
|
|
|
|
|
|
|
|
check_get_group("u31_i1", 3190001);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getpgram_app_id_not_allowed_platform) {
|
|
|
|
expect_no_group_name("u1_root");
|
|
|
|
expect_no_group_name("u1_debuggerd");
|
|
|
|
|
|
|
|
expect_no_group_name("u31_root");
|
|
|
|
expect_no_group_name("u31_debuggerd");
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrgid_app_id_u1_non_exist) {
|
|
|
|
expect_no_group_id(100000); // There is no 'root' for secondary users.
|
|
|
|
expect_no_group_id(101999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_group_id(102900); // The OEM ranges were never allocated to secondary users.
|
|
|
|
expect_no_group_id(105000); // The OEM ranges were never allocated to secondary users.
|
|
|
|
|
|
|
|
// The shared range is shared among users, and therefore doesn't exist for secondary users.
|
|
|
|
expect_no_group_id(150000);
|
2014-11-19 01:14:54 +01:00
|
|
|
}
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
TEST(grp, getgrgid_app_id_u31_non_exist) {
|
|
|
|
expect_no_group_id(3100000); // There is no 'root' for secondary users.
|
|
|
|
expect_no_group_id(3101999); // End of the system reserved range, unallocated.
|
|
|
|
expect_no_group_id(3102900); // The OEM ranges were never allocated to secondary users.
|
|
|
|
expect_no_group_id(3105000); // The OEM ranges were never allocated to secondary users.
|
|
|
|
|
|
|
|
// The shared range is shared among users, and therefore doesn't exist for secondary users.
|
|
|
|
expect_no_group_id(3150000);
|
2012-09-13 19:52:52 +02:00
|
|
|
}
|
2015-07-21 04:46:26 +02:00
|
|
|
|
pwd/grp: fix pwd _r reentrancy, new tests, clean up
getpwnam_r() and getpwuid_r() clobber the storage used by getpwnam()
and getpwuid(). This isn't likely to be a big issue, but since we do
this right for the group functions, fix this as well as add a test.
Both use more space in buf than is actually required, but well below
their sysconf() suggested values, so we accept that to keep the code
concise.
Add tests for dealing with unaligned input buffers, particularly for
getgrnam_r() and getgrgid_r(), as they require alignment but this
wasn't being tested.
Refactor common initialization code for both passwd and group state
structs.
Remove extraneous null pointer checks; the values they were testing
were offsets of a previous pointer, so guaranteed to never actually be
null. If the underlying pointer is actually null, we're beyond repair
anyway, so accept that we'll crash.
Test: pwd/grp unit tests
Change-Id: I60c4d00e9ab3cf55daf8314c5029fd914025b696
2019-05-15 02:02:28 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-12-13 02:32:14 +01:00
|
|
|
TEST(grp, getgrnam_r_reentrancy) {
|
2015-07-21 04:46:26 +02:00
|
|
|
#if defined(__BIONIC__)
|
|
|
|
group grp_storage[2];
|
|
|
|
char buf[2][512];
|
|
|
|
group* grp[3];
|
|
|
|
int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
|
|
|
|
ASSERT_EQ(0, result);
|
|
|
|
check_group(grp[0], "root", 0);
|
|
|
|
grp[1] = getgrnam("system");
|
|
|
|
check_group(grp[1], "system", 1000);
|
|
|
|
result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
|
|
|
|
ASSERT_EQ(0, result);
|
|
|
|
check_group(grp[2], "radio", 1001);
|
|
|
|
check_group(grp[0], "root", 0);
|
|
|
|
check_group(grp[1], "system", 1000);
|
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2015-07-21 04:46:26 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-12-13 02:32:14 +01:00
|
|
|
TEST(grp, getgrgid_r_reentrancy) {
|
2015-07-21 04:46:26 +02:00
|
|
|
#if defined(__BIONIC__)
|
|
|
|
group grp_storage[2];
|
|
|
|
char buf[2][512];
|
|
|
|
group* grp[3];
|
|
|
|
int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
|
|
|
|
ASSERT_EQ(0, result);
|
|
|
|
check_group(grp[0], "root", 0);
|
|
|
|
grp[1] = getgrgid(1000);
|
|
|
|
check_group(grp[1], "system", 1000);
|
|
|
|
result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
|
|
|
|
ASSERT_EQ(0, result);
|
|
|
|
check_group(grp[2], "radio", 1001);
|
|
|
|
check_group(grp[0], "root", 0);
|
|
|
|
check_group(grp[1], "system", 1000);
|
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2015-07-21 04:46:26 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-12-13 02:32:14 +01:00
|
|
|
TEST(grp, getgrnam_r_large_enough_suggested_buffer_size) {
|
2015-07-21 04:46:26 +02:00
|
|
|
long size = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
|
|
ASSERT_GT(size, 0);
|
|
|
|
char buf[size];
|
|
|
|
group grp_storage;
|
|
|
|
group* grp;
|
|
|
|
ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
|
|
|
|
check_group(grp, "root", 0);
|
|
|
|
}
|
2016-04-06 19:35:48 +02:00
|
|
|
|
2016-12-13 02:32:14 +01:00
|
|
|
TEST(grp, getgrent_iterate) {
|
2018-02-27 23:05:53 +01:00
|
|
|
#if defined(__BIONIC__)
|
2016-04-06 19:35:48 +02:00
|
|
|
group* grp;
|
2017-11-14 17:50:43 +01:00
|
|
|
std::set<gid_t> gids;
|
2016-04-06 19:35:48 +02:00
|
|
|
|
|
|
|
setgrent();
|
2018-08-03 02:31:13 +02:00
|
|
|
while ((grp = getgrent()) != nullptr) {
|
|
|
|
ASSERT_TRUE(grp->gr_name != nullptr) << "grp->gr_gid: " << grp->gr_gid;
|
|
|
|
ASSERT_TRUE(grp->gr_mem != nullptr) << "grp->gr_gid: " << grp->gr_gid;
|
2017-11-10 19:57:21 +01:00
|
|
|
EXPECT_STREQ(grp->gr_name, grp->gr_mem[0]) << "grp->gr_gid: " << grp->gr_gid;
|
2018-08-03 02:31:13 +02:00
|
|
|
EXPECT_TRUE(grp->gr_mem[1] == nullptr) << "grp->gr_gid: " << grp->gr_gid;
|
2017-11-14 17:50:43 +01:00
|
|
|
|
Tighten pwd/grp iteration tests.
Previously, these tests would fail if vendors modified
private/android_filesystem_config.h to add their custom AIDs, but we
did not have a good alternative that vendors could use, so we added a
special case to ignore the vendor AID ranges.
We've had a proper solution since P for this range, so it's long past
time to remove this special case.
Test: add system, vendor, odm, product, and system_ext AIDs to
config.fs, ensure that they've taken effect on cuttlefish,
pass these unit tests
Change-Id: I6c9c2bf5e895c25805222da018188b269777171c
2020-04-10 22:00:42 +02:00
|
|
|
EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
|
2017-11-14 17:50:43 +01:00
|
|
|
gids.emplace(grp->gr_gid);
|
2016-04-06 19:35:48 +02:00
|
|
|
}
|
|
|
|
endgrent();
|
|
|
|
|
2019-04-25 19:34:07 +02:00
|
|
|
expect_ids(gids, true);
|
2018-02-27 23:05:53 +01:00
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-02-27 23:05:53 +01:00
|
|
|
#endif
|
2020-08-12 23:25:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(grp, getgrouplist) {
|
|
|
|
#if defined(__BIONIC__)
|
|
|
|
// Query the number of groups.
|
|
|
|
int ngroups = 0;
|
|
|
|
ASSERT_EQ(-1, getgrouplist("root", 123, nullptr, &ngroups));
|
|
|
|
ASSERT_EQ(1, ngroups);
|
|
|
|
|
|
|
|
// Query the specific groups (just the one you pass in on Android).
|
|
|
|
ngroups = 8;
|
|
|
|
gid_t groups[ngroups];
|
|
|
|
ASSERT_EQ(1, getgrouplist("root", 123, groups, &ngroups));
|
|
|
|
ASSERT_EQ(1, ngroups);
|
|
|
|
ASSERT_EQ(123u, groups[0]);
|
|
|
|
#else
|
|
|
|
GTEST_SKIP() << "bionic-only test (groups too unpredictable)";
|
|
|
|
#endif
|
2016-04-06 19:35:48 +02:00
|
|
|
}
|
2018-05-24 23:44:10 +02:00
|
|
|
|
Simplify our trivial initgroups(), and add a test.
initgroups() is just a call to getgrouplist() followed by a call to
setgroups(). The tricky part is memory allocation. OpenBSD allocates an
NGROUPS_MAX-sized array of gid_t on the stack. FreeBSD allocates a
sysconf(_SC_NGROUPS_MAX)-sized array of gid_t on the heap. bionic had a
mix where it would try a 2-element stack array but fall back to a heap
allocation, which sounds reasonable if you want to avoid a 256KiB
(64Ki*4 bytes) allocation on either stack or heap. But that constant 2?
That's weird in two ways... It's really small (musl has an NGROUPS_MAX
of 32 unlike the Linux kernel's 64Ki, but 32 is still a lot larger than
2), but at the same time it's too big --- bionic's getgrouplist() always
returns a single element.
So although the FreeBSD "what the hell, let's just allocate 256KiB on
the heap" implementation would have been fine, there's really no point,
and anyone who's trying to understand initgroups() on Android really
needs to read getgroupslist() anyway, so let's just have the most
trivial implementation -- a single-element array -- and let's have it
right next to getgroupslist() in the same file as all the other <grp.h>
functions.
Also add a trivial smoke test. You mostly won't have permission to do
anything interesting with initgroups(), and it's basically unused save
for privilege dropping tcpdump and strace, but we may as well make an
effort. (I tested tcpdump before and after too.)
Test: treehugger
Change-Id: I67fe02e309ed1dbefc490c01733738363ca606be
2024-02-15 02:10:54 +01:00
|
|
|
TEST(grp, initgroups) {
|
|
|
|
if (getuid() != 0) GTEST_SKIP() << "test requires root";
|
|
|
|
ASSERT_EQ(0, initgroups("root", 0));
|
|
|
|
}
|
|
|
|
|
2018-05-24 23:44:10 +02:00
|
|
|
#if defined(__BIONIC__)
|
|
|
|
static void TestAidNamePrefix(const std::string& file_path) {
|
|
|
|
std::string file_contents;
|
|
|
|
if (!ReadFileToString(file_path, &file_contents)) {
|
|
|
|
// If we cannot read this file, then there are no vendor defind AID names, in which case this
|
|
|
|
// test passes by default.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto lines = Split(file_contents, "\n");
|
|
|
|
for (const auto& line : lines) {
|
|
|
|
if (line.empty()) continue;
|
|
|
|
auto name = Split(line, ":")[0];
|
|
|
|
EXPECT_TRUE(StartsWith(name, "vendor_"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TEST(pwd, vendor_prefix_users) {
|
|
|
|
#if defined(__BIONIC__)
|
2018-10-23 07:50:04 +02:00
|
|
|
if (android::base::GetIntProperty("ro.product.first_api_level", 0) <= 28) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-24 23:44:10 +02:00
|
|
|
TestAidNamePrefix("/vendor/etc/passwd");
|
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-05-24 23:44:10 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(pwd, vendor_prefix_groups) {
|
|
|
|
#if defined(__BIONIC__)
|
2018-10-23 07:50:04 +02:00
|
|
|
if (android::base::GetIntProperty("ro.product.first_api_level", 0) <= 28) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-24 23:44:10 +02:00
|
|
|
TestAidNamePrefix("/vendor/etc/group");
|
|
|
|
#else
|
2019-03-09 00:20:23 +01:00
|
|
|
GTEST_SKIP() << "bionic-only test";
|
2018-05-24 23:44:10 +02:00
|
|
|
#endif
|
|
|
|
}
|