summaryrefslogtreecommitdiffstats
path: root/fs_mgr
diff options
context:
space:
mode:
authorMark Salyzyn2018-06-20 15:07:28 -0500
committerMark Salyzyn2018-06-27 16:49:06 -0500
commiteba4706a2ee0ea473c5066675c4397211f063b62 (patch)
tree3234fa8bc78996ba7b3bb838932feb6dcb870015 /fs_mgr
parent78ea17a6415c5d231606c7099eed7febc7801052 (diff)
downloadplatform-system-core-eba4706a2ee0ea473c5066675c4397211f063b62.tar.gz
platform-system-core-eba4706a2ee0ea473c5066675c4397211f063b62.tar.xz
platform-system-core-eba4706a2ee0ea473c5066675c4397211f063b62.zip
fs_mgr: Add support in fs_mgr_read_fstab_file for /proc/mounts
Generate fstab from /proc/mounts. Basically like any regular fstab minus the requirement for the Android fs_mgr_flags. Added a unit test to confirm that fs_mgr_read_fstab("/proc/mounts") matches the setmntent("/proc/mounts")+getmntent() content. As a result, discovered a bug in parse_flags that would report "ro" if the "rootcontext=..." flag was referenced. Test: fs_mgr_unit_test Bug: 109821005 Change-Id: I635ee979e11ee089b09adbedb5f42b6ba78026de
Diffstat (limited to 'fs_mgr')
-rw-r--r--fs_mgr/fs_mgr_fstab.cpp96
-rw-r--r--fs_mgr/tests/fs_mgr_test.cpp72
2 files changed, 122 insertions, 46 deletions
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index a14dba3c6..a5b3fe833 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -235,41 +235,46 @@ static int parse_flags(char *flags, struct flag_list *fl,
235 * If not found, the loop exits with fl[i].name being null. 235 * If not found, the loop exits with fl[i].name being null.
236 */ 236 */
237 for (i = 0; fl[i].name; i++) { 237 for (i = 0; fl[i].name; i++) {
238 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { 238 auto name = fl[i].name;
239 auto len = strlen(name);
240 auto end = len;
241 if (name[end - 1] == '=') --end;
242 if (!strncmp(p, name, len) && (p[end] == name[end])) {
239 f |= fl[i].flag; 243 f |= fl[i].flag;
240 if ((fl[i].flag == MF_CRYPT) && flag_vals) { 244 if (!flag_vals) break;
245 if (p[end] != '=') break;
246 char* arg = p + end + 1;
247 auto flag = fl[i].flag;
248 if (flag == MF_CRYPT) {
241 /* The encryptable flag is followed by an = and the 249 /* The encryptable flag is followed by an = and the
242 * location of the keys. Get it and return it. 250 * location of the keys. Get it and return it.
243 */ 251 */
244 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 252 flag_vals->key_loc = strdup(arg);
245 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) { 253 } else if (flag == MF_VERIFY) {
246 /* If the verify flag is followed by an = and the 254 /* If the verify flag is followed by an = and the
247 * location for the verity state, get it and return it. 255 * location for the verity state, get it and return it.
248 */ 256 */
249 char *start = strchr(p, '='); 257 flag_vals->verity_loc = strdup(arg);
250 if (start) { 258 } else if (flag == MF_FORCECRYPT) {
251 flag_vals->verity_loc = strdup(start + 1);
252 }
253 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
254 /* The forceencrypt flag is followed by an = and the 259 /* The forceencrypt flag is followed by an = and the
255 * location of the keys. Get it and return it. 260 * location of the keys. Get it and return it.
256 */ 261 */
257 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 262 flag_vals->key_loc = strdup(arg);
258 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) { 263 } else if (flag == MF_FORCEFDEORFBE) {
259 /* The forcefdeorfbe flag is followed by an = and the 264 /* The forcefdeorfbe flag is followed by an = and the
260 * location of the keys. Get it and return it. 265 * location of the keys. Get it and return it.
261 */ 266 */
262 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 267 flag_vals->key_loc = strdup(arg);
263 flag_vals->file_contents_mode = EM_AES_256_XTS; 268 flag_vals->file_contents_mode = EM_AES_256_XTS;
264 flag_vals->file_names_mode = EM_AES_256_CTS; 269 flag_vals->file_names_mode = EM_AES_256_CTS;
265 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) { 270 } else if (flag == MF_FILEENCRYPTION) {
266 /* The fileencryption flag is followed by an = and 271 /* The fileencryption flag is followed by an = and
267 * the mode of contents encryption, then optionally a 272 * the mode of contents encryption, then optionally a
268 * : and the mode of filenames encryption (defaults 273 * : and the mode of filenames encryption (defaults
269 * to aes-256-cts). Get it and return it. 274 * to aes-256-cts). Get it and return it.
270 */ 275 */
271 char *mode = strchr(p, '=') + 1; 276 auto mode = arg;
272 char *colon = strchr(mode, ':'); 277 auto colon = strchr(mode, ':');
273 if (colon) { 278 if (colon) {
274 *colon = '\0'; 279 *colon = '\0';
275 } 280 }
@@ -283,33 +288,30 @@ static int parse_flags(char *flags, struct flag_list *fl,
283 } else { 288 } else {
284 flag_vals->file_names_mode = EM_AES_256_CTS; 289 flag_vals->file_names_mode = EM_AES_256_CTS;
285 } 290 }
286 } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) { 291 } else if (flag == MF_KEYDIRECTORY) {
287 /* The metadata flag is followed by an = and the 292 /* The metadata flag is followed by an = and the
288 * directory for the keys. Get it and return it. 293 * directory for the keys. Get it and return it.
289 */ 294 */
290 flag_vals->key_dir = strdup(strchr(p, '=') + 1); 295 flag_vals->key_dir = strdup(arg);
291 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { 296 } else if (flag == MF_LENGTH) {
292 /* The length flag is followed by an = and the 297 /* The length flag is followed by an = and the
293 * size of the partition. Get it and return it. 298 * size of the partition. Get it and return it.
294 */ 299 */
295 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); 300 flag_vals->part_length = strtoll(arg, NULL, 0);
296 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { 301 } else if (flag == MF_VOLDMANAGED) {
297 /* The voldmanaged flag is followed by an = and the 302 /* The voldmanaged flag is followed by an = and the
298 * label, a colon and the partition number or the 303 * label, a colon and the partition number or the
299 * word "auto", e.g. 304 * word "auto", e.g.
300 * voldmanaged=sdcard:3 305 * voldmanaged=sdcard:3
301 * Get and return them. 306 * Get and return them.
302 */ 307 */
303 char *label_start; 308 auto label_start = arg;
304 char *label_end; 309 auto label_end = strchr(label_start, ':');
305 char *part_start;
306 310
307 label_start = strchr(p, '=') + 1;
308 label_end = strchr(p, ':');
309 if (label_end) { 311 if (label_end) {
310 flag_vals->label = strndup(label_start, 312 flag_vals->label = strndup(label_start,
311 (int) (label_end - label_start)); 313 (int) (label_end - label_start));
312 part_start = strchr(p, ':') + 1; 314 auto part_start = label_end + 1;
313 if (!strcmp(part_start, "auto")) { 315 if (!strcmp(part_start, "auto")) {
314 flag_vals->partnum = -1; 316 flag_vals->partnum = -1;
315 } else { 317 } else {
@@ -318,41 +320,41 @@ static int parse_flags(char *flags, struct flag_list *fl,
318 } else { 320 } else {
319 LERROR << "Warning: voldmanaged= flag malformed"; 321 LERROR << "Warning: voldmanaged= flag malformed";
320 } 322 }
321 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { 323 } else if (flag == MF_SWAPPRIO) {
322 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); 324 flag_vals->swap_prio = strtoll(arg, NULL, 0);
323 } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) { 325 } else if (flag == MF_MAX_COMP_STREAMS) {
324 flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0); 326 flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
325 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { 327 } else if (flag == MF_ZRAMSIZE) {
326 int is_percent = !!strrchr(p, '%'); 328 auto is_percent = !!strrchr(arg, '%');
327 unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0); 329 auto val = strtoll(arg, NULL, 0);
328 if (is_percent) 330 if (is_percent)
329 flag_vals->zram_size = calculate_zram_size(val); 331 flag_vals->zram_size = calculate_zram_size(val);
330 else 332 else
331 flag_vals->zram_size = val; 333 flag_vals->zram_size = val;
332 } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) { 334 } else if (flag == MF_RESERVEDSIZE) {
333 /* The reserved flag is followed by an = and the 335 /* The reserved flag is followed by an = and the
334 * reserved size of the partition. Get it and return it. 336 * reserved size of the partition. Get it and return it.
335 */ 337 */
336 flag_vals->reserved_size = parse_size(strchr(p, '=') + 1); 338 flag_vals->reserved_size = parse_size(arg);
337 } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) { 339 } else if (flag == MF_ERASEBLKSIZE) {
338 /* The erase block size flag is followed by an = and the flash 340 /* The erase block size flag is followed by an = and the flash
339 * erase block size. Get it, check that it is a power of 2 and 341 * erase block size. Get it, check that it is a power of 2 and
340 * at least 4096, and return it. 342 * at least 4096, and return it.
341 */ 343 */
342 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0); 344 auto val = strtoul(arg, NULL, 0);
343 if (val >= 4096 && (val & (val - 1)) == 0) 345 if (val >= 4096 && (val & (val - 1)) == 0)
344 flag_vals->erase_blk_size = val; 346 flag_vals->erase_blk_size = val;
345 } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) { 347 } else if (flag == MF_LOGICALBLKSIZE) {
346 /* The logical block size flag is followed by an = and the flash 348 /* The logical block size flag is followed by an = and the flash
347 * logical block size. Get it, check that it is a power of 2 and 349 * logical block size. Get it, check that it is a power of 2 and
348 * at least 4096, and return it. 350 * at least 4096, and return it.
349 */ 351 */
350 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0); 352 auto val = strtoul(arg, NULL, 0);
351 if (val >= 4096 && (val & (val - 1)) == 0) 353 if (val >= 4096 && (val & (val - 1)) == 0)
352 flag_vals->logical_blk_size = val; 354 flag_vals->logical_blk_size = val;
353 } else if ((fl[i].flag == MF_SYSFS) && flag_vals) { 355 } else if (flag == MF_SYSFS) {
354 /* The path to trigger device gc by idle-maint of vold. */ 356 /* The path to trigger device gc by idle-maint of vold. */
355 flag_vals->sysfs_path = strdup(strchr(p, '=') + 1); 357 flag_vals->sysfs_path = strdup(arg);
356 } 358 }
357 break; 359 break;
358 } 360 }
@@ -506,8 +508,7 @@ bool is_dt_compatible() {
506 return false; 508 return false;
507} 509}
508 510
509static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) 511static struct fstab* fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts) {
510{
511 int cnt, entries; 512 int cnt, entries;
512 ssize_t len; 513 ssize_t len;
513 size_t alloc_len = 0; 514 size_t alloc_len = 0;
@@ -607,7 +608,10 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
607 fstab->recs[cnt].fs_options = NULL; 608 fstab->recs[cnt].fs_options = NULL;
608 } 609 }
609 610
610 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 611 // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
612 if (proc_mounts) {
613 p += strlen(p);
614 } else if (!(p = strtok_r(NULL, delim, &save_ptr))) {
611 LERROR << "Error parsing fs_mgr_options"; 615 LERROR << "Error parsing fs_mgr_options";
612 goto err; 616 goto err;
613 } 617 }
@@ -739,7 +743,7 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
739 return nullptr; 743 return nullptr;
740 } 744 }
741 745
742 fstab = fs_mgr_read_fstab_file(fstab_file); 746 fstab = fs_mgr_read_fstab_file(fstab_file, !strcmp("/proc/mounts", fstab_path));
743 if (!fstab) { 747 if (!fstab) {
744 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'"; 748 LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
745 } 749 }
@@ -767,7 +771,7 @@ struct fstab *fs_mgr_read_fstab_dt()
767 return nullptr; 771 return nullptr;
768 } 772 }
769 773
770 struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get()); 774 struct fstab* fstab = fs_mgr_read_fstab_file(fstab_file.get(), false);
771 if (!fstab) { 775 if (!fstab) {
772 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:" 776 LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
773 << std::endl << fstab_buf; 777 << std::endl << fstab_buf;
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 2e76752c0..8b1c55a6e 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -14,13 +14,18 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <linux/fs.h>
18#include <mntent.h>
19
17#include <algorithm> 20#include <algorithm>
18#include <iterator> 21#include <iterator>
22#include <set>
19#include <string> 23#include <string>
20#include <utility> 24#include <utility>
21#include <vector> 25#include <vector>
22 26
23#include <android-base/strings.h> 27#include <android-base/strings.h>
28#include <fstab/fstab.h>
24#include <gtest/gtest.h> 29#include <gtest/gtest.h>
25 30
26#include "../fs_mgr_priv_boot_config.h" 31#include "../fs_mgr_priv_boot_config.h"
@@ -129,3 +134,70 @@ TEST(fs_mgr, fs_mgr_get_boot_config_from_kernel_cmdline) {
129 EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content)); 134 EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content));
130 EXPECT_TRUE(content.empty()) << content; 135 EXPECT_TRUE(content.empty()) << content;
131} 136}
137
138TEST(fs_mgr, fs_mgr_read_fstab_file_proc_mounts) {
139 auto fstab = fs_mgr_read_fstab("/proc/mounts");
140 ASSERT_NE(fstab, nullptr);
141
142 std::unique_ptr<std::FILE, int (*)(std::FILE*)> mounts(setmntent("/proc/mounts", "r"),
143 endmntent);
144 ASSERT_NE(mounts, nullptr);
145
146 mntent* mentry;
147 int i = 0;
148 while ((mentry = getmntent(mounts.get())) != nullptr) {
149 ASSERT_LT(i, fstab->num_entries);
150 auto fsrec = &fstab->recs[i];
151
152 std::string mnt_fsname(mentry->mnt_fsname ?: "nullptr");
153 std::string blk_device(fsrec->blk_device ?: "nullptr");
154 EXPECT_EQ(mnt_fsname, blk_device);
155
156 std::string mnt_dir(mentry->mnt_dir ?: "nullptr");
157 std::string mount_point(fsrec->mount_point ?: "nullptr");
158 EXPECT_EQ(mnt_dir, mount_point);
159
160 std::string mnt_type(mentry->mnt_type ?: "nullptr");
161 std::string fs_type(fsrec->fs_type ?: "nullptr");
162 EXPECT_EQ(mnt_type, fs_type);
163
164 std::set<std::string> mnt_opts;
165 for (auto& s : android::base::Split(mentry->mnt_opts ?: "nullptr", ",")) {
166 mnt_opts.emplace(s);
167 }
168 std::set<std::string> fs_options;
169 for (auto& s : android::base::Split(fsrec->fs_options ?: "nullptr", ",")) {
170 fs_options.emplace(s);
171 }
172 // matches private content in fs_mgr_fstab.c
173 static struct flag_list {
174 const char* name;
175 unsigned int flag;
176 } mount_flags[] = {
177 {"noatime", MS_NOATIME},
178 {"noexec", MS_NOEXEC},
179 {"nosuid", MS_NOSUID},
180 {"nodev", MS_NODEV},
181 {"nodiratime", MS_NODIRATIME},
182 {"ro", MS_RDONLY},
183 {"rw", 0},
184 {"remount", MS_REMOUNT},
185 {"bind", MS_BIND},
186 {"rec", MS_REC},
187 {"unbindable", MS_UNBINDABLE},
188 {"private", MS_PRIVATE},
189 {"slave", MS_SLAVE},
190 {"shared", MS_SHARED},
191 {"defaults", 0},
192 {0, 0},
193 };
194 for (auto f = 0; mount_flags[f].name; ++f) {
195 if (mount_flags[f].flag & fsrec->flags) {
196 fs_options.emplace(mount_flags[f].name);
197 }
198 }
199 if (!(fsrec->flags & MS_RDONLY)) fs_options.emplace("rw");
200 EXPECT_EQ(mnt_opts, fs_options);
201 ++i;
202 }
203}