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