• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <dirent.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/mount.h>
24 #include <unistd.h>
25 
26 #include <android-base/file.h>
27 #include <android-base/stringprintf.h>
28 #include <android-base/strings.h>
29 
30 #include "fs_mgr_priv.h"
31 
32 const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
33 
34 struct fs_mgr_flag_values {
35     char *key_loc;
36     char* key_dir;
37     char *verity_loc;
38     long long part_length;
39     char *label;
40     int partnum;
41     int swap_prio;
42     int max_comp_streams;
43     unsigned int zram_size;
44     uint64_t reserved_size;
45     unsigned int file_contents_mode;
46     unsigned int file_names_mode;
47     unsigned int erase_blk_size;
48     unsigned int logical_blk_size;
49 };
50 
51 struct flag_list {
52     const char *name;
53     unsigned int flag;
54 };
55 
56 static struct flag_list mount_flags[] = {
57     { "noatime",    MS_NOATIME },
58     { "noexec",     MS_NOEXEC },
59     { "nosuid",     MS_NOSUID },
60     { "nodev",      MS_NODEV },
61     { "nodiratime", MS_NODIRATIME },
62     { "ro",         MS_RDONLY },
63     { "rw",         0 },
64     { "remount",    MS_REMOUNT },
65     { "bind",       MS_BIND },
66     { "rec",        MS_REC },
67     { "unbindable", MS_UNBINDABLE },
68     { "private",    MS_PRIVATE },
69     { "slave",      MS_SLAVE },
70     { "shared",     MS_SHARED },
71     { "defaults",   0 },
72     { 0,            0 },
73 };
74 
75 static struct flag_list fs_mgr_flags[] = {
76     {"wait", MF_WAIT},
77     {"check", MF_CHECK},
78     {"encryptable=", MF_CRYPT},
79     {"forceencrypt=", MF_FORCECRYPT},
80     {"fileencryption=", MF_FILEENCRYPTION},
81     {"forcefdeorfbe=", MF_FORCEFDEORFBE},
82     {"keydirectory=", MF_KEYDIRECTORY},
83     {"nonremovable", MF_NONREMOVABLE},
84     {"voldmanaged=", MF_VOLDMANAGED},
85     {"length=", MF_LENGTH},
86     {"recoveryonly", MF_RECOVERYONLY},
87     {"swapprio=", MF_SWAPPRIO},
88     {"zramsize=", MF_ZRAMSIZE},
89     {"max_comp_streams=", MF_MAX_COMP_STREAMS},
90     {"verifyatboot", MF_VERIFYATBOOT},
91     {"verify", MF_VERIFY},
92     {"avb", MF_AVB},
93     {"noemulatedsd", MF_NOEMULATEDSD},
94     {"notrim", MF_NOTRIM},
95     {"formattable", MF_FORMATTABLE},
96     {"slotselect", MF_SLOTSELECT},
97     {"nofail", MF_NOFAIL},
98     {"latemount", MF_LATEMOUNT},
99     {"reservedsize=", MF_RESERVEDSIZE},
100     {"quota", MF_QUOTA},
101     {"eraseblk=", MF_ERASEBLKSIZE},
102     {"logicalblk=", MF_LOGICALBLKSIZE},
103     {"defaults", 0},
104     {0, 0},
105 };
106 
107 #define EM_AES_256_XTS  1
108 #define EM_ICE          2
109 #define EM_AES_256_CTS  3
110 #define EM_AES_256_HEH  4
111 
112 static const struct flag_list file_contents_encryption_modes[] = {
113     {"aes-256-xts", EM_AES_256_XTS},
114     {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
115     {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
116     {0, 0},
117 };
118 
119 static const struct flag_list file_names_encryption_modes[] = {
120     {"aes-256-cts", EM_AES_256_CTS},
121     {"aes-256-heh", EM_AES_256_HEH},
122     {0, 0},
123 };
124 
encryption_mode_to_flag(const struct flag_list * list,const char * mode,const char * type)125 static unsigned int encryption_mode_to_flag(const struct flag_list *list,
126                                             const char *mode, const char *type)
127 {
128     const struct flag_list *j;
129 
130     for (j = list; j->name; ++j) {
131         if (!strcmp(mode, j->name)) {
132             return j->flag;
133         }
134     }
135     LERROR << "Unknown " << type << " encryption mode: " << mode;
136     return 0;
137 }
138 
flag_to_encryption_mode(const struct flag_list * list,unsigned int flag)139 static const char *flag_to_encryption_mode(const struct flag_list *list,
140                                            unsigned int flag)
141 {
142     const struct flag_list *j;
143 
144     for (j = list; j->name; ++j) {
145         if (flag == j->flag) {
146             return j->name;
147         }
148     }
149     return nullptr;
150 }
151 
calculate_zram_size(unsigned int percentage)152 static uint64_t calculate_zram_size(unsigned int percentage)
153 {
154     uint64_t total;
155 
156     total  = sysconf(_SC_PHYS_PAGES);
157     total *= percentage;
158     total /= 100;
159 
160     total *= sysconf(_SC_PAGESIZE);
161 
162     return total;
163 }
164 
parse_size(const char * arg)165 static uint64_t parse_size(const char *arg)
166 {
167     char *endptr;
168     uint64_t size = strtoull(arg, &endptr, 10);
169     if (*endptr == 'k' || *endptr == 'K')
170         size *= 1024LL;
171     else if (*endptr == 'm' || *endptr == 'M')
172         size *= 1024LL * 1024LL;
173     else if (*endptr == 'g' || *endptr == 'G')
174         size *= 1024LL * 1024LL * 1024LL;
175 
176     return size;
177 }
178 
179 /* fills 'dt_value' with the underlying device tree value string without
180  * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
181  * otherwise.
182  */
read_dt_file(const std::string & file_name,std::string * dt_value)183 static bool read_dt_file(const std::string& file_name, std::string* dt_value)
184 {
185     if (android::base::ReadFileToString(file_name, dt_value)) {
186         if (!dt_value->empty()) {
187             // trim the trailing '\0' out, otherwise the comparison
188             // will produce false-negatives.
189             dt_value->resize(dt_value->size() - 1);
190             return true;
191         }
192     }
193 
194     return false;
195 }
196 
parse_flags(char * flags,struct flag_list * fl,struct fs_mgr_flag_values * flag_vals,char * fs_options,int fs_options_len)197 static int parse_flags(char *flags, struct flag_list *fl,
198                        struct fs_mgr_flag_values *flag_vals,
199                        char *fs_options, int fs_options_len)
200 {
201     int f = 0;
202     int i;
203     char *p;
204     char *savep;
205 
206     /* initialize flag values.  If we find a relevant flag, we'll
207      * update the value */
208     if (flag_vals) {
209         memset(flag_vals, 0, sizeof(*flag_vals));
210         flag_vals->partnum = -1;
211         flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
212     }
213 
214     /* initialize fs_options to the null string */
215     if (fs_options && (fs_options_len > 0)) {
216         fs_options[0] = '\0';
217     }
218 
219     p = strtok_r(flags, ",", &savep);
220     while (p) {
221         /* Look for the flag "p" in the flag list "fl"
222          * If not found, the loop exits with fl[i].name being null.
223          */
224         for (i = 0; fl[i].name; i++) {
225             if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
226                 f |= fl[i].flag;
227                 if ((fl[i].flag == MF_CRYPT) && flag_vals) {
228                     /* The encryptable flag is followed by an = and the
229                      * location of the keys.  Get it and return it.
230                      */
231                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
232                 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) {
233                     /* If the verify flag is followed by an = and the
234                      * location for the verity state,  get it and return it.
235                      */
236                     char *start = strchr(p, '=');
237                     if (start) {
238                         flag_vals->verity_loc = strdup(start + 1);
239                     }
240                 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
241                     /* The forceencrypt flag is followed by an = and the
242                      * location of the keys.  Get it and return it.
243                      */
244                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
245                 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) {
246                     /* The forcefdeorfbe flag is followed by an = and the
247                      * location of the keys.  Get it and return it.
248                      */
249                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
250                     flag_vals->file_contents_mode = EM_AES_256_XTS;
251                     flag_vals->file_names_mode = EM_AES_256_CTS;
252                 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
253                     /* The fileencryption flag is followed by an = and
254                      * the mode of contents encryption, then optionally a
255                      * : and the mode of filenames encryption (defaults
256                      * to aes-256-cts).  Get it and return it.
257                      */
258                     char *mode = strchr(p, '=') + 1;
259                     char *colon = strchr(mode, ':');
260                     if (colon) {
261                         *colon = '\0';
262                     }
263                     flag_vals->file_contents_mode =
264                         encryption_mode_to_flag(file_contents_encryption_modes,
265                                                 mode, "file contents");
266                     if (colon) {
267                         flag_vals->file_names_mode =
268                             encryption_mode_to_flag(file_names_encryption_modes,
269                                                     colon + 1, "file names");
270                     } else {
271                         flag_vals->file_names_mode = EM_AES_256_CTS;
272                     }
273                 } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
274                     /* The metadata flag is followed by an = and the
275                      * directory for the keys.  Get it and return it.
276                      */
277                     flag_vals->key_dir = strdup(strchr(p, '=') + 1);
278                 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
279                     /* The length flag is followed by an = and the
280                      * size of the partition.  Get it and return it.
281                      */
282                     flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
283                 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
284                     /* The voldmanaged flag is followed by an = and the
285                      * label, a colon and the partition number or the
286                      * word "auto", e.g.
287                      *   voldmanaged=sdcard:3
288                      * Get and return them.
289                      */
290                     char *label_start;
291                     char *label_end;
292                     char *part_start;
293 
294                     label_start = strchr(p, '=') + 1;
295                     label_end = strchr(p, ':');
296                     if (label_end) {
297                         flag_vals->label = strndup(label_start,
298                                                    (int) (label_end - label_start));
299                         part_start = strchr(p, ':') + 1;
300                         if (!strcmp(part_start, "auto")) {
301                             flag_vals->partnum = -1;
302                         } else {
303                             flag_vals->partnum = strtol(part_start, NULL, 0);
304                         }
305                     } else {
306                         LERROR << "Warning: voldmanaged= flag malformed";
307                     }
308                 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
309                     flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
310                 } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) {
311                     flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0);
312                 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
313                     int is_percent = !!strrchr(p, '%');
314                     unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0);
315                     if (is_percent)
316                         flag_vals->zram_size = calculate_zram_size(val);
317                     else
318                         flag_vals->zram_size = val;
319                 } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
320                     /* The reserved flag is followed by an = and the
321                      * reserved size of the partition.  Get it and return it.
322                      */
323                     flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
324                 } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) {
325                     /* The erase block size flag is followed by an = and the flash
326                      * erase block size. Get it, check that it is a power of 2 and
327                      * at least 4096, and return it.
328                      */
329                     unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
330                     if (val >= 4096 && (val & (val - 1)) == 0)
331                         flag_vals->erase_blk_size = val;
332                 } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) {
333                     /* The logical block size flag is followed by an = and the flash
334                      * logical block size. Get it, check that it is a power of 2 and
335                      * at least 4096, and return it.
336                      */
337                     unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
338                     if (val >= 4096 && (val & (val - 1)) == 0)
339                         flag_vals->logical_blk_size = val;
340                 }
341                 break;
342             }
343         }
344 
345         if (!fl[i].name) {
346             if (fs_options) {
347                 /* It's not a known flag, so it must be a filesystem specific
348                  * option.  Add it to fs_options if it was passed in.
349                  */
350                 strlcat(fs_options, p, fs_options_len);
351                 strlcat(fs_options, ",", fs_options_len);
352             } else {
353                 /* fs_options was not passed in, so if the flag is unknown
354                  * it's an error.
355                  */
356                 LERROR << "Warning: unknown flag " << p;
357             }
358         }
359         p = strtok_r(NULL, ",", &savep);
360     }
361 
362     if (fs_options && fs_options[0]) {
363         /* remove the last trailing comma from the list of options */
364         fs_options[strlen(fs_options) - 1] = '\0';
365     }
366 
367     return f;
368 }
369 
init_android_dt_dir()370 static std::string init_android_dt_dir() {
371     std::string android_dt_dir;
372     // The platform may specify a custom Android DT path in kernel cmdline
373     if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
374         // Fall back to the standard procfs-based path
375         android_dt_dir = kDefaultAndroidDtDir;
376     }
377     return android_dt_dir;
378 }
379 
380 // FIXME: The same logic is duplicated in system/core/init/
get_android_dt_dir()381 const std::string& get_android_dt_dir() {
382     // Set once and saves time for subsequent calls to this function
383     static const std::string kAndroidDtDir = init_android_dt_dir();
384     return kAndroidDtDir;
385 }
386 
is_dt_fstab_compatible()387 static bool is_dt_fstab_compatible() {
388     std::string dt_value;
389     std::string file_name = get_android_dt_dir() + "/fstab/compatible";
390     if (read_dt_file(file_name, &dt_value)) {
391         if (dt_value == "android,fstab") {
392             return true;
393         }
394     }
395 
396     return false;
397 }
398 
read_fstab_from_dt()399 static std::string read_fstab_from_dt() {
400     std::string fstab;
401     if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
402         return fstab;
403     }
404 
405     std::string fstabdir_name = get_android_dt_dir() + "/fstab";
406     std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
407     if (!fstabdir) return fstab;
408 
409     dirent* dp;
410     while ((dp = readdir(fstabdir.get())) != NULL) {
411         // skip over name, compatible and .
412         if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
413 
414         // create <dev> <mnt_point>  <type>  <mnt_flags>  <fsmgr_flags>\n
415         std::vector<std::string> fstab_entry;
416         std::string file_name;
417         std::string value;
418         // skip a partition entry if the status property is present and not set to ok
419         file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
420         if (read_dt_file(file_name, &value)) {
421             if (value != "okay" && value != "ok") {
422                 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
423                 continue;
424             }
425         }
426 
427         file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
428         if (!read_dt_file(file_name, &value)) {
429             LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
430             fstab.clear();
431             break;
432         }
433         fstab_entry.push_back(value);
434         fstab_entry.push_back(android::base::StringPrintf("/%s", dp->d_name));
435 
436         file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
437         if (!read_dt_file(file_name, &value)) {
438             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
439             fstab.clear();
440             break;
441         }
442         fstab_entry.push_back(value);
443 
444         file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
445         if (!read_dt_file(file_name, &value)) {
446             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
447             fstab.clear();
448             break;
449         }
450         fstab_entry.push_back(value);
451 
452         file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
453         if (!read_dt_file(file_name, &value)) {
454             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
455             fstab.clear();
456             break;
457         }
458         fstab_entry.push_back(value);
459 
460         fstab += android::base::Join(fstab_entry, " ");
461         fstab += '\n';
462     }
463 
464     return fstab;
465 }
466 
is_dt_compatible()467 bool is_dt_compatible() {
468     std::string file_name = get_android_dt_dir() + "/compatible";
469     std::string dt_value;
470     if (read_dt_file(file_name, &dt_value)) {
471         if (dt_value == "android,firmware") {
472             return true;
473         }
474     }
475 
476     return false;
477 }
478 
fs_mgr_read_fstab_file(FILE * fstab_file)479 static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
480 {
481     int cnt, entries;
482     ssize_t len;
483     size_t alloc_len = 0;
484     char *line = NULL;
485     const char *delim = " \t";
486     char *save_ptr, *p;
487     struct fstab *fstab = NULL;
488     struct fs_mgr_flag_values flag_vals;
489 #define FS_OPTIONS_LEN 1024
490     char tmp_fs_options[FS_OPTIONS_LEN];
491 
492     entries = 0;
493     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
494         /* if the last character is a newline, shorten the string by 1 byte */
495         if (line[len - 1] == '\n') {
496             line[len - 1] = '\0';
497         }
498         /* Skip any leading whitespace */
499         p = line;
500         while (isspace(*p)) {
501             p++;
502         }
503         /* ignore comments or empty lines */
504         if (*p == '#' || *p == '\0')
505             continue;
506         entries++;
507     }
508 
509     if (!entries) {
510         LERROR << "No entries found in fstab";
511         goto err;
512     }
513 
514     /* Allocate and init the fstab structure */
515     fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
516     fstab->num_entries = entries;
517     fstab->recs = static_cast<struct fstab_rec *>(
518         calloc(fstab->num_entries, sizeof(struct fstab_rec)));
519 
520     fseek(fstab_file, 0, SEEK_SET);
521 
522     cnt = 0;
523     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
524         /* if the last character is a newline, shorten the string by 1 byte */
525         if (line[len - 1] == '\n') {
526             line[len - 1] = '\0';
527         }
528 
529         /* Skip any leading whitespace */
530         p = line;
531         while (isspace(*p)) {
532             p++;
533         }
534         /* ignore comments or empty lines */
535         if (*p == '#' || *p == '\0')
536             continue;
537 
538         /* If a non-comment entry is greater than the size we allocated, give an
539          * error and quit.  This can happen in the unlikely case the file changes
540          * between the two reads.
541          */
542         if (cnt >= entries) {
543             LERROR << "Tried to process more entries than counted";
544             break;
545         }
546 
547         if (!(p = strtok_r(line, delim, &save_ptr))) {
548             LERROR << "Error parsing mount source";
549             goto err;
550         }
551         fstab->recs[cnt].blk_device = strdup(p);
552 
553         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
554             LERROR << "Error parsing mount_point";
555             goto err;
556         }
557         fstab->recs[cnt].mount_point = strdup(p);
558 
559         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
560             LERROR << "Error parsing fs_type";
561             goto err;
562         }
563         fstab->recs[cnt].fs_type = strdup(p);
564 
565         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
566             LERROR << "Error parsing mount_flags";
567             goto err;
568         }
569         tmp_fs_options[0] = '\0';
570         fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
571                                        tmp_fs_options, FS_OPTIONS_LEN);
572 
573         /* fs_options are optional */
574         if (tmp_fs_options[0]) {
575             fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
576         } else {
577             fstab->recs[cnt].fs_options = NULL;
578         }
579 
580         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
581             LERROR << "Error parsing fs_mgr_options";
582             goto err;
583         }
584         fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
585                                                     &flag_vals, NULL, 0);
586         fstab->recs[cnt].key_loc = flag_vals.key_loc;
587         fstab->recs[cnt].key_dir = flag_vals.key_dir;
588         fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
589         fstab->recs[cnt].length = flag_vals.part_length;
590         fstab->recs[cnt].label = flag_vals.label;
591         fstab->recs[cnt].partnum = flag_vals.partnum;
592         fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
593         fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
594         fstab->recs[cnt].zram_size = flag_vals.zram_size;
595         fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
596         fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
597         fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
598         fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
599         fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
600         cnt++;
601     }
602     /* If an A/B partition, modify block device to be the real block device */
603     if (!fs_mgr_update_for_slotselect(fstab)) {
604         LERROR << "Error updating for slotselect";
605         goto err;
606     }
607     free(line);
608     return fstab;
609 
610 err:
611     free(line);
612     if (fstab)
613         fs_mgr_free_fstab(fstab);
614     return NULL;
615 }
616 
617 /* merges fstab entries from both a and b, then returns the merged result.
618  * note that the caller should only manage the return pointer without
619  * doing further memory management for the two inputs, i.e. only need to
620  * frees up memory of the return value without touching a and b. */
in_place_merge(struct fstab * a,struct fstab * b)621 static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
622 {
623     if (!a) return b;
624     if (!b) return a;
625 
626     int total_entries = a->num_entries + b->num_entries;
627     a->recs = static_cast<struct fstab_rec *>(realloc(
628         a->recs, total_entries * (sizeof(struct fstab_rec))));
629     if (!a->recs) {
630         LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
631         // If realloc() fails the original block is left untouched;
632         // it is not freed or moved. So we have to free both a and b here.
633         fs_mgr_free_fstab(a);
634         fs_mgr_free_fstab(b);
635         return nullptr;
636     }
637 
638     for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
639         // copy the pointer directly *without* malloc and memcpy
640         a->recs[i] = b->recs[j];
641     }
642 
643     // Frees up b, but don't free b->recs[X] to make sure they are
644     // accessible through a->recs[X].
645     free(b->fstab_filename);
646     free(b);
647 
648     a->num_entries = total_entries;
649     return a;
650 }
651 
fs_mgr_read_fstab(const char * fstab_path)652 struct fstab *fs_mgr_read_fstab(const char *fstab_path)
653 {
654     FILE *fstab_file;
655     struct fstab *fstab;
656 
657     fstab_file = fopen(fstab_path, "r");
658     if (!fstab_file) {
659         PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
660         return nullptr;
661     }
662 
663     fstab = fs_mgr_read_fstab_file(fstab_file);
664     if (fstab) {
665         fstab->fstab_filename = strdup(fstab_path);
666     } else {
667         LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
668     }
669 
670     fclose(fstab_file);
671     return fstab;
672 }
673 
674 /* Returns fstab entries parsed from the device tree if they
675  * exist
676  */
fs_mgr_read_fstab_dt()677 struct fstab *fs_mgr_read_fstab_dt()
678 {
679     std::string fstab_buf = read_fstab_from_dt();
680     if (fstab_buf.empty()) {
681         LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
682         return nullptr;
683     }
684 
685     std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
686         fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
687                  fstab_buf.length(), "r"), fclose);
688     if (!fstab_file) {
689         PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
690         return nullptr;
691     }
692 
693     struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
694     if (!fstab) {
695         LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
696                << std::endl << fstab_buf;
697     }
698 
699     return fstab;
700 }
701 
702 /*
703  * tries to load default fstab.<hardware> file from /odm/etc, /vendor/etc
704  * or /. loads the first one found and also combines fstab entries passed
705  * in from device tree.
706  */
fs_mgr_read_fstab_default()707 struct fstab *fs_mgr_read_fstab_default()
708 {
709     std::string hw;
710     std::string default_fstab;
711 
712     // Use different fstab paths for normal boot and recovery boot, respectively
713     if (access("/sbin/recovery", F_OK) == 0) {
714         default_fstab = "/etc/recovery.fstab";
715     } else if (fs_mgr_get_boot_config("hardware", &hw)) {  // normal boot
716         for (const char *prefix : {"/odm/etc/fstab.","/vendor/etc/fstab.", "/fstab."}) {
717             default_fstab = prefix + hw;
718             if (access(default_fstab.c_str(), F_OK) == 0) break;
719         }
720     } else {
721         LWARNING << __FUNCTION__ << "(): failed to find device hardware name";
722     }
723 
724     // combines fstab entries passed in from device tree with
725     // the ones found from default_fstab file
726     struct fstab *fstab_dt = fs_mgr_read_fstab_dt();
727     struct fstab *fstab = fs_mgr_read_fstab(default_fstab.c_str());
728 
729     return in_place_merge(fstab_dt, fstab);
730 }
731 
fs_mgr_free_fstab(struct fstab * fstab)732 void fs_mgr_free_fstab(struct fstab *fstab)
733 {
734     int i;
735 
736     if (!fstab) {
737         return;
738     }
739 
740     for (i = 0; i < fstab->num_entries; i++) {
741         /* Free the pointers return by strdup(3) */
742         free(fstab->recs[i].blk_device);
743         free(fstab->recs[i].mount_point);
744         free(fstab->recs[i].fs_type);
745         free(fstab->recs[i].fs_options);
746         free(fstab->recs[i].key_loc);
747         free(fstab->recs[i].key_dir);
748         free(fstab->recs[i].label);
749     }
750 
751     /* Free the fstab_recs array created by calloc(3) */
752     free(fstab->recs);
753 
754     /* Free the fstab filename */
755     free(fstab->fstab_filename);
756 
757     /* Free fstab */
758     free(fstab);
759 }
760 
761 /* 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)762 int fs_mgr_add_entry(struct fstab *fstab,
763                      const char *mount_point, const char *fs_type,
764                      const char *blk_device)
765 {
766     struct fstab_rec *new_fstab_recs;
767     int n = fstab->num_entries;
768 
769     new_fstab_recs = (struct fstab_rec *)
770                      realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
771 
772     if (!new_fstab_recs) {
773         return -1;
774     }
775 
776     /* A new entry was added, so initialize it */
777      memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
778      new_fstab_recs[n].mount_point = strdup(mount_point);
779      new_fstab_recs[n].fs_type = strdup(fs_type);
780      new_fstab_recs[n].blk_device = strdup(blk_device);
781      new_fstab_recs[n].length = 0;
782 
783      /* Update the fstab struct */
784      fstab->recs = new_fstab_recs;
785      fstab->num_entries++;
786 
787      return 0;
788 }
789 
790 /*
791  * Returns the 1st matching fstab_rec that follows the start_rec.
792  * start_rec is the result of a previous search or NULL.
793  */
fs_mgr_get_entry_for_mount_point_after(struct fstab_rec * start_rec,struct fstab * fstab,const char * path)794 struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path)
795 {
796     int i;
797     if (!fstab) {
798         return NULL;
799     }
800 
801     if (start_rec) {
802         for (i = 0; i < fstab->num_entries; i++) {
803             if (&fstab->recs[i] == start_rec) {
804                 i++;
805                 break;
806             }
807         }
808     } else {
809         i = 0;
810     }
811     for (; i < fstab->num_entries; i++) {
812         int len = strlen(fstab->recs[i].mount_point);
813         if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
814             (path[len] == '\0' || path[len] == '/')) {
815             return &fstab->recs[i];
816         }
817     }
818     return NULL;
819 }
820 
821 /*
822  * Returns the 1st matching mount point.
823  * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
824  * and give the fstab_rec from the previous search.
825  */
fs_mgr_get_entry_for_mount_point(struct fstab * fstab,const char * path)826 struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
827 {
828     return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
829 }
830 
fs_mgr_is_voldmanaged(const struct fstab_rec * fstab)831 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
832 {
833     return fstab->fs_mgr_flags & MF_VOLDMANAGED;
834 }
835 
fs_mgr_is_nonremovable(const struct fstab_rec * fstab)836 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
837 {
838     return fstab->fs_mgr_flags & MF_NONREMOVABLE;
839 }
840 
fs_mgr_is_verified(const struct fstab_rec * fstab)841 int fs_mgr_is_verified(const struct fstab_rec *fstab)
842 {
843     return fstab->fs_mgr_flags & MF_VERIFY;
844 }
845 
fs_mgr_is_avb(const struct fstab_rec * fstab)846 int fs_mgr_is_avb(const struct fstab_rec *fstab)
847 {
848     return fstab->fs_mgr_flags & MF_AVB;
849 }
850 
fs_mgr_is_verifyatboot(const struct fstab_rec * fstab)851 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
852 {
853     return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
854 }
855 
fs_mgr_is_encryptable(const struct fstab_rec * fstab)856 int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
857 {
858     return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
859 }
860 
fs_mgr_is_file_encrypted(const struct fstab_rec * fstab)861 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
862 {
863     return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
864 }
865 
fs_mgr_get_file_encryption_modes(const struct fstab_rec * fstab,const char ** contents_mode_ret,const char ** filenames_mode_ret)866 void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
867                                       const char **contents_mode_ret,
868                                       const char **filenames_mode_ret)
869 {
870     *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes,
871                                                  fstab->file_contents_mode);
872     *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes,
873                                                   fstab->file_names_mode);
874 }
875 
fs_mgr_is_convertible_to_fbe(const struct fstab_rec * fstab)876 int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
877 {
878     return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
879 }
880 
fs_mgr_is_noemulatedsd(const struct fstab_rec * fstab)881 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
882 {
883     return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
884 }
885 
fs_mgr_is_notrim(const struct fstab_rec * fstab)886 int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
887     return fstab->fs_mgr_flags & MF_NOTRIM;
888 }
889 
fs_mgr_is_formattable(const struct fstab_rec * fstab)890 int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
891     return fstab->fs_mgr_flags & (MF_FORMATTABLE);
892 }
893 
fs_mgr_is_slotselect(const struct fstab_rec * fstab)894 int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
895     return fstab->fs_mgr_flags & MF_SLOTSELECT;
896 }
897 
fs_mgr_is_nofail(const struct fstab_rec * fstab)898 int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
899     return fstab->fs_mgr_flags & MF_NOFAIL;
900 }
901 
fs_mgr_is_latemount(const struct fstab_rec * fstab)902 int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
903     return fstab->fs_mgr_flags & MF_LATEMOUNT;
904 }
905 
fs_mgr_is_quota(const struct fstab_rec * fstab)906 int fs_mgr_is_quota(const struct fstab_rec* fstab) {
907     return fstab->fs_mgr_flags & MF_QUOTA;
908 }
909