1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/mount.h>
23 #include <unistd.h>
24
25 #include "fs_mgr_priv.h"
26
27 struct fs_mgr_flag_values {
28 char *key_loc;
29 char *verity_loc;
30 long long part_length;
31 char *label;
32 int partnum;
33 int swap_prio;
34 unsigned int zram_size;
35 unsigned int file_encryption_mode;
36 };
37
38 struct flag_list {
39 const char *name;
40 unsigned int flag;
41 };
42
43 static struct flag_list mount_flags[] = {
44 { "noatime", MS_NOATIME },
45 { "noexec", MS_NOEXEC },
46 { "nosuid", MS_NOSUID },
47 { "nodev", MS_NODEV },
48 { "nodiratime", MS_NODIRATIME },
49 { "ro", MS_RDONLY },
50 { "rw", 0 },
51 { "remount", MS_REMOUNT },
52 { "bind", MS_BIND },
53 { "rec", MS_REC },
54 { "unbindable", MS_UNBINDABLE },
55 { "private", MS_PRIVATE },
56 { "slave", MS_SLAVE },
57 { "shared", MS_SHARED },
58 { "defaults", 0 },
59 { 0, 0 },
60 };
61
62 static struct flag_list fs_mgr_flags[] = {
63 { "wait", MF_WAIT },
64 { "check", MF_CHECK },
65 { "encryptable=",MF_CRYPT },
66 { "forceencrypt=",MF_FORCECRYPT },
67 { "fileencryption=",MF_FILEENCRYPTION },
68 { "forcefdeorfbe=",MF_FORCEFDEORFBE },
69 { "nonremovable",MF_NONREMOVABLE },
70 { "voldmanaged=",MF_VOLDMANAGED},
71 { "length=", MF_LENGTH },
72 { "recoveryonly",MF_RECOVERYONLY },
73 { "swapprio=", MF_SWAPPRIO },
74 { "zramsize=", MF_ZRAMSIZE },
75 { "verifyatboot", MF_VERIFYATBOOT },
76 { "verify", MF_VERIFY },
77 { "noemulatedsd", MF_NOEMULATEDSD },
78 { "notrim", MF_NOTRIM },
79 { "formattable", MF_FORMATTABLE },
80 { "slotselect", MF_SLOTSELECT },
81 { "nofail", MF_NOFAIL },
82 { "latemount", MF_LATEMOUNT },
83 { "defaults", 0 },
84 { 0, 0 },
85 };
86
87 #define EM_SOFTWARE 1
88 #define EM_ICE 2
89
90 static struct flag_list encryption_modes[] = {
91 {"software", EM_SOFTWARE},
92 {"ice", EM_ICE},
93 {0, 0}
94 };
95
calculate_zram_size(unsigned int percentage)96 static uint64_t calculate_zram_size(unsigned int percentage)
97 {
98 uint64_t total;
99
100 total = sysconf(_SC_PHYS_PAGES);
101 total *= percentage;
102 total /= 100;
103
104 total *= sysconf(_SC_PAGESIZE);
105
106 return total;
107 }
108
parse_flags(char * flags,struct flag_list * fl,struct fs_mgr_flag_values * flag_vals,char * fs_options,int fs_options_len)109 static int parse_flags(char *flags, struct flag_list *fl,
110 struct fs_mgr_flag_values *flag_vals,
111 char *fs_options, int fs_options_len)
112 {
113 int f = 0;
114 int i;
115 char *p;
116 char *savep;
117
118 /* initialize flag values. If we find a relevant flag, we'll
119 * update the value */
120 if (flag_vals) {
121 memset(flag_vals, 0, sizeof(*flag_vals));
122 flag_vals->partnum = -1;
123 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
124 }
125
126 /* initialize fs_options to the null string */
127 if (fs_options && (fs_options_len > 0)) {
128 fs_options[0] = '\0';
129 }
130
131 p = strtok_r(flags, ",", &savep);
132 while (p) {
133 /* Look for the flag "p" in the flag list "fl"
134 * If not found, the loop exits with fl[i].name being null.
135 */
136 for (i = 0; fl[i].name; i++) {
137 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
138 f |= fl[i].flag;
139 if ((fl[i].flag == MF_CRYPT) && flag_vals) {
140 /* The encryptable flag is followed by an = and the
141 * location of the keys. Get it and return it.
142 */
143 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
144 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) {
145 /* If the verify flag is followed by an = and the
146 * location for the verity state, get it and return it.
147 */
148 char *start = strchr(p, '=');
149 if (start) {
150 flag_vals->verity_loc = strdup(start + 1);
151 }
152 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
153 /* The forceencrypt flag is followed by an = and the
154 * location of the keys. Get it and return it.
155 */
156 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
157 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) {
158 /* The forcefdeorfbe flag is followed by an = and the
159 * location of the keys. Get it and return it.
160 */
161 flag_vals->key_loc = strdup(strchr(p, '=') + 1);
162 flag_vals->file_encryption_mode = EM_SOFTWARE;
163 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
164 /* The fileencryption flag is followed by an = and the
165 * type of the encryption. Get it and return it.
166 */
167 const struct flag_list *j;
168 const char *mode = strchr(p, '=') + 1;
169 for (j = encryption_modes; j->name; ++j) {
170 if (!strcmp(mode, j->name)) {
171 flag_vals->file_encryption_mode = j->flag;
172 }
173 }
174 if (flag_vals->file_encryption_mode == 0) {
175 ERROR("Unknown file encryption mode: %s\n", mode);
176 }
177 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
178 /* The length flag is followed by an = and the
179 * size of the partition. Get it and return it.
180 */
181 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
182 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
183 /* The voldmanaged flag is followed by an = and the
184 * label, a colon and the partition number or the
185 * word "auto", e.g.
186 * voldmanaged=sdcard:3
187 * Get and return them.
188 */
189 char *label_start;
190 char *label_end;
191 char *part_start;
192
193 label_start = strchr(p, '=') + 1;
194 label_end = strchr(p, ':');
195 if (label_end) {
196 flag_vals->label = strndup(label_start,
197 (int) (label_end - label_start));
198 part_start = strchr(p, ':') + 1;
199 if (!strcmp(part_start, "auto")) {
200 flag_vals->partnum = -1;
201 } else {
202 flag_vals->partnum = strtol(part_start, NULL, 0);
203 }
204 } else {
205 ERROR("Warning: voldmanaged= flag malformed\n");
206 }
207 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
208 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
209 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
210 int is_percent = !!strrchr(p, '%');
211 unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0);
212 if (is_percent)
213 flag_vals->zram_size = calculate_zram_size(val);
214 else
215 flag_vals->zram_size = val;
216 }
217 break;
218 }
219 }
220
221 if (!fl[i].name) {
222 if (fs_options) {
223 /* It's not a known flag, so it must be a filesystem specific
224 * option. Add it to fs_options if it was passed in.
225 */
226 strlcat(fs_options, p, fs_options_len);
227 strlcat(fs_options, ",", fs_options_len);
228 } else {
229 /* fs_options was not passed in, so if the flag is unknown
230 * it's an error.
231 */
232 ERROR("Warning: unknown flag %s\n", p);
233 }
234 }
235 p = strtok_r(NULL, ",", &savep);
236 }
237
238 if (fs_options && fs_options[0]) {
239 /* remove the last trailing comma from the list of options */
240 fs_options[strlen(fs_options) - 1] = '\0';
241 }
242
243 return f;
244 }
245
fs_mgr_read_fstab(const char * fstab_path)246 struct fstab *fs_mgr_read_fstab(const char *fstab_path)
247 {
248 FILE *fstab_file;
249 int cnt, entries;
250 ssize_t len;
251 size_t alloc_len = 0;
252 char *line = NULL;
253 const char *delim = " \t";
254 char *save_ptr, *p;
255 struct fstab *fstab = NULL;
256 struct fs_mgr_flag_values flag_vals;
257 #define FS_OPTIONS_LEN 1024
258 char tmp_fs_options[FS_OPTIONS_LEN];
259
260 fstab_file = fopen(fstab_path, "r");
261 if (!fstab_file) {
262 ERROR("Cannot open file %s\n", fstab_path);
263 return 0;
264 }
265
266 entries = 0;
267 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
268 /* if the last character is a newline, shorten the string by 1 byte */
269 if (line[len - 1] == '\n') {
270 line[len - 1] = '\0';
271 }
272 /* Skip any leading whitespace */
273 p = line;
274 while (isspace(*p)) {
275 p++;
276 }
277 /* ignore comments or empty lines */
278 if (*p == '#' || *p == '\0')
279 continue;
280 entries++;
281 }
282
283 if (!entries) {
284 ERROR("No entries found in fstab\n");
285 goto err;
286 }
287
288 /* Allocate and init the fstab structure */
289 fstab = calloc(1, sizeof(struct fstab));
290 fstab->num_entries = entries;
291 fstab->fstab_filename = strdup(fstab_path);
292 fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
293
294 fseek(fstab_file, 0, SEEK_SET);
295
296 cnt = 0;
297 while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
298 /* if the last character is a newline, shorten the string by 1 byte */
299 if (line[len - 1] == '\n') {
300 line[len - 1] = '\0';
301 }
302
303 /* Skip any leading whitespace */
304 p = line;
305 while (isspace(*p)) {
306 p++;
307 }
308 /* ignore comments or empty lines */
309 if (*p == '#' || *p == '\0')
310 continue;
311
312 /* If a non-comment entry is greater than the size we allocated, give an
313 * error and quit. This can happen in the unlikely case the file changes
314 * between the two reads.
315 */
316 if (cnt >= entries) {
317 ERROR("Tried to process more entries than counted\n");
318 break;
319 }
320
321 if (!(p = strtok_r(line, delim, &save_ptr))) {
322 ERROR("Error parsing mount source\n");
323 goto err;
324 }
325 fstab->recs[cnt].blk_device = strdup(p);
326
327 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
328 ERROR("Error parsing mount_point\n");
329 goto err;
330 }
331 fstab->recs[cnt].mount_point = strdup(p);
332
333 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
334 ERROR("Error parsing fs_type\n");
335 goto err;
336 }
337 fstab->recs[cnt].fs_type = strdup(p);
338
339 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
340 ERROR("Error parsing mount_flags\n");
341 goto err;
342 }
343 tmp_fs_options[0] = '\0';
344 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
345 tmp_fs_options, FS_OPTIONS_LEN);
346
347 /* fs_options are optional */
348 if (tmp_fs_options[0]) {
349 fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
350 } else {
351 fstab->recs[cnt].fs_options = NULL;
352 }
353
354 if (!(p = strtok_r(NULL, delim, &save_ptr))) {
355 ERROR("Error parsing fs_mgr_options\n");
356 goto err;
357 }
358 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
359 &flag_vals, NULL, 0);
360 fstab->recs[cnt].key_loc = flag_vals.key_loc;
361 fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
362 fstab->recs[cnt].length = flag_vals.part_length;
363 fstab->recs[cnt].label = flag_vals.label;
364 fstab->recs[cnt].partnum = flag_vals.partnum;
365 fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
366 fstab->recs[cnt].zram_size = flag_vals.zram_size;
367 fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
368 cnt++;
369 }
370 /* If an A/B partition, modify block device to be the real block device */
371 if (fs_mgr_update_for_slotselect(fstab) != 0) {
372 ERROR("Error updating for slotselect\n");
373 goto err;
374 }
375 fclose(fstab_file);
376 free(line);
377 return fstab;
378
379 err:
380 fclose(fstab_file);
381 free(line);
382 if (fstab)
383 fs_mgr_free_fstab(fstab);
384 return NULL;
385 }
386
fs_mgr_free_fstab(struct fstab * fstab)387 void fs_mgr_free_fstab(struct fstab *fstab)
388 {
389 int i;
390
391 if (!fstab) {
392 return;
393 }
394
395 for (i = 0; i < fstab->num_entries; i++) {
396 /* Free the pointers return by strdup(3) */
397 free(fstab->recs[i].blk_device);
398 free(fstab->recs[i].mount_point);
399 free(fstab->recs[i].fs_type);
400 free(fstab->recs[i].fs_options);
401 free(fstab->recs[i].key_loc);
402 free(fstab->recs[i].label);
403 }
404
405 /* Free the fstab_recs array created by calloc(3) */
406 free(fstab->recs);
407
408 /* Free the fstab filename */
409 free(fstab->fstab_filename);
410
411 /* Free fstab */
412 free(fstab);
413 }
414
415 /* Add an entry to the fstab, and return 0 on success or -1 on error */
fs_mgr_add_entry(struct fstab * fstab,const char * mount_point,const char * fs_type,const char * blk_device)416 int fs_mgr_add_entry(struct fstab *fstab,
417 const char *mount_point, const char *fs_type,
418 const char *blk_device)
419 {
420 struct fstab_rec *new_fstab_recs;
421 int n = fstab->num_entries;
422
423 new_fstab_recs = (struct fstab_rec *)
424 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
425
426 if (!new_fstab_recs) {
427 return -1;
428 }
429
430 /* A new entry was added, so initialize it */
431 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
432 new_fstab_recs[n].mount_point = strdup(mount_point);
433 new_fstab_recs[n].fs_type = strdup(fs_type);
434 new_fstab_recs[n].blk_device = strdup(blk_device);
435 new_fstab_recs[n].length = 0;
436
437 /* Update the fstab struct */
438 fstab->recs = new_fstab_recs;
439 fstab->num_entries++;
440
441 return 0;
442 }
443
444 /*
445 * Returns the 1st matching fstab_rec that follows the start_rec.
446 * start_rec is the result of a previous search or NULL.
447 */
fs_mgr_get_entry_for_mount_point_after(struct fstab_rec * start_rec,struct fstab * fstab,const char * path)448 struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path)
449 {
450 int i;
451 if (!fstab) {
452 return NULL;
453 }
454
455 if (start_rec) {
456 for (i = 0; i < fstab->num_entries; i++) {
457 if (&fstab->recs[i] == start_rec) {
458 i++;
459 break;
460 }
461 }
462 } else {
463 i = 0;
464 }
465 for (; i < fstab->num_entries; i++) {
466 int len = strlen(fstab->recs[i].mount_point);
467 if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
468 (path[len] == '\0' || path[len] == '/')) {
469 return &fstab->recs[i];
470 }
471 }
472 return NULL;
473 }
474
475 /*
476 * Returns the 1st matching mount point.
477 * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
478 * and give the fstab_rec from the previous search.
479 */
fs_mgr_get_entry_for_mount_point(struct fstab * fstab,const char * path)480 struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
481 {
482 return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
483 }
484
fs_mgr_is_voldmanaged(const struct fstab_rec * fstab)485 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
486 {
487 return fstab->fs_mgr_flags & MF_VOLDMANAGED;
488 }
489
fs_mgr_is_nonremovable(const struct fstab_rec * fstab)490 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
491 {
492 return fstab->fs_mgr_flags & MF_NONREMOVABLE;
493 }
494
fs_mgr_is_verified(const struct fstab_rec * fstab)495 int fs_mgr_is_verified(const struct fstab_rec *fstab)
496 {
497 return fstab->fs_mgr_flags & MF_VERIFY;
498 }
499
fs_mgr_is_encryptable(const struct fstab_rec * fstab)500 int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
501 {
502 return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
503 }
504
fs_mgr_is_file_encrypted(const struct fstab_rec * fstab)505 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
506 {
507 return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
508 }
509
fs_mgr_get_file_encryption_mode(const struct fstab_rec * fstab)510 const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab)
511 {
512 const struct flag_list *j;
513 for (j = encryption_modes; j->name; ++j) {
514 if (fstab->file_encryption_mode == j->flag) {
515 return j->name;
516 }
517 }
518 return NULL;
519 }
520
fs_mgr_is_convertible_to_fbe(const struct fstab_rec * fstab)521 int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
522 {
523 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
524 }
525
fs_mgr_is_noemulatedsd(const struct fstab_rec * fstab)526 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
527 {
528 return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
529 }
530
fs_mgr_is_notrim(struct fstab_rec * fstab)531 int fs_mgr_is_notrim(struct fstab_rec *fstab)
532 {
533 return fstab->fs_mgr_flags & MF_NOTRIM;
534 }
535
fs_mgr_is_formattable(struct fstab_rec * fstab)536 int fs_mgr_is_formattable(struct fstab_rec *fstab)
537 {
538 return fstab->fs_mgr_flags & (MF_FORMATTABLE);
539 }
540
fs_mgr_is_slotselect(struct fstab_rec * fstab)541 int fs_mgr_is_slotselect(struct fstab_rec *fstab)
542 {
543 return fstab->fs_mgr_flags & MF_SLOTSELECT;
544 }
545
fs_mgr_is_nofail(struct fstab_rec * fstab)546 int fs_mgr_is_nofail(struct fstab_rec *fstab)
547 {
548 return fstab->fs_mgr_flags & MF_NOFAIL;
549 }
550
fs_mgr_is_latemount(struct fstab_rec * fstab)551 int fs_mgr_is_latemount(struct fstab_rec *fstab)
552 {
553 return fstab->fs_mgr_flags & MF_LATEMOUNT;
554 }
555