summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcutils/fs_config.cpp49
-rw-r--r--libcutils/tests/fs_config.cpp173
2 files changed, 181 insertions, 41 deletions
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index ea99595f4..40d3476ae 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -139,14 +139,8 @@ static const struct fs_path_config android_files[] = {
139 { 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" }, 139 { 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" },
140 { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 }, 140 { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 },
141 { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 }, 141 { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 },
142 { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/build.prop" },
143 { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/default.prop" },
144 { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_dirs" },
145 { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_files" },
146 { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 }, 142 { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 },
147 { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 }, 143 { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 },
148 { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_dirs" },
149 { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_files" },
150 { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, 144 { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" },
151 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" }, 145 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" },
152 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" }, 146 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" },
@@ -163,10 +157,6 @@ static const struct fs_path_config android_files[] = {
163 { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, 157 { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
164 { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, 158 { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
165 { 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" }, 159 { 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" },
166 { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/build.prop" },
167 { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/default.prop" },
168 { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs" },
169 { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_files" },
170 { 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" }, 160 { 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
171 { 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" }, 161 { 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
172 { 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 }, 162 { 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
@@ -205,9 +195,6 @@ static const struct fs_path_config android_files[] = {
205 // Support RT scheduling in Bluetooth 195 // Support RT scheduling in Bluetooth
206 { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) | 196 { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
207 CAP_MASK_LONG(CAP_SYS_NICE), 197 CAP_MASK_LONG(CAP_SYS_NICE),
208 "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
209 { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
210 CAP_MASK_LONG(CAP_SYS_NICE),
211 "vendor/bin/hw/android.hardware.bluetooth@1.0-service" }, 198 "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
212 199
213 // Support wifi_hal_legacy administering a network interface. 200 // Support wifi_hal_legacy administering a network interface.
@@ -233,8 +220,6 @@ static const struct fs_path_config android_files[] = {
233 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, 220 { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" },
234 { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, 221 { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" },
235 { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" }, 222 { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" },
236 { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" },
237 { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" },
238 { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, 223 { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" },
239 { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" }, 224 { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" },
240 { 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" }, 225 { 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) {
273 return fd; 258 return fd;
274} 259}
275 260
261// if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>"
262static bool is_partition(const char* path, size_t len) {
263 static const char* partitions[] = {"vendor/", "oem/", "odm/"};
264 for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
265 size_t plen = strlen(partitions[i]);
266 if (len <= plen) continue;
267 if (!strncmp(path, partitions[i], plen)) return true;
268 }
269 return false;
270}
271
272// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
273// "system/<partition>/<stuff>" to "<partition>/<stuff>"
274static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
275 if (!strncmp(prefix, path, len)) return true;
276
277 static const char system[] = "system/";
278 if (!strncmp(path, system, strlen(system))) {
279 path += strlen(system);
280 } else if (len <= strlen(system)) {
281 return false;
282 } else if (strncmp(prefix, system, strlen(system))) {
283 return false;
284 } else {
285 prefix += strlen(system);
286 len -= strlen(system);
287 }
288 return is_partition(prefix, len) && !strncmp(prefix, path, len);
289}
290
276static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) { 291static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
277 if (dir) { 292 if (dir) {
278 if (plen < len) { 293 if (plen < len) {
@@ -281,13 +296,13 @@ static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char*
281 } else { 296 } else {
282 // If name ends in * then allow partial matches. 297 // If name ends in * then allow partial matches.
283 if (prefix[len - 1] == '*') { 298 if (prefix[len - 1] == '*') {
284 return !strncmp(prefix, path, len - 1); 299 return prefix_cmp(prefix, path, len - 1);
285 } 300 }
286 if (plen != len) { 301 if (plen != len) {
287 return false; 302 return false;
288 } 303 }
289 } 304 }
290 return !strncmp(prefix, path, len); 305 return prefix_cmp(prefix, path, len);
291} 306}
292 307
293void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid, 308void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp
index 3917a0b2e..a62cd51a2 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/tests/fs_config.cpp
@@ -14,63 +14,188 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <inttypes.h>
18
17#include <string> 19#include <string>
18 20
19#include <gtest/gtest.h> 21#include <gtest/gtest.h>
20 22
23#include <android-base/file.h>
24#include <android-base/stringprintf.h>
21#include <android-base/strings.h> 25#include <android-base/strings.h>
22 26
23#include <private/android_filesystem_config.h> 27#include <private/android_filesystem_config.h>
28#include <private/fs_config.h>
24 29
25extern const struct fs_path_config* __for_testing_only__android_dirs; 30extern const fs_path_config* __for_testing_only__android_dirs;
26extern const struct fs_path_config* __for_testing_only__android_files; 31extern const fs_path_config* __for_testing_only__android_files;
27 32
28static void check_one(const struct fs_path_config* paths, const std::string& prefix, 33// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
29 const std::string& alternate) { 34// hit a nullptr termination, before we declare the list is just too big or
30 for (size_t idx = 0; paths[idx].prefix; ++idx) { 35// could be missing the nullptr.
31 std::string path(paths[idx].prefix); 36static constexpr size_t max_idx = 4096;
37
38static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
39 const std::string& prefix) {
40 bool retval = false;
41
42 std::string alternate = "system/" + prefix;
43
44 for (size_t idx = 0; idx < paths.size(); ++idx) {
45 size_t second;
46 std::string path(paths[idx]);
47 // check if there are multiple identical paths
48 for (second = idx + 1; second < paths.size(); ++second) {
49 if (path == paths[second]) {
50 GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
51 retval = true;
52 break;
53 }
54 }
55
56 // check if path is <partition>/
32 if (android::base::StartsWith(path, prefix.c_str())) { 57 if (android::base::StartsWith(path, prefix.c_str())) {
33 path = alternate + path.substr(prefix.length()); 58 // rebuild path to be system/<partition>/... to check for alias
34 size_t second; 59 path = alternate + path.substr(prefix.size());
35 for (second = 0; paths[second].prefix; ++second) { 60 for (second = 0; second < paths.size(); ++second) {
36 if (path == paths[second].prefix) break; 61 if (path == paths[second]) {
62 GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
63 << paths[idx] << " and " << paths[second]
64 << " (remove latter)";
65 retval = true;
66 break;
67 }
68 }
69 continue;
70 }
71
72 // check if path is system/<partition>/
73 if (android::base::StartsWith(path, alternate.c_str())) {
74 // rebuild path to be <partition>/... to check for alias
75 path = prefix + path.substr(alternate.size());
76 for (second = 0; second < paths.size(); ++second) {
77 if (path == paths[second]) break;
37 } 78 }
38 if (!paths[second].prefix) { 79 if (second >= paths.size()) {
39 // guaranteed to fail expectations, trigger test failure with 80 GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
40 // a message that reports the violation as an inequality. 81 << " with " << path;
41 EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str()); 82 retval = true;
42 } 83 }
43 } 84 }
44 } 85 }
86 return retval;
87}
88
89static bool check_unique(const fs_path_config* paths, const char* type_name,
90 const std::string& prefix) {
91 std::string config("system/core/libcutils/fs_config.cpp:android_");
92 config += type_name;
93 config += "[]";
94
95 bool retval = false;
96 std::vector<const char*> paths_tmp;
97 for (size_t idx = 0; paths[idx].prefix; ++idx) {
98 if (idx > max_idx) {
99 GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
100 retval = true;
101 break;
102 }
103 paths_tmp.push_back(paths[idx].prefix);
104 }
105
106 return check_unique(paths_tmp, config, prefix) || retval;
45} 107}
46 108
47static void check_two(const struct fs_path_config* paths, const std::string& prefix) { 109#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
110
111static bool check_unique(const std::string& config, const std::string& prefix) {
112 int retval = false;
113
114 std::string data;
115 if (!android::base::ReadFileToString(config, &data)) return retval;
116
117 const fs_path_config_from_file* pc =
118 reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
119 size_t len = data.size();
120
121 std::vector<const char*> paths_tmp;
122 size_t entry_number = 0;
123 while (len > 0) {
124 uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
125 if (host_len > len) {
126 GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
127 << host_len << " > " << len << ")";
128 const std::string unknown("?");
129 GTEST_LOG_(WARNING)
130 << config << ": entry[" << entry_number << "]={ "
131 << "len=" << ((len >= endof(pc, len))
132 ? android::base::StringPrintf("%" PRIu16, pc->len)
133 : unknown)
134 << ", mode=" << ((len >= endof(pc, mode))
135 ? android::base::StringPrintf("0%" PRIo16, pc->mode)
136 : unknown)
137 << ", uid=" << ((len >= endof(pc, uid))
138 ? android::base::StringPrintf("%" PRIu16, pc->uid)
139 : unknown)
140 << ", gid=" << ((len >= endof(pc, gid))
141 ? android::base::StringPrintf("%" PRIu16, pc->gid)
142 : unknown)
143 << ", capabilities="
144 << ((len >= endof(pc, capabilities))
145 ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
146 : unknown)
147 << ", prefix="
148 << ((len >= offsetof(fs_path_config_from_file, prefix))
149 ? android::base::StringPrintf(
150 "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
151 pc->prefix)
152 : unknown)
153 << " }";
154 retval = true;
155 break;
156 }
157 paths_tmp.push_back(pc->prefix);
158
159 pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
160 host_len);
161 len -= host_len;
162 ++entry_number;
163 }
164
165 return check_unique(paths_tmp, config, prefix) || retval;
166}
167
168void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
48 ASSERT_FALSE(paths == nullptr); 169 ASSERT_FALSE(paths == nullptr);
49 std::string alternate = "system/" + prefix; 170 ASSERT_FALSE(type_name == nullptr);
50 check_one(paths, prefix, alternate); 171 ASSERT_FALSE(prefix == nullptr);
51 check_one(paths, alternate, prefix); 172 bool check_internal = check_unique(paths, type_name, prefix);
173 EXPECT_FALSE(check_internal);
174 bool check_overrides =
175 check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
176 EXPECT_FALSE(check_overrides);
52} 177}
53 178
54TEST(fs_config, vendor_dirs_alias) { 179TEST(fs_config, vendor_dirs_alias) {
55 check_two(__for_testing_only__android_dirs, "vendor/"); 180 check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
56} 181}
57 182
58TEST(fs_config, vendor_files_alias) { 183TEST(fs_config, vendor_files_alias) {
59 check_two(__for_testing_only__android_files, "vendor/"); 184 check_two(__for_testing_only__android_files, "files", "vendor/");
60} 185}
61 186
62TEST(fs_config, oem_dirs_alias) { 187TEST(fs_config, oem_dirs_alias) {
63 check_two(__for_testing_only__android_dirs, "oem/"); 188 check_two(__for_testing_only__android_dirs, "dirs", "oem/");
64} 189}
65 190
66TEST(fs_config, oem_files_alias) { 191TEST(fs_config, oem_files_alias) {
67 check_two(__for_testing_only__android_files, "oem/"); 192 check_two(__for_testing_only__android_files, "files", "oem/");
68} 193}
69 194
70TEST(fs_config, odm_dirs_alias) { 195TEST(fs_config, odm_dirs_alias) {
71 check_two(__for_testing_only__android_dirs, "odm/"); 196 check_two(__for_testing_only__android_dirs, "dirs", "odm/");
72} 197}
73 198
74TEST(fs_config, odm_files_alias) { 199TEST(fs_config, odm_files_alias) {
75 check_two(__for_testing_only__android_files, "odm/"); 200 check_two(__for_testing_only__android_files, "files", "odm/");
76} 201}