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, ¶ms.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, ¶ms.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, ¶ms.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, ¶ms, 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, ¶ms, 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, ¶ms, 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, ¶ms,
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