c2b9fec50b
Require that users and groups found in /vendor/etc/{passwd,group} start with vendor_. This is needed to compliance with Treble as without this prefix, it is possible for a new system image to create a user/group name that a vendor has already used, causing a collision. Bug: 79528966 Test: new unit test Change-Id: I07500641e165f41526a8101592d83fa174e7a711
246 lines
7.5 KiB
C++
246 lines
7.5 KiB
C++
/*
|
|
* Copyright (C) 2018 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 <unistd.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "TemporaryFile.h"
|
|
|
|
#if defined(__BIONIC__)
|
|
#include "../libc/bionic/grp_pwd_file.cpp"
|
|
|
|
template <typename T>
|
|
class FileUnmapper {
|
|
public:
|
|
FileUnmapper(T& file) : file_(file) {
|
|
}
|
|
~FileUnmapper() {
|
|
file_.Unmap();
|
|
}
|
|
|
|
private:
|
|
T& file_;
|
|
};
|
|
|
|
void FindAndCheckPasswdEntry(PasswdFile* file, const char* name, uid_t uid, gid_t gid,
|
|
const char* dir, const char* shell) {
|
|
passwd_state_t name_passwd_state;
|
|
ASSERT_TRUE(file->FindByName(name, &name_passwd_state)) << name;
|
|
|
|
passwd& name_passwd = name_passwd_state.passwd_;
|
|
EXPECT_STREQ(name, name_passwd.pw_name);
|
|
EXPECT_EQ(nullptr, name_passwd.pw_passwd);
|
|
EXPECT_EQ(uid, name_passwd.pw_uid);
|
|
EXPECT_EQ(gid, name_passwd.pw_gid);
|
|
EXPECT_EQ(nullptr, name_passwd.pw_gecos);
|
|
EXPECT_STREQ(dir, name_passwd.pw_dir);
|
|
EXPECT_STREQ(shell, name_passwd.pw_shell);
|
|
|
|
passwd_state_t id_passwd_state;
|
|
ASSERT_TRUE(file->FindById(uid, &id_passwd_state)) << uid;
|
|
|
|
passwd& id_passwd = id_passwd_state.passwd_;
|
|
EXPECT_STREQ(name, id_passwd.pw_name);
|
|
EXPECT_EQ(nullptr, id_passwd.pw_passwd);
|
|
EXPECT_EQ(uid, id_passwd.pw_uid);
|
|
EXPECT_EQ(gid, id_passwd.pw_gid);
|
|
EXPECT_EQ(nullptr, id_passwd.pw_gecos);
|
|
EXPECT_STREQ(dir, id_passwd.pw_dir);
|
|
EXPECT_STREQ(shell, id_passwd.pw_shell);
|
|
}
|
|
|
|
void FindAndCheckGroupEntry(GroupFile* file, const char* name, gid_t gid) {
|
|
group_state_t name_group_state;
|
|
ASSERT_TRUE(file->FindByName(name, &name_group_state)) << name;
|
|
|
|
group& name_group = name_group_state.group_;
|
|
EXPECT_STREQ(name, name_group.gr_name);
|
|
EXPECT_EQ(nullptr, name_group.gr_passwd);
|
|
EXPECT_EQ(gid, name_group.gr_gid);
|
|
EXPECT_EQ(name_group.gr_name, name_group.gr_mem[0]);
|
|
EXPECT_EQ(nullptr, name_group.gr_mem[1]);
|
|
|
|
group_state_t id_group_state;
|
|
ASSERT_TRUE(file->FindById(gid, &id_group_state)) << gid;
|
|
|
|
group& id_group = id_group_state.group_;
|
|
EXPECT_STREQ(name, id_group.gr_name);
|
|
EXPECT_EQ(nullptr, id_group.gr_passwd);
|
|
EXPECT_EQ(gid, id_group.gr_gid);
|
|
EXPECT_EQ(id_group.gr_name, id_group.gr_mem[0]);
|
|
EXPECT_EQ(nullptr, id_group.gr_mem[1]);
|
|
}
|
|
|
|
#endif // __BIONIC__
|
|
|
|
TEST(grp_pwd_file, passwd_file_one_entry) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] = "name:password:1:2:user_info:dir:shell\n";
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
PasswdFile passwd_file(file.filename, nullptr);
|
|
FileUnmapper unmapper(passwd_file);
|
|
|
|
FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell");
|
|
|
|
EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr));
|
|
EXPECT_FALSE(passwd_file.FindById(3, nullptr));
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|
|
|
|
TEST(grp_pwd_file, group_file_one_entry) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] = "name:password:1:one,two,three\n";
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
GroupFile group_file(file.filename, nullptr);
|
|
FileUnmapper unmapper(group_file);
|
|
|
|
FindAndCheckGroupEntry(&group_file, "name", 1);
|
|
|
|
EXPECT_FALSE(group_file.FindByName("not_name", nullptr));
|
|
EXPECT_FALSE(group_file.FindById(3, nullptr));
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|
|
|
|
TEST(grp_pwd_file, passwd_file_many_entries) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] =
|
|
"first:x:1:2::dir:shell\n"
|
|
"abc1::3:4::def:abc\n"
|
|
"abc2::5:4:abc::abc\n"
|
|
"abc3::7:4:abc:def:\n"
|
|
"abc4::9:4:::abc\n"
|
|
"abc5::11:4:abc:def:abc\n"
|
|
"middle-ish::13:4::/:/system/bin/sh\n"
|
|
"abc7::15:4:abc::\n"
|
|
"abc8::17:4:::\n"
|
|
"abc9::19:4:abc:def:abc\n"
|
|
"abc10::21:4:abc:def:abc\n"
|
|
"abc11::23:4:abc:def:abc\n"
|
|
"abc12::25:4:abc:def:abc\n"
|
|
"abc13::27:4:abc:def:abc\n"
|
|
"last::29:4::last_user_dir:last_user_shell\n";
|
|
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
PasswdFile passwd_file(file.filename, nullptr);
|
|
FileUnmapper unmapper(passwd_file);
|
|
|
|
FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell");
|
|
FindAndCheckPasswdEntry(&passwd_file, "middle-ish", 13, 4, "/", "/system/bin/sh");
|
|
FindAndCheckPasswdEntry(&passwd_file, "last", 29, 4, "last_user_dir", "last_user_shell");
|
|
|
|
EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr));
|
|
EXPECT_FALSE(passwd_file.FindById(50, nullptr));
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|
|
|
|
TEST(grp_pwd_file, group_file_many_entries) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] =
|
|
"first:password:1:one,two,three\n"
|
|
"abc:def:2:group1,group2,group3\n"
|
|
"abc:def:3:\n"
|
|
"abc:def:4:\n"
|
|
"abc:def:5:\n"
|
|
"middle-ish:def_a_password_that_is_over_32_characters_long:6:\n"
|
|
"abc:def:7:\n"
|
|
"abc:def:8:\n"
|
|
"abc:def:20:\n"
|
|
"abc:def:25:\n"
|
|
"abc:def:27:\n"
|
|
"abc:def:52:\n"
|
|
"last::800:\n";
|
|
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
GroupFile group_file(file.filename, nullptr);
|
|
FileUnmapper unmapper(group_file);
|
|
|
|
FindAndCheckGroupEntry(&group_file, "first", 1);
|
|
FindAndCheckGroupEntry(&group_file, "middle-ish", 6);
|
|
FindAndCheckGroupEntry(&group_file, "last", 800);
|
|
|
|
EXPECT_FALSE(group_file.FindByName("not_name", nullptr));
|
|
EXPECT_FALSE(group_file.FindById(799, nullptr));
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|
|
|
|
TEST(grp_pwd_file, passwd_file_required_prefix) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] =
|
|
"name:password:1:2:user_info:dir:shell\n"
|
|
"vendor_name:password:3:4:user_info:dir:shell\n";
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
PasswdFile passwd_file(file.filename, "vendor_");
|
|
FileUnmapper unmapper(passwd_file);
|
|
|
|
EXPECT_FALSE(passwd_file.FindByName("name", nullptr));
|
|
EXPECT_FALSE(passwd_file.FindById(1, nullptr));
|
|
|
|
FindAndCheckPasswdEntry(&passwd_file, "vendor_name", 3, 4, "dir", "shell");
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|
|
|
|
TEST(grp_pwd_file, group_file_required_prefix) {
|
|
#if defined(__BIONIC__)
|
|
TemporaryFile file;
|
|
ASSERT_NE(-1, file.fd);
|
|
static const char test_string[] =
|
|
"name:password:1:one,two,three\n"
|
|
"vendor_name:password:2:one,two,three\n";
|
|
write(file.fd, test_string, sizeof(test_string) - 1);
|
|
|
|
GroupFile group_file(file.filename, "vendor_");
|
|
FileUnmapper unmapper(group_file);
|
|
|
|
EXPECT_FALSE(group_file.FindByName("name", nullptr));
|
|
EXPECT_FALSE(group_file.FindById(1, nullptr));
|
|
|
|
FindAndCheckGroupEntry(&group_file, "vendor_name", 2);
|
|
|
|
#else // __BIONIC__
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif // __BIONIC__
|
|
}
|