Merge changes Iad6ba65e,Ia6a7e8c9,Ida9405cb am: 037d2b71dc
am: 219e7200be
am: 7c466b936a
Change-Id: I9da0e906b391b9e4846c534eda77fb33d96e191a
This commit is contained in:
commit
645d62facb
2 changed files with 182 additions and 42 deletions
|
@ -139,14 +139,8 @@ static const struct fs_path_config android_files[] = {
|
|||
{ 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/odm/build.prop" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/odm/default.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_dirs" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_files" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_dirs" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_files" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" },
|
||||
|
@ -163,10 +157,6 @@ static const struct fs_path_config android_files[] = {
|
|||
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
|
||||
{ 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/build.prop" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/default.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_files" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
|
||||
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
|
||||
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
|
||||
|
@ -203,9 +193,6 @@ static const struct fs_path_config android_files[] = {
|
|||
|
||||
// Support Bluetooth legacy hal accessing /sys/class/rfkill
|
||||
// Support RT scheduling in Bluetooth
|
||||
{ 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
|
||||
CAP_MASK_LONG(CAP_SYS_NICE),
|
||||
"system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
|
||||
{ 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
|
||||
CAP_MASK_LONG(CAP_SYS_NICE),
|
||||
"vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
|
||||
|
@ -233,8 +220,6 @@ static const struct fs_path_config android_files[] = {
|
|||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" },
|
||||
|
@ -273,6 +258,36 @@ static int fs_config_open(int dir, int which, const char* target_out_path) {
|
|||
return fd;
|
||||
}
|
||||
|
||||
// if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>"
|
||||
static bool is_partition(const char* path, size_t len) {
|
||||
static const char* partitions[] = {"vendor/", "oem/", "odm/"};
|
||||
for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
|
||||
size_t plen = strlen(partitions[i]);
|
||||
if (len <= plen) continue;
|
||||
if (!strncmp(path, partitions[i], plen)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
|
||||
// "system/<partition>/<stuff>" to "<partition>/<stuff>"
|
||||
static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
|
||||
if (!strncmp(prefix, path, len)) return true;
|
||||
|
||||
static const char system[] = "system/";
|
||||
if (!strncmp(path, system, strlen(system))) {
|
||||
path += strlen(system);
|
||||
} else if (len <= strlen(system)) {
|
||||
return false;
|
||||
} else if (strncmp(prefix, system, strlen(system))) {
|
||||
return false;
|
||||
} else {
|
||||
prefix += strlen(system);
|
||||
len -= strlen(system);
|
||||
}
|
||||
return is_partition(prefix, len) && !strncmp(prefix, path, len);
|
||||
}
|
||||
|
||||
static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
|
||||
if (dir) {
|
||||
if (plen < len) {
|
||||
|
@ -281,13 +296,13 @@ static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char*
|
|||
} else {
|
||||
// If name ends in * then allow partial matches.
|
||||
if (prefix[len - 1] == '*') {
|
||||
return !strncmp(prefix, path, len - 1);
|
||||
return prefix_cmp(prefix, path, len - 1);
|
||||
}
|
||||
if (plen != len) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !strncmp(prefix, path, len);
|
||||
return prefix_cmp(prefix, path, len);
|
||||
}
|
||||
|
||||
void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
|
||||
|
|
|
@ -14,63 +14,188 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <private/fs_config.h>
|
||||
|
||||
extern const struct fs_path_config* __for_testing_only__android_dirs;
|
||||
extern const struct fs_path_config* __for_testing_only__android_files;
|
||||
extern const fs_path_config* __for_testing_only__android_dirs;
|
||||
extern const fs_path_config* __for_testing_only__android_files;
|
||||
|
||||
static void check_one(const struct fs_path_config* paths, const std::string& prefix,
|
||||
const std::string& alternate) {
|
||||
for (size_t idx = 0; paths[idx].prefix; ++idx) {
|
||||
std::string path(paths[idx].prefix);
|
||||
if (android::base::StartsWith(path, prefix.c_str())) {
|
||||
path = alternate + path.substr(prefix.length());
|
||||
size_t second;
|
||||
for (second = 0; paths[second].prefix; ++second) {
|
||||
if (path == paths[second].prefix) break;
|
||||
// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
|
||||
// hit a nullptr termination, before we declare the list is just too big or
|
||||
// could be missing the nullptr.
|
||||
static constexpr size_t max_idx = 4096;
|
||||
|
||||
static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
|
||||
const std::string& prefix) {
|
||||
bool retval = false;
|
||||
|
||||
std::string alternate = "system/" + prefix;
|
||||
|
||||
for (size_t idx = 0; idx < paths.size(); ++idx) {
|
||||
size_t second;
|
||||
std::string path(paths[idx]);
|
||||
// check if there are multiple identical paths
|
||||
for (second = idx + 1; second < paths.size(); ++second) {
|
||||
if (path == paths[second]) {
|
||||
GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
if (!paths[second].prefix) {
|
||||
// guaranteed to fail expectations, trigger test failure with
|
||||
// a message that reports the violation as an inequality.
|
||||
EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str());
|
||||
}
|
||||
|
||||
// check if path is <partition>/
|
||||
if (android::base::StartsWith(path, prefix.c_str())) {
|
||||
// rebuild path to be system/<partition>/... to check for alias
|
||||
path = alternate + path.substr(prefix.size());
|
||||
for (second = 0; second < paths.size(); ++second) {
|
||||
if (path == paths[second]) {
|
||||
GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
|
||||
<< paths[idx] << " and " << paths[second]
|
||||
<< " (remove latter)";
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if path is system/<partition>/
|
||||
if (android::base::StartsWith(path, alternate.c_str())) {
|
||||
// rebuild path to be <partition>/... to check for alias
|
||||
path = prefix + path.substr(alternate.size());
|
||||
for (second = 0; second < paths.size(); ++second) {
|
||||
if (path == paths[second]) break;
|
||||
}
|
||||
if (second >= paths.size()) {
|
||||
GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
|
||||
<< " with " << path;
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void check_two(const struct fs_path_config* paths, const std::string& prefix) {
|
||||
static bool check_unique(const fs_path_config* paths, const char* type_name,
|
||||
const std::string& prefix) {
|
||||
std::string config("system/core/libcutils/fs_config.cpp:android_");
|
||||
config += type_name;
|
||||
config += "[]";
|
||||
|
||||
bool retval = false;
|
||||
std::vector<const char*> paths_tmp;
|
||||
for (size_t idx = 0; paths[idx].prefix; ++idx) {
|
||||
if (idx > max_idx) {
|
||||
GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
paths_tmp.push_back(paths[idx].prefix);
|
||||
}
|
||||
|
||||
return check_unique(paths_tmp, config, prefix) || retval;
|
||||
}
|
||||
|
||||
#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
|
||||
|
||||
static bool check_unique(const std::string& config, const std::string& prefix) {
|
||||
int retval = false;
|
||||
|
||||
std::string data;
|
||||
if (!android::base::ReadFileToString(config, &data)) return retval;
|
||||
|
||||
const fs_path_config_from_file* pc =
|
||||
reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
|
||||
size_t len = data.size();
|
||||
|
||||
std::vector<const char*> paths_tmp;
|
||||
size_t entry_number = 0;
|
||||
while (len > 0) {
|
||||
uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
|
||||
if (host_len > len) {
|
||||
GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
|
||||
<< host_len << " > " << len << ")";
|
||||
const std::string unknown("?");
|
||||
GTEST_LOG_(WARNING)
|
||||
<< config << ": entry[" << entry_number << "]={ "
|
||||
<< "len=" << ((len >= endof(pc, len))
|
||||
? android::base::StringPrintf("%" PRIu16, pc->len)
|
||||
: unknown)
|
||||
<< ", mode=" << ((len >= endof(pc, mode))
|
||||
? android::base::StringPrintf("0%" PRIo16, pc->mode)
|
||||
: unknown)
|
||||
<< ", uid=" << ((len >= endof(pc, uid))
|
||||
? android::base::StringPrintf("%" PRIu16, pc->uid)
|
||||
: unknown)
|
||||
<< ", gid=" << ((len >= endof(pc, gid))
|
||||
? android::base::StringPrintf("%" PRIu16, pc->gid)
|
||||
: unknown)
|
||||
<< ", capabilities="
|
||||
<< ((len >= endof(pc, capabilities))
|
||||
? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
|
||||
: unknown)
|
||||
<< ", prefix="
|
||||
<< ((len >= offsetof(fs_path_config_from_file, prefix))
|
||||
? android::base::StringPrintf(
|
||||
"\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
|
||||
pc->prefix)
|
||||
: unknown)
|
||||
<< " }";
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
paths_tmp.push_back(pc->prefix);
|
||||
|
||||
pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
|
||||
host_len);
|
||||
len -= host_len;
|
||||
++entry_number;
|
||||
}
|
||||
|
||||
return check_unique(paths_tmp, config, prefix) || retval;
|
||||
}
|
||||
|
||||
void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
|
||||
ASSERT_FALSE(paths == nullptr);
|
||||
std::string alternate = "system/" + prefix;
|
||||
check_one(paths, prefix, alternate);
|
||||
check_one(paths, alternate, prefix);
|
||||
ASSERT_FALSE(type_name == nullptr);
|
||||
ASSERT_FALSE(prefix == nullptr);
|
||||
bool check_internal = check_unique(paths, type_name, prefix);
|
||||
EXPECT_FALSE(check_internal);
|
||||
bool check_overrides =
|
||||
check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
|
||||
EXPECT_FALSE(check_overrides);
|
||||
}
|
||||
|
||||
TEST(fs_config, vendor_dirs_alias) {
|
||||
check_two(__for_testing_only__android_dirs, "vendor/");
|
||||
check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
|
||||
}
|
||||
|
||||
TEST(fs_config, vendor_files_alias) {
|
||||
check_two(__for_testing_only__android_files, "vendor/");
|
||||
check_two(__for_testing_only__android_files, "files", "vendor/");
|
||||
}
|
||||
|
||||
TEST(fs_config, oem_dirs_alias) {
|
||||
check_two(__for_testing_only__android_dirs, "oem/");
|
||||
check_two(__for_testing_only__android_dirs, "dirs", "oem/");
|
||||
}
|
||||
|
||||
TEST(fs_config, oem_files_alias) {
|
||||
check_two(__for_testing_only__android_files, "oem/");
|
||||
check_two(__for_testing_only__android_files, "files", "oem/");
|
||||
}
|
||||
|
||||
TEST(fs_config, odm_dirs_alias) {
|
||||
check_two(__for_testing_only__android_dirs, "odm/");
|
||||
check_two(__for_testing_only__android_dirs, "dirs", "odm/");
|
||||
}
|
||||
|
||||
TEST(fs_config, odm_files_alias) {
|
||||
check_two(__for_testing_only__android_files, "odm/");
|
||||
check_two(__for_testing_only__android_files, "files", "odm/");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue