fs_mgr_verity.cpp revision 7ad3159db9be8fcb7246fbb750884f5a9edf368f
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#include <private/android_filesystem_config.h>
43
44#include "fec/io.h"
45
46#include "fs_mgr.h"
47#include "fs_mgr_priv.h"
48#include "fs_mgr_priv_dm_ioctl.h"
49
50#define VERITY_TABLE_RSA_KEY "/verity_key"
51#define VERITY_TABLE_HASH_IDX 8
52#define VERITY_TABLE_SALT_IDX 9
53
54#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
55#define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
56#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
57
58#define VERITY_TABLE_OPT_FEC_FORMAT \
59    "use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 \
60    " fec_roots %u " VERITY_TABLE_OPT_IGNZERO
61#define VERITY_TABLE_OPT_FEC_ARGS 9
62
63#define METADATA_MAGIC 0x01564c54
64#define METADATA_TAG_MAX_LENGTH 63
65#define METADATA_EOD "eod"
66
67#define VERITY_LASTSIG_TAG "verity_lastsig"
68
69#define VERITY_STATE_TAG "verity_state"
70#define VERITY_STATE_HEADER 0x83c0ae9d
71#define VERITY_STATE_VERSION 1
72
73#define VERITY_KMSG_RESTART "dm-verity device corrupted"
74#define VERITY_KMSG_BUFSIZE 1024
75
76#define READ_BUF_SIZE 4096
77
78#define __STRINGIFY(x) #x
79#define STRINGIFY(x) __STRINGIFY(x)
80
81struct verity_state {
82    uint32_t header;
83    uint32_t version;
84    int32_t mode;
85};
86
87extern struct fs_info info;
88
89static RSA *load_key(const char *path)
90{
91    uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
92
93    FILE* f = fopen(path, "r");
94    if (!f) {
95        LERROR << "Can't open " << path;
96        return NULL;
97    }
98
99    if (!fread(key_data, sizeof(key_data), 1, f)) {
100        LERROR << "Could not read key!";
101        fclose(f);
102        return NULL;
103    }
104
105    fclose(f);
106
107    RSA* key = NULL;
108    if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) {
109        LERROR << "Could not parse key!";
110        return NULL;
111    }
112
113    return key;
114}
115
116static 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
142out:
143    RSA_free(key);
144    return retval;
145}
146
147static 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
159static 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
186struct verity_table_params {
187    char *table;
188    int mode;
189    struct fec_ecc_metadata ecc;
190    const char *ecc_dev;
191};
192
193typedef bool (*format_verity_table_func)(char *buf, const size_t bufsize,
194        const struct verity_table_params *params);
195
196static 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
235static 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
254static int load_verity_table(struct dm_ioctl *io, const std::string &name,
255                             uint64_t device_size, int fd,
256        const struct verity_table_params *params, format_verity_table_func format)
257{
258    char *verity_params;
259    char *buffer = (char*) io;
260    size_t bufsize;
261
262    fs_mgr_verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
263
264    struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
265
266    // set tgt arguments
267    io->target_count = 1;
268    tgt->status = 0;
269    tgt->sector_start = 0;
270    tgt->length = device_size / 512;
271    strcpy(tgt->target_type, "verity");
272
273    // build the verity params
274    verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
275    bufsize = DM_BUF_SIZE - (verity_params - buffer);
276
277    if (!format(verity_params, bufsize, params)) {
278        LERROR << "Failed to format verity parameters";
279        return -1;
280    }
281
282    LINFO << "loading verity table: '" << verity_params << "'";
283
284    // set next target boundary
285    verity_params += strlen(verity_params) + 1;
286    verity_params = (char*)(((uintptr_t)verity_params + 7) & ~7);
287    tgt->next = verity_params - buffer;
288
289    // send the ioctl to load the verity table
290    if (ioctl(fd, DM_TABLE_LOAD, io)) {
291        PERROR << "Error loading verity table";
292        return -1;
293    }
294
295    return 0;
296}
297
298static int check_verity_restart(const char *fname)
299{
300    char buffer[VERITY_KMSG_BUFSIZE + 1];
301    int fd;
302    int rc = 0;
303    ssize_t size;
304    struct stat s;
305
306    fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
307
308    if (fd == -1) {
309        if (errno != ENOENT) {
310            PERROR << "Failed to open " << fname;
311        }
312        goto out;
313    }
314
315    if (fstat(fd, &s) == -1) {
316        PERROR << "Failed to fstat " << fname;
317        goto out;
318    }
319
320    size = VERITY_KMSG_BUFSIZE;
321
322    if (size > s.st_size) {
323        size = s.st_size;
324    }
325
326    if (lseek(fd, s.st_size - size, SEEK_SET) == -1) {
327        PERROR << "Failed to lseek " << (intmax_t)(s.st_size - size) << " " << fname;
328        goto out;
329    }
330
331    if (!android::base::ReadFully(fd, buffer, size)) {
332        PERROR << "Failed to read " << size << " bytes from " << fname;
333        goto out;
334    }
335
336    buffer[size] = '\0';
337
338    if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) {
339        rc = 1;
340    }
341
342out:
343    if (fd != -1) {
344        close(fd);
345    }
346
347    return rc;
348}
349
350static int was_verity_restart()
351{
352    static const char *files[] = {
353        "/sys/fs/pstore/console-ramoops",
354        "/proc/last_kmsg",
355        NULL
356    };
357    int i;
358
359    for (i = 0; files[i]; ++i) {
360        if (check_verity_restart(files[i])) {
361            return 1;
362        }
363    }
364
365    return 0;
366}
367
368static int metadata_add(FILE *fp, long start, const char *tag,
369        unsigned int length, off64_t *offset)
370{
371    if (fseek(fp, start, SEEK_SET) < 0 ||
372        fprintf(fp, "%s %u\n", tag, length) < 0) {
373        return -1;
374    }
375
376    *offset = ftell(fp);
377
378    if (fseek(fp, length, SEEK_CUR) < 0 ||
379        fprintf(fp, METADATA_EOD " 0\n") < 0) {
380        return -1;
381    }
382
383    return 0;
384}
385
386static int metadata_find(const char *fname, const char *stag,
387        unsigned int slength, off64_t *offset)
388{
389    FILE *fp = NULL;
390    char tag[METADATA_TAG_MAX_LENGTH + 1];
391    int rc = -1;
392    int n;
393    long start = 0x4000; /* skip cryptfs metadata area */
394    uint32_t magic;
395    unsigned int length = 0;
396
397    if (!fname) {
398        return -1;
399    }
400
401    fp = fopen(fname, "r+");
402
403    if (!fp) {
404        PERROR << "Failed to open " << fname;
405        goto out;
406    }
407
408    /* check magic */
409    if (fseek(fp, start, SEEK_SET) < 0 ||
410        fread(&magic, sizeof(magic), 1, fp) != 1) {
411        PERROR << "Failed to read magic from " << fname;
412        goto out;
413    }
414
415    if (magic != METADATA_MAGIC) {
416        magic = METADATA_MAGIC;
417
418        if (fseek(fp, start, SEEK_SET) < 0 ||
419            fwrite(&magic, sizeof(magic), 1, fp) != 1) {
420            PERROR << "Failed to write magic to " << fname;
421            goto out;
422        }
423
424        rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset);
425        if (rc < 0) {
426            PERROR << "Failed to add metadata to " << fname;
427        }
428
429        goto out;
430    }
431
432    start += sizeof(magic);
433
434    while (1) {
435        n = fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n",
436                tag, &length);
437
438        if (n == 2 && strcmp(tag, METADATA_EOD)) {
439            /* found a tag */
440            start = ftell(fp);
441
442            if (!strcmp(tag, stag) && length == slength) {
443                *offset = start;
444                rc = 0;
445                goto out;
446            }
447
448            start += length;
449
450            if (fseek(fp, length, SEEK_CUR) < 0) {
451                PERROR << "Failed to seek " << fname;
452                goto out;
453            }
454        } else {
455            rc = metadata_add(fp, start, stag, slength, offset);
456            if (rc < 0) {
457                PERROR << "Failed to write metadata to " << fname;
458            }
459            goto out;
460        }
461   }
462
463out:
464    if (fp) {
465        fflush(fp);
466        fclose(fp);
467    }
468
469    return rc;
470}
471
472static int write_verity_state(const char *fname, off64_t offset, int32_t mode)
473{
474    int fd;
475    int rc = -1;
476    struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode };
477
478    fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC));
479
480    if (fd == -1) {
481        PERROR << "Failed to open " << fname;
482        goto out;
483    }
484
485    if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
486        PERROR << "Failed to write " << sizeof(s) << " bytes to " << fname
487               << " to offset " << offset;
488        goto out;
489    }
490
491    rc = 0;
492
493out:
494    if (fd != -1) {
495        close(fd);
496    }
497
498    return rc;
499}
500
501static int read_verity_state(const char *fname, off64_t offset, int *mode)
502{
503    int fd = -1;
504    int rc = -1;
505    struct verity_state s;
506
507    fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
508
509    if (fd == -1) {
510        PERROR << "Failed to open " << fname;
511        goto out;
512    }
513
514    if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
515        PERROR << "Failed to read " <<  sizeof(s) << " bytes from " << fname
516               << " offset " << offset;
517        goto out;
518    }
519
520    if (s.header != VERITY_STATE_HEADER) {
521        /* space allocated, but no state written. write default state */
522        *mode = VERITY_MODE_DEFAULT;
523        rc = write_verity_state(fname, offset, *mode);
524        goto out;
525    }
526
527    if (s.version != VERITY_STATE_VERSION) {
528        LERROR << "Unsupported verity state version (" << s.version << ")";
529        goto out;
530    }
531
532    if (s.mode < VERITY_MODE_EIO ||
533        s.mode > VERITY_MODE_LAST) {
534        LERROR << "Unsupported verity mode (" << s.mode << ")";
535        goto out;
536    }
537
538    *mode = s.mode;
539    rc = 0;
540
541out:
542    if (fd != -1) {
543        close(fd);
544    }
545
546    return rc;
547}
548
549static int read_partition(const char *path, uint64_t size)
550{
551    char buf[READ_BUF_SIZE];
552    ssize_t size_read;
553    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
554
555    if (fd == -1) {
556        PERROR << "Failed to open " << path;
557        return -errno;
558    }
559
560    while (size) {
561        size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
562        if (size_read == -1) {
563            PERROR << "Error in reading partition " << path;
564            return -errno;
565        }
566        size -= size_read;
567    }
568
569    return 0;
570}
571
572static int compare_last_signature(struct fstab_rec *fstab, int *match)
573{
574    char tag[METADATA_TAG_MAX_LENGTH + 1];
575    int fd = -1;
576    int rc = -1;
577    off64_t offset = 0;
578    struct fec_handle *f = NULL;
579    struct fec_verity_metadata verity;
580    uint8_t curr[SHA256_DIGEST_LENGTH];
581    uint8_t prev[SHA256_DIGEST_LENGTH];
582
583    *match = 1;
584
585    if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
586            FEC_DEFAULT_ROOTS) == -1) {
587        PERROR << "Failed to open '" << fstab->blk_device << "'";
588        return rc;
589    }
590
591    // read verity metadata
592    if (fec_verity_get_metadata(f, &verity) == -1) {
593        PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
594        goto out;
595    }
596
597    SHA256(verity.signature, sizeof(verity.signature), curr);
598
599    if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s",
600            basename(fstab->mount_point)) >= (int)sizeof(tag)) {
601        LERROR << "Metadata tag name too long for " << fstab->mount_point;
602        goto out;
603    }
604
605    if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_LENGTH,
606            &offset) < 0) {
607        goto out;
608    }
609
610    fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDWR | O_SYNC | O_CLOEXEC));
611
612    if (fd == -1) {
613        PERROR << "Failed to open " << fstab->verity_loc;
614        goto out;
615    }
616
617    if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev),
618            offset)) != sizeof(prev)) {
619        PERROR << "Failed to read " << sizeof(prev) << " bytes from "
620               << fstab->verity_loc << " offset " << offset;
621        goto out;
622    }
623
624    *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH);
625
626    if (!*match) {
627        /* update current signature hash */
628        if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
629                offset)) != sizeof(curr)) {
630            PERROR << "Failed to write " << sizeof(curr) << " bytes to "
631                   << fstab->verity_loc << " offset " << offset;
632            goto out;
633        }
634    }
635
636    rc = 0;
637
638out:
639    fec_close(f);
640    return rc;
641}
642
643static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset)
644{
645    char tag[METADATA_TAG_MAX_LENGTH + 1];
646
647    if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s",
648            basename(fstab->mount_point)) >= (int)sizeof(tag)) {
649        LERROR << "Metadata tag name too long for " << fstab->mount_point;
650        return -1;
651    }
652
653    return metadata_find(fstab->verity_loc, tag, sizeof(struct verity_state),
654                offset);
655}
656
657static int load_verity_state(struct fstab_rec *fstab, int *mode)
658{
659    int match = 0;
660    off64_t offset = 0;
661
662    /* unless otherwise specified, use EIO mode */
663    *mode = VERITY_MODE_EIO;
664
665    /* use the kernel parameter if set */
666    std::string veritymode;
667    if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
668        if (veritymode.compare("enforcing")) {
669            *mode = VERITY_MODE_DEFAULT;
670        }
671        return 0;
672    }
673
674    if (get_verity_state_offset(fstab, &offset) < 0) {
675        /* fall back to stateless behavior */
676        return 0;
677    }
678
679    if (was_verity_restart()) {
680        /* device was restarted after dm-verity detected a corrupted
681         * block, so use EIO mode */
682        return write_verity_state(fstab->verity_loc, offset, *mode);
683    }
684
685    if (!compare_last_signature(fstab, &match) && !match) {
686        /* partition has been reflashed, reset dm-verity state */
687        *mode = VERITY_MODE_DEFAULT;
688        return write_verity_state(fstab->verity_loc, offset, *mode);
689    }
690
691    return read_verity_state(fstab->verity_loc, offset, mode);
692}
693
694int fs_mgr_load_verity_state(int *mode)
695{
696    int rc = -1;
697    int i;
698    int current;
699    struct fstab *fstab = NULL;
700
701    /* return the default mode, unless any of the verified partitions are in
702     * logging mode, in which case return that */
703    *mode = VERITY_MODE_DEFAULT;
704
705    fstab = fs_mgr_read_fstab_default();
706    if (!fstab) {
707        LERROR << "Failed to read default fstab";
708        goto out;
709    }
710
711    for (i = 0; i < fstab->num_entries; i++) {
712        if (!fs_mgr_is_verified(&fstab->recs[i])) {
713            continue;
714        }
715
716        rc = load_verity_state(&fstab->recs[i], &current);
717        if (rc < 0) {
718            continue;
719        }
720
721        if (current != VERITY_MODE_DEFAULT) {
722            *mode = current;
723            break;
724        }
725    }
726
727    rc = 0;
728
729out:
730    if (fstab) {
731        fs_mgr_free_fstab(fstab);
732    }
733
734    return rc;
735}
736
737int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
738{
739    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
740    bool system_root = false;
741    std::string mount_point;
742    char propbuf[PROPERTY_VALUE_MAX];
743    const char *status;
744    int fd = -1;
745    int i;
746    int mode;
747    int rc = -1;
748    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
749    struct fstab *fstab = NULL;
750
751    if (!callback) {
752        return -1;
753    }
754
755    if (fs_mgr_load_verity_state(&mode) == -1) {
756        return -1;
757    }
758
759    fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
760    if (fd == -1) {
761        PERROR << "Error opening device mapper";
762        goto out;
763    }
764
765    property_get("ro.build.system_root_image", propbuf, "");
766    system_root = !strcmp(propbuf, "true");
767    fstab = fs_mgr_read_fstab_default();
768    if (!fstab) {
769        LERROR << "Failed to read default fstab";
770        goto out;
771    }
772
773    for (i = 0; i < fstab->num_entries; i++) {
774        if (!fs_mgr_is_verified(&fstab->recs[i])) {
775            continue;
776        }
777
778        if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
779            mount_point = "system";
780        } else {
781            mount_point = basename(fstab->recs[i].mount_point);
782        }
783
784        fs_mgr_verity_ioctl_init(io, mount_point, 0);
785
786        if (ioctl(fd, DM_TABLE_STATUS, io)) {
787            if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
788                status = "V";
789            } else {
790                PERROR << "Failed to query DM_TABLE_STATUS for "
791                       << mount_point.c_str();
792                continue;
793            }
794        }
795
796        status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
797
798        if (*status == 'C' || *status == 'V') {
799            callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
800        }
801    }
802
803    rc = 0;
804
805out:
806    if (fstab) {
807        fs_mgr_free_fstab(fstab);
808    }
809
810    if (fd) {
811        close(fd);
812    }
813
814    return rc;
815}
816
817static void update_verity_table_blk_device(char *blk_device, char **table)
818{
819    std::string result, word;
820    auto tokens = android::base::Split(*table, " ");
821
822    for (const auto& token : tokens) {
823        if (android::base::StartsWith(token, "/dev/block/") &&
824            android::base::StartsWith(blk_device, token.c_str())) {
825            word = blk_device;
826        } else {
827            word = token;
828        }
829
830        if (result.empty()) {
831            result = word;
832        } else {
833            result += " " + word;
834        }
835    }
836
837    if (result.empty()) {
838        return;
839    }
840
841    free(*table);
842    *table = strdup(result.c_str());
843}
844
845// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
846// mount. The 'wait_for_verity_dev' parameter makes this function wait for the
847// verity device to get created before return
848int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev)
849{
850    int retval = FS_MGR_SETUP_VERITY_FAIL;
851    int fd = -1;
852    std::string verity_blk_name;
853    struct fec_handle *f = NULL;
854    struct fec_verity_metadata verity;
855    struct verity_table_params params = { .table = NULL };
856
857    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
858    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
859    const std::string mount_point(basename(fstab->mount_point));
860    bool verified_at_boot = false;
861
862    // This is a public API and so deserves its own check to see if verity
863    // setup is needed at all.
864    if (!is_device_secure()) {
865        LINFO << "Verity setup skipped for " << mount_point;
866        return FS_MGR_SETUP_VERITY_SUCCESS;
867    }
868
869    if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
870            FEC_DEFAULT_ROOTS) < 0) {
871        PERROR << "Failed to open '" << fstab->blk_device << "'";
872        return retval;
873    }
874
875    // read verity metadata
876    if (fec_verity_get_metadata(f, &verity) < 0) {
877        PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
878        // Allow verity disabled when the device is unlocked without metadata
879        if ("0" == android::base::GetProperty("ro.boot.flash.locked", "")) {
880            retval = FS_MGR_SETUP_VERITY_DISABLED;
881            LWARNING << "Allow invalid metadata when the device is unlocked";
882        }
883        goto out;
884    }
885
886#ifdef ALLOW_ADBD_DISABLE_VERITY
887    if (verity.disabled) {
888        retval = FS_MGR_SETUP_VERITY_DISABLED;
889        LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG";
890        goto out;
891    }
892#endif
893
894    // read ecc metadata
895    if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
896        params.ecc.valid = false;
897    }
898
899    params.ecc_dev = fstab->blk_device;
900
901    // get the device mapper fd
902    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
903        PERROR << "Error opening device mapper";
904        goto out;
905    }
906
907    // create the device
908    if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
909        LERROR << "Couldn't create verity device!";
910        goto out;
911    }
912
913    // get the name of the device file
914    if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
915        LERROR << "Couldn't get verity device number!";
916        goto out;
917    }
918
919    if (load_verity_state(fstab, &params.mode) < 0) {
920        /* if accessing or updating the state failed, switch to the default
921         * safe mode. This makes sure the device won't end up in an endless
922         * restart loop, and no corrupted data will be exposed to userspace
923         * without a warning. */
924        params.mode = VERITY_MODE_EIO;
925    }
926
927    if (!verity.table) {
928        goto out;
929    }
930
931    params.table = strdup(verity.table);
932    if (!params.table) {
933        goto out;
934    }
935
936    // verify the signature on the table
937    if (verify_verity_signature(verity) < 0) {
938        if (params.mode == VERITY_MODE_LOGGING) {
939            // the user has been warned, allow mounting without dm-verity
940            retval = FS_MGR_SETUP_VERITY_SUCCESS;
941            goto out;
942        }
943
944        // invalidate root hash and salt to trigger device-specific recovery
945        if (invalidate_table(params.table, verity.table_length) < 0) {
946            goto out;
947        }
948    }
949
950    LINFO << "Enabling dm-verity for " << mount_point.c_str()
951          << " (mode " << params.mode << ")";
952
953    if (fstab->fs_mgr_flags & MF_SLOTSELECT) {
954        // Update the verity params using the actual block device path
955        update_verity_table_blk_device(fstab->blk_device, &params.table);
956    }
957
958    // load the verity mapping table
959    if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
960            format_verity_table) == 0) {
961        goto loaded;
962    }
963
964    if (params.ecc.valid) {
965        // kernel may not support error correction, try without
966        LINFO << "Disabling error correction for " << mount_point.c_str();
967        params.ecc.valid = false;
968
969        if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
970                format_verity_table) == 0) {
971            goto loaded;
972        }
973    }
974
975    // try the legacy format for backwards compatibility
976    if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
977            format_legacy_verity_table) == 0) {
978        goto loaded;
979    }
980
981    if (params.mode != VERITY_MODE_EIO) {
982        // as a last resort, EIO mode should always be supported
983        LINFO << "Falling back to EIO mode for " << mount_point.c_str();
984        params.mode = VERITY_MODE_EIO;
985
986        if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
987                format_legacy_verity_table) == 0) {
988            goto loaded;
989        }
990    }
991
992    LERROR << "Failed to load verity table for " << mount_point.c_str();
993    goto out;
994
995loaded:
996
997    // activate the device
998    if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
999        goto out;
1000    }
1001
1002    // mark the underlying block device as read-only
1003    fs_mgr_set_blk_ro(fstab->blk_device);
1004
1005    // Verify the entire partition in one go
1006    // If there is an error, allow it to mount as a normal verity partition.
1007    if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
1008        LINFO << "Verifying partition " << fstab->blk_device << " at boot";
1009        int err = read_partition(verity_blk_name.c_str(), verity.data_size);
1010        if (!err) {
1011            LINFO << "Verified verity partition "
1012                  << fstab->blk_device << " at boot";
1013            verified_at_boot = true;
1014        }
1015    }
1016
1017    // assign the new verity block device as the block device
1018    if (!verified_at_boot) {
1019        free(fstab->blk_device);
1020        fstab->blk_device = strdup(verity_blk_name.c_str());
1021    } else if (!fs_mgr_destroy_verity_device(io, mount_point, fd)) {
1022        LERROR << "Failed to remove verity device " << mount_point.c_str();
1023        goto out;
1024    }
1025
1026    // make sure we've set everything up properly
1027    if (wait_for_verity_dev && fs_mgr_test_access(fstab->blk_device) < 0) {
1028        goto out;
1029    }
1030
1031    retval = FS_MGR_SETUP_VERITY_SUCCESS;
1032
1033out:
1034    if (fd != -1) {
1035        close(fd);
1036    }
1037
1038    fec_close(f);
1039    free(params.table);
1040
1041    return retval;
1042}
1043