• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 <fcntl.h>
20 #include <inttypes.h>
21 #include <libgen.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/mount.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <time.h>
30 #include <unistd.h>
31 
32 #include <android-base/file.h>
33 #include <android-base/properties.h>
34 #include <android-base/strings.h>
35 #include <android-base/unique_fd.h>
36 #include <crypto_utils/android_pubkey.h>
37 #include <cutils/properties.h>
38 #include <libdm/dm.h>
39 #include <logwrap/logwrap.h>
40 #include <openssl/obj_mac.h>
41 #include <openssl/rsa.h>
42 #include <openssl/sha.h>
43 
44 #include "fec/io.h"
45 
46 #include "fs_mgr.h"
47 #include "fs_mgr_dm_linear.h"
48 #include "fs_mgr_priv.h"
49 
50 // Realistically, this file should be part of the android::fs_mgr namespace;
51 using namespace android::fs_mgr;
52 
53 #define VERITY_TABLE_RSA_KEY "/verity_key"
54 #define VERITY_TABLE_HASH_IDX 8
55 #define VERITY_TABLE_SALT_IDX 9
56 
57 #define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
58 #define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
59 #define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
60 
61 #define VERITY_TABLE_OPT_FEC_FORMAT \
62     "use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 \
63     " fec_roots %u " VERITY_TABLE_OPT_IGNZERO
64 #define VERITY_TABLE_OPT_FEC_ARGS 9
65 
66 #define METADATA_MAGIC 0x01564c54
67 #define METADATA_TAG_MAX_LENGTH 63
68 #define METADATA_EOD "eod"
69 
70 #define VERITY_LASTSIG_TAG "verity_lastsig"
71 
72 #define VERITY_STATE_TAG "verity_state"
73 #define VERITY_STATE_HEADER 0x83c0ae9d
74 #define VERITY_STATE_VERSION 1
75 
76 #define VERITY_KMSG_RESTART "dm-verity device corrupted"
77 #define VERITY_KMSG_BUFSIZE 1024
78 
79 #define READ_BUF_SIZE 4096
80 
81 #define __STRINGIFY(x) #x
82 #define STRINGIFY(x) __STRINGIFY(x)
83 
84 struct verity_state {
85     uint32_t header;
86     uint32_t version;
87     int32_t mode;
88 };
89 
90 extern struct fs_info info;
91 
load_key(const char * path)92 static RSA *load_key(const char *path)
93 {
94     uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
95 
96     auto f = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path, "re"), fclose};
97     if (!f) {
98         LERROR << "Can't open " << path;
99         return nullptr;
100     }
101 
102     if (!fread(key_data, sizeof(key_data), 1, f.get())) {
103         LERROR << "Could not read key!";
104         return nullptr;
105     }
106 
107     RSA* key = nullptr;
108     if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) {
109         LERROR << "Could not parse key!";
110         return nullptr;
111     }
112 
113     return key;
114 }
115 
verify_table(const uint8_t * signature,size_t signature_size,const char * table,uint32_t table_length)116 static int verify_table(const uint8_t *signature, size_t signature_size,
117         const char *table, uint32_t table_length)
118 {
119     RSA *key;
120     uint8_t hash_buf[SHA256_DIGEST_LENGTH];
121     int retval = -1;
122 
123     // Hash the table
124     SHA256((uint8_t*)table, table_length, hash_buf);
125 
126     // Now get the public key from the keyfile
127     key = load_key(VERITY_TABLE_RSA_KEY);
128     if (!key) {
129         LERROR << "Couldn't load verity keys";
130         goto out;
131     }
132 
133     // verify the result
134     if (!RSA_verify(NID_sha256, hash_buf, sizeof(hash_buf), signature,
135                     signature_size, key)) {
136         LERROR << "Couldn't verify table";
137         goto out;
138     }
139 
140     retval = 0;
141 
142 out:
143     RSA_free(key);
144     return retval;
145 }
146 
verify_verity_signature(const struct fec_verity_metadata & verity)147 static int verify_verity_signature(const struct fec_verity_metadata& verity)
148 {
149     if (verify_table(verity.signature, sizeof(verity.signature),
150             verity.table, verity.table_length) == 0 ||
151         verify_table(verity.ecc_signature, sizeof(verity.ecc_signature),
152             verity.table, verity.table_length) == 0) {
153         return 0;
154     }
155 
156     return -1;
157 }
158 
invalidate_table(char * table,size_t table_length)159 static int invalidate_table(char *table, size_t table_length)
160 {
161     size_t n = 0;
162     size_t idx = 0;
163     size_t cleared = 0;
164 
165     while (n < table_length) {
166         if (table[n++] == ' ') {
167             ++idx;
168         }
169 
170         if (idx != VERITY_TABLE_HASH_IDX && idx != VERITY_TABLE_SALT_IDX) {
171             continue;
172         }
173 
174         while (n < table_length && table[n] != ' ') {
175             table[n++] = '0';
176         }
177 
178         if (++cleared == 2) {
179             return 0;
180         }
181     }
182 
183     return -1;
184 }
185 
186 struct verity_table_params {
187     char *table;
188     int mode;
189     struct fec_ecc_metadata ecc;
190     const char *ecc_dev;
191 };
192 
193 typedef bool (*format_verity_table_func)(char *buf, const size_t bufsize,
194         const struct verity_table_params *params);
195 
format_verity_table(char * buf,const size_t bufsize,const struct verity_table_params * params)196 static bool format_verity_table(char *buf, const size_t bufsize,
197         const struct verity_table_params *params)
198 {
199     const char *mode_flag = NULL;
200     int res = -1;
201 
202     if (params->mode == VERITY_MODE_RESTART) {
203         mode_flag = VERITY_TABLE_OPT_RESTART;
204     } else if (params->mode == VERITY_MODE_LOGGING) {
205         mode_flag = VERITY_TABLE_OPT_LOGGING;
206     }
207 
208     if (params->ecc.valid) {
209         if (mode_flag) {
210             res = snprintf(buf, bufsize,
211                     "%s %u %s " VERITY_TABLE_OPT_FEC_FORMAT,
212                     params->table, 1 + VERITY_TABLE_OPT_FEC_ARGS, mode_flag, params->ecc_dev,
213                     params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
214         } else {
215             res = snprintf(buf, bufsize,
216                     "%s %u " VERITY_TABLE_OPT_FEC_FORMAT,
217                     params->table, VERITY_TABLE_OPT_FEC_ARGS, params->ecc_dev,
218                     params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
219         }
220     } else if (mode_flag) {
221         res = snprintf(buf, bufsize, "%s 2 " VERITY_TABLE_OPT_IGNZERO " %s", params->table,
222                     mode_flag);
223     } else {
224         res = snprintf(buf, bufsize, "%s 1 " VERITY_TABLE_OPT_IGNZERO, params->table);
225     }
226 
227     if (res < 0 || (size_t)res >= bufsize) {
228         LERROR << "Error building verity table; insufficient buffer size?";
229         return false;
230     }
231 
232     return true;
233 }
234 
format_legacy_verity_table(char * buf,const size_t bufsize,const struct verity_table_params * params)235 static bool format_legacy_verity_table(char *buf, const size_t bufsize,
236         const struct verity_table_params *params)
237 {
238     int res;
239 
240     if (params->mode == VERITY_MODE_EIO) {
241         res = strlcpy(buf, params->table, bufsize);
242     } else {
243         res = snprintf(buf, bufsize, "%s %d", params->table, params->mode);
244     }
245 
246     if (res < 0 || (size_t)res >= bufsize) {
247         LERROR << "Error building verity table; insufficient buffer size?";
248         return false;
249     }
250 
251     return true;
252 }
253 
load_verity_table(android::dm::DeviceMapper & dm,const std::string & name,uint64_t device_size,const struct verity_table_params * params,format_verity_table_func format)254 static int load_verity_table(android::dm::DeviceMapper& dm, const std::string& name,
255                              uint64_t device_size, const struct verity_table_params* params,
256                              format_verity_table_func format) {
257     android::dm::DmTable table;
258     table.set_readonly(true);
259 
260     char buffer[DM_BUF_SIZE];
261     if (!format(buffer, sizeof(buffer), params)) {
262         LERROR << "Failed to format verity parameters";
263         return -1;
264     }
265 
266     android::dm::DmTargetVerityString target(0, device_size / 512, buffer);
267     if (!table.AddTarget(std::make_unique<decltype(target)>(target))) {
268         LERROR << "Failed to add verity target";
269         return -1;
270     }
271     if (!dm.CreateDevice(name, table)) {
272         LERROR << "Failed to create verity device \"" << name << "\"";
273         return -1;
274     }
275     return 0;
276 }
277 
check_verity_restart(const char * fname)278 static int check_verity_restart(const char *fname)
279 {
280     char buffer[VERITY_KMSG_BUFSIZE + 1];
281     int fd;
282     int rc = 0;
283     ssize_t size;
284     struct stat s;
285 
286     fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
287 
288     if (fd == -1) {
289         if (errno != ENOENT) {
290             PERROR << "Failed to open " << fname;
291         }
292         goto out;
293     }
294 
295     if (fstat(fd, &s) == -1) {
296         PERROR << "Failed to fstat " << fname;
297         goto out;
298     }
299 
300     size = VERITY_KMSG_BUFSIZE;
301 
302     if (size > s.st_size) {
303         size = s.st_size;
304     }
305 
306     if (lseek(fd, s.st_size - size, SEEK_SET) == -1) {
307         PERROR << "Failed to lseek " << (intmax_t)(s.st_size - size) << " " << fname;
308         goto out;
309     }
310 
311     if (!android::base::ReadFully(fd, buffer, size)) {
312         PERROR << "Failed to read " << size << " bytes from " << fname;
313         goto out;
314     }
315 
316     buffer[size] = '\0';
317 
318     if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) {
319         rc = 1;
320     }
321 
322 out:
323     if (fd != -1) {
324         close(fd);
325     }
326 
327     return rc;
328 }
329 
was_verity_restart()330 static int was_verity_restart()
331 {
332     static const char* files[] = {
333         // clang-format off
334         "/sys/fs/pstore/console-ramoops-0",
335         "/sys/fs/pstore/console-ramoops",
336         "/proc/last_kmsg",
337         NULL
338         // clang-format on
339     };
340     int i;
341 
342     for (i = 0; files[i]; ++i) {
343         if (check_verity_restart(files[i])) {
344             return 1;
345         }
346     }
347 
348     return 0;
349 }
350 
metadata_add(FILE * fp,long start,const char * tag,unsigned int length,off64_t * offset)351 static int metadata_add(FILE *fp, long start, const char *tag,
352         unsigned int length, off64_t *offset)
353 {
354     if (fseek(fp, start, SEEK_SET) < 0 ||
355         fprintf(fp, "%s %u\n", tag, length) < 0) {
356         return -1;
357     }
358 
359     *offset = ftell(fp);
360 
361     if (fseek(fp, length, SEEK_CUR) < 0 ||
362         fprintf(fp, METADATA_EOD " 0\n") < 0) {
363         return -1;
364     }
365 
366     return 0;
367 }
368 
metadata_find(const char * fname,const char * stag,unsigned int slength,off64_t * offset)369 static int metadata_find(const char *fname, const char *stag,
370         unsigned int slength, off64_t *offset)
371 {
372     char tag[METADATA_TAG_MAX_LENGTH + 1];
373     int rc = -1;
374     int n;
375     long start = 0x4000; /* skip cryptfs metadata area */
376     uint32_t magic;
377     unsigned int length = 0;
378 
379     if (!fname) {
380         return -1;
381     }
382 
383     auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fname, "re+"), fclose};
384 
385     if (!fp) {
386         PERROR << "Failed to open " << fname;
387         return -1;
388     }
389 
390     /* check magic */
391     if (fseek(fp.get(), start, SEEK_SET) < 0 || fread(&magic, sizeof(magic), 1, fp.get()) != 1) {
392         PERROR << "Failed to read magic from " << fname;
393         return -1;
394     }
395 
396     if (magic != METADATA_MAGIC) {
397         magic = METADATA_MAGIC;
398 
399         if (fseek(fp.get(), start, SEEK_SET) < 0 ||
400             fwrite(&magic, sizeof(magic), 1, fp.get()) != 1) {
401             PERROR << "Failed to write magic to " << fname;
402             return -1;
403         }
404 
405         rc = metadata_add(fp.get(), start + sizeof(magic), stag, slength, offset);
406         if (rc < 0) {
407             PERROR << "Failed to add metadata to " << fname;
408         }
409 
410         return rc;
411     }
412 
413     start += sizeof(magic);
414 
415     while (1) {
416         n = fscanf(fp.get(), "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", tag, &length);
417 
418         if (n == 2 && strcmp(tag, METADATA_EOD)) {
419             /* found a tag */
420             start = ftell(fp.get());
421 
422             if (!strcmp(tag, stag) && length == slength) {
423                 *offset = start;
424                 return 0;
425             }
426 
427             start += length;
428 
429             if (fseek(fp.get(), length, SEEK_CUR) < 0) {
430                 PERROR << "Failed to seek " << fname;
431                 return -1;
432             }
433         } else {
434             rc = metadata_add(fp.get(), start, stag, slength, offset);
435             if (rc < 0) {
436                 PERROR << "Failed to write metadata to " << fname;
437             }
438             return rc;
439         }
440     }
441 }
442 
write_verity_state(const char * fname,off64_t offset,int32_t mode)443 static int write_verity_state(const char *fname, off64_t offset, int32_t mode)
444 {
445     int fd;
446     int rc = -1;
447     struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode };
448 
449     fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC));
450 
451     if (fd == -1) {
452         PERROR << "Failed to open " << fname;
453         goto out;
454     }
455 
456     if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
457         PERROR << "Failed to write " << sizeof(s) << " bytes to " << fname
458                << " to offset " << offset;
459         goto out;
460     }
461 
462     rc = 0;
463 
464 out:
465     if (fd != -1) {
466         close(fd);
467     }
468 
469     return rc;
470 }
471 
read_verity_state(const char * fname,off64_t offset,int * mode)472 static int read_verity_state(const char *fname, off64_t offset, int *mode)
473 {
474     int fd = -1;
475     int rc = -1;
476     struct verity_state s;
477 
478     fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
479 
480     if (fd == -1) {
481         PERROR << "Failed to open " << fname;
482         goto out;
483     }
484 
485     if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
486         PERROR << "Failed to read " <<  sizeof(s) << " bytes from " << fname
487                << " offset " << offset;
488         goto out;
489     }
490 
491     if (s.header != VERITY_STATE_HEADER) {
492         /* space allocated, but no state written. write default state */
493         *mode = VERITY_MODE_DEFAULT;
494         rc = write_verity_state(fname, offset, *mode);
495         goto out;
496     }
497 
498     if (s.version != VERITY_STATE_VERSION) {
499         LERROR << "Unsupported verity state version (" << s.version << ")";
500         goto out;
501     }
502 
503     if (s.mode < VERITY_MODE_EIO ||
504         s.mode > VERITY_MODE_LAST) {
505         LERROR << "Unsupported verity mode (" << s.mode << ")";
506         goto out;
507     }
508 
509     *mode = s.mode;
510     rc = 0;
511 
512 out:
513     if (fd != -1) {
514         close(fd);
515     }
516 
517     return rc;
518 }
519 
read_partition(const char * path,uint64_t size)520 static int read_partition(const char *path, uint64_t size)
521 {
522     char buf[READ_BUF_SIZE];
523     ssize_t size_read;
524     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
525 
526     if (fd == -1) {
527         PERROR << "Failed to open " << path;
528         return -errno;
529     }
530 
531     while (size) {
532         size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
533         if (size_read == -1) {
534             PERROR << "Error in reading partition " << path;
535             return -errno;
536         }
537         size -= size_read;
538     }
539 
540     return 0;
541 }
542 
compare_last_signature(const FstabEntry & entry,int * match)543 static int compare_last_signature(const FstabEntry& entry, int* match) {
544     char tag[METADATA_TAG_MAX_LENGTH + 1];
545     int fd = -1;
546     int rc = -1;
547     off64_t offset = 0;
548     struct fec_handle *f = NULL;
549     struct fec_verity_metadata verity;
550     uint8_t curr[SHA256_DIGEST_LENGTH];
551     uint8_t prev[SHA256_DIGEST_LENGTH];
552 
553     *match = 1;
554 
555     if (fec_open(&f, entry.blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) ==
556         -1) {
557         PERROR << "Failed to open '" << entry.blk_device << "'";
558         return rc;
559     }
560 
561     // read verity metadata
562     if (fec_verity_get_metadata(f, &verity) == -1) {
563         PERROR << "Failed to get verity metadata '" << entry.blk_device << "'";
564         goto out;
565     }
566 
567     SHA256(verity.signature, sizeof(verity.signature), curr);
568 
569     if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s", basename(entry.mount_point.c_str())) >=
570         (int)sizeof(tag)) {
571         LERROR << "Metadata tag name too long for " << entry.mount_point;
572         goto out;
573     }
574 
575     if (metadata_find(entry.verity_loc.c_str(), tag, SHA256_DIGEST_LENGTH, &offset) < 0) {
576         goto out;
577     }
578 
579     fd = TEMP_FAILURE_RETRY(open(entry.verity_loc.c_str(), O_RDWR | O_SYNC | O_CLOEXEC));
580 
581     if (fd == -1) {
582         PERROR << "Failed to open " << entry.verity_loc;
583         goto out;
584     }
585 
586     if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev), offset)) != sizeof(prev)) {
587         PERROR << "Failed to read " << sizeof(prev) << " bytes from " << entry.verity_loc
588                << " offset " << offset;
589         goto out;
590     }
591 
592     *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH);
593 
594     if (!*match) {
595         /* update current signature hash */
596         if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
597                 offset)) != sizeof(curr)) {
598             PERROR << "Failed to write " << sizeof(curr) << " bytes to " << entry.verity_loc
599                    << " offset " << offset;
600             goto out;
601         }
602     }
603 
604     rc = 0;
605 
606 out:
607     fec_close(f);
608     return rc;
609 }
610 
get_verity_state_offset(const FstabEntry & entry,off64_t * offset)611 static int get_verity_state_offset(const FstabEntry& entry, off64_t* offset) {
612     char tag[METADATA_TAG_MAX_LENGTH + 1];
613 
614     if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s", basename(entry.mount_point.c_str())) >=
615         (int)sizeof(tag)) {
616         LERROR << "Metadata tag name too long for " << entry.mount_point;
617         return -1;
618     }
619 
620     return metadata_find(entry.verity_loc.c_str(), tag, sizeof(struct verity_state), offset);
621 }
622 
load_verity_state(const FstabEntry & entry,int * mode)623 int load_verity_state(const FstabEntry& entry, int* mode) {
624     // unless otherwise specified, use EIO mode.
625     *mode = VERITY_MODE_EIO;
626 
627     // use the kernel parameter if set.
628     std::string veritymode;
629     if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
630         if (veritymode == "enforcing") {
631             *mode = VERITY_MODE_DEFAULT;
632         }
633         return 0;
634     }
635 
636     off64_t offset = 0;
637     if (get_verity_state_offset(entry, &offset) < 0) {
638         /* fall back to stateless behavior */
639         return 0;
640     }
641 
642     if (was_verity_restart()) {
643         /* device was restarted after dm-verity detected a corrupted
644          * block, so use EIO mode */
645         return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
646     }
647 
648     int match = 0;
649     if (!compare_last_signature(entry, &match) && !match) {
650         /* partition has been reflashed, reset dm-verity state */
651         *mode = VERITY_MODE_DEFAULT;
652         return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
653     }
654 
655     return read_verity_state(entry.verity_loc.c_str(), offset, mode);
656 }
657 
658 // Update the verity table using the actual block device path.
659 // Two cases:
660 // Case-1: verity table is shared for devices with different by-name prefix.
661 // Example:
662 //   verity table token:       /dev/block/bootdevice/by-name/vendor
663 //   blk_device-1 (non-A/B):   /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor
664 //   blk_device-2 (A/B):       /dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor_a
665 //
666 // Case-2: append A/B suffix in the verity table.
667 // Example:
668 //   verity table token: /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor
669 //   blk_device:         /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor_a
update_verity_table_blk_device(const std::string & blk_device,char ** table,bool slot_select)670 static void update_verity_table_blk_device(const std::string& blk_device, char** table,
671                                            bool slot_select) {
672     bool updated = false;
673     std::string result, ab_suffix;
674     auto tokens = android::base::Split(*table, " ");
675 
676     // If slot_select is set, it means blk_device is already updated with ab_suffix.
677     if (slot_select) ab_suffix = fs_mgr_get_slot_suffix();
678 
679     for (const auto& token : tokens) {
680         std::string new_token;
681         if (android::base::StartsWith(token, "/dev/block/")) {
682             if (token == blk_device) return;  // no need to update if they're already the same.
683             std::size_t found1 = blk_device.find("by-name");
684             std::size_t found2 = token.find("by-name");
685             if (found1 != std::string::npos && found2 != std::string::npos &&
686                 blk_device.substr(found1) == token.substr(found2) + ab_suffix) {
687                 new_token = blk_device;
688             }
689         }
690 
691         if (!new_token.empty()) {
692             updated = true;
693             LINFO << "Verity table: updated block device from '" << token << "' to '" << new_token
694                   << "'";
695         } else {
696             new_token = token;
697         }
698 
699         if (result.empty()) {
700             result = new_token;
701         } else {
702             result += " " + new_token;
703         }
704     }
705 
706     if (!updated) {
707         return;
708     }
709 
710     free(*table);
711     *table = strdup(result.c_str());
712 }
713 
714 // prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
715 // mount. The 'wait_for_verity_dev' parameter makes this function wait for the
716 // verity device to get created before return
fs_mgr_setup_verity(FstabEntry * entry,bool wait_for_verity_dev)717 int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) {
718     int retval = FS_MGR_SETUP_VERITY_FAIL;
719     int fd = -1;
720     std::string verity_blk_name;
721     struct fec_handle *f = NULL;
722     struct fec_verity_metadata verity;
723     struct verity_table_params params = { .table = NULL };
724 
725     const std::string mount_point(basename(entry->mount_point.c_str()));
726     bool verified_at_boot = false;
727 
728     android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
729 
730     if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) <
731         0) {
732         PERROR << "Failed to open '" << entry->blk_device << "'";
733         return retval;
734     }
735 
736     // read verity metadata
737     if (fec_verity_get_metadata(f, &verity) < 0) {
738         PERROR << "Failed to get verity metadata '" << entry->blk_device << "'";
739         // Allow verity disabled when the device is unlocked without metadata
740         if (fs_mgr_is_device_unlocked()) {
741             retval = FS_MGR_SETUP_VERITY_SKIPPED;
742             LWARNING << "Allow invalid metadata when the device is unlocked";
743         }
744         goto out;
745     }
746 
747 #ifdef ALLOW_ADBD_DISABLE_VERITY
748     if (verity.disabled) {
749         retval = FS_MGR_SETUP_VERITY_DISABLED;
750         LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG/ENG";
751         goto out;
752     }
753 #endif
754 
755     // read ecc metadata
756     if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
757         params.ecc.valid = false;
758     }
759 
760     params.ecc_dev = entry->blk_device.c_str();
761 
762     if (load_verity_state(*entry, &params.mode) < 0) {
763         /* if accessing or updating the state failed, switch to the default
764          * safe mode. This makes sure the device won't end up in an endless
765          * restart loop, and no corrupted data will be exposed to userspace
766          * without a warning. */
767         params.mode = VERITY_MODE_EIO;
768     }
769 
770     if (!verity.table) {
771         goto out;
772     }
773 
774     params.table = strdup(verity.table);
775     if (!params.table) {
776         goto out;
777     }
778 
779     // verify the signature on the table
780     if (verify_verity_signature(verity) < 0) {
781         // Allow signature verification error when the device is unlocked
782         if (fs_mgr_is_device_unlocked()) {
783             retval = FS_MGR_SETUP_VERITY_SKIPPED;
784             LWARNING << "Allow signature verification error when the device is unlocked";
785             goto out;
786         }
787         if (params.mode == VERITY_MODE_LOGGING) {
788             // the user has been warned, allow mounting without dm-verity
789             retval = FS_MGR_SETUP_VERITY_SKIPPED;
790             goto out;
791         }
792 
793         // invalidate root hash and salt to trigger device-specific recovery
794         if (invalidate_table(params.table, verity.table_length) < 0) {
795             goto out;
796         }
797     }
798 
799     LINFO << "Enabling dm-verity for " << mount_point.c_str()
800           << " (mode " << params.mode << ")";
801 
802     // Update the verity params using the actual block device path
803     update_verity_table_blk_device(entry->blk_device, &params.table,
804                                    entry->fs_mgr_flags.slot_select);
805 
806     // load the verity mapping table
807     if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
808         goto loaded;
809     }
810 
811     if (params.ecc.valid) {
812         // kernel may not support error correction, try without
813         LINFO << "Disabling error correction for " << mount_point.c_str();
814         params.ecc.valid = false;
815 
816         if (load_verity_table(dm, mount_point, verity.data_size, &params, format_verity_table) == 0) {
817             goto loaded;
818         }
819     }
820 
821     // try the legacy format for backwards compatibility
822     if (load_verity_table(dm, mount_point, verity.data_size, &params, format_legacy_verity_table) ==
823         0) {
824         goto loaded;
825     }
826 
827     if (params.mode != VERITY_MODE_EIO) {
828         // as a last resort, EIO mode should always be supported
829         LINFO << "Falling back to EIO mode for " << mount_point.c_str();
830         params.mode = VERITY_MODE_EIO;
831 
832         if (load_verity_table(dm, mount_point, verity.data_size, &params,
833                               format_legacy_verity_table) == 0) {
834             goto loaded;
835         }
836     }
837 
838     LERROR << "Failed to load verity table for " << mount_point.c_str();
839     goto out;
840 
841 loaded:
842     if (!dm.GetDmDevicePathByName(mount_point, &verity_blk_name)) {
843         LERROR << "Couldn't get verity device number!";
844         goto out;
845     }
846 
847     // mark the underlying block device as read-only
848     fs_mgr_set_blk_ro(entry->blk_device);
849 
850     // Verify the entire partition in one go
851     // If there is an error, allow it to mount as a normal verity partition.
852     if (entry->fs_mgr_flags.verify_at_boot) {
853         LINFO << "Verifying partition " << entry->blk_device << " at boot";
854         int err = read_partition(verity_blk_name.c_str(), verity.data_size);
855         if (!err) {
856             LINFO << "Verified verity partition " << entry->blk_device << " at boot";
857             verified_at_boot = true;
858         }
859     }
860 
861     // assign the new verity block device as the block device
862     if (!verified_at_boot) {
863         entry->blk_device = verity_blk_name;
864     } else if (!dm.DeleteDevice(mount_point)) {
865         LERROR << "Failed to remove verity device " << mount_point.c_str();
866         goto out;
867     }
868 
869     // make sure we've set everything up properly
870     if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) {
871         goto out;
872     }
873 
874     retval = FS_MGR_SETUP_VERITY_SUCCESS;
875 
876 out:
877     if (fd != -1) {
878         close(fd);
879     }
880 
881     fec_close(f);
882     free(params.table);
883 
884     return retval;
885 }
886 
fs_mgr_teardown_verity(FstabEntry * entry,bool wait)887 bool fs_mgr_teardown_verity(FstabEntry* entry, bool wait) {
888     const std::string mount_point(basename(entry->mount_point.c_str()));
889     if (!android::fs_mgr::UnmapDevice(mount_point, wait ? 1000ms : 0ms)) {
890         return false;
891     }
892     LINFO << "Unmapped verity device " << mount_point;
893     return true;
894 }
895