Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define TRACE_TAG TRACE_ADB
     18 
     19 #include "sysdeps.h"
     20 
     21 #include <fcntl.h>
     22 #include <inttypes.h>
     23 #include <stdarg.h>
     24 #include <stdio.h>
     25 #include <sys/stat.h>
     26 
     27 #include "cutils/properties.h"
     28 
     29 #include "adb.h"
     30 #include "adb_io.h"
     31 #include "ext4_sb.h"
     32 #include "fs_mgr.h"
     33 #include "remount_service.h"
     34 
     35 #define FSTAB_PREFIX "/fstab."
     36 struct fstab *fstab;
     37 
     38 #ifdef ALLOW_ADBD_DISABLE_VERITY
     39 static const bool kAllowDisableVerity = true;
     40 #else
     41 static const bool kAllowDisableVerity = false;
     42 #endif
     43 
     44 static int get_target_device_size(int fd, const char *blk_device,
     45                                   uint64_t *device_size)
     46 {
     47     int data_device;
     48     struct ext4_super_block sb;
     49     struct fs_info info;
     50 
     51     info.len = 0;  /* Only len is set to 0 to ask the device for real size. */
     52 
     53     data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
     54     if (data_device < 0) {
     55         WriteFdFmt(fd, "Error opening block device (%s)\n", strerror(errno));
     56         return -1;
     57     }
     58 
     59     if (lseek64(data_device, 1024, SEEK_SET) < 0) {
     60         WriteFdFmt(fd, "Error seeking to superblock\n");
     61         adb_close(data_device);
     62         return -1;
     63     }
     64 
     65     if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
     66         WriteFdFmt(fd, "Error reading superblock\n");
     67         adb_close(data_device);
     68         return -1;
     69     }
     70 
     71     ext4_parse_sb(&sb, &info);
     72     *device_size = info.len;
     73 
     74     adb_close(data_device);
     75     return 0;
     76 }
     77 
     78 /* Turn verity on/off */
     79 static int set_verity_enabled_state(int fd, const char *block_device,
     80                                     const char* mount_point, bool enable)
     81 {
     82     uint32_t magic_number;
     83     const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
     84                                       : VERITY_METADATA_MAGIC_DISABLE;
     85     uint64_t device_length = 0;
     86     int device = -1;
     87     int retval = -1;
     88 
     89     if (!make_block_device_writable(block_device)) {
     90         WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
     91                    block_device, strerror(errno));
     92         goto errout;
     93     }
     94 
     95     device = adb_open(block_device, O_RDWR | O_CLOEXEC);
     96     if (device == -1) {
     97         WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
     98         WriteFdFmt(fd, "Maybe run adb remount?\n");
     99         goto errout;
    100     }
    101 
    102     // find the start of the verity metadata
    103     if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
    104         WriteFdFmt(fd, "Could not get target device size.\n");
    105         goto errout;
    106     }
    107 
    108     if (lseek64(device, device_length, SEEK_SET) < 0) {
    109         WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
    110         goto errout;
    111     }
    112 
    113     // check the magic number
    114     if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) {
    115         WriteFdFmt(fd, "Couldn't read magic number!\n");
    116         goto errout;
    117     }
    118 
    119     if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
    120         WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
    121         goto errout;
    122     }
    123 
    124     if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
    125         WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
    126         goto errout;
    127     }
    128 
    129     if (magic_number != VERITY_METADATA_MAGIC_NUMBER
    130             && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
    131         WriteFdFmt(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length);
    132         goto errout;
    133     }
    134 
    135     if (lseek64(device, device_length, SEEK_SET) < 0) {
    136         WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
    137         goto errout;
    138     }
    139 
    140     if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
    141         WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
    142                    enable ? "enabled" : "disabled",
    143                    block_device, strerror(errno));
    144         goto errout;
    145     }
    146 
    147     WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
    148     retval = 0;
    149 errout:
    150     if (device != -1)
    151         adb_close(device);
    152     return retval;
    153 }
    154 
    155 void set_verity_enabled_state_service(int fd, void* cookie)
    156 {
    157     bool enable = (cookie != NULL);
    158     if (kAllowDisableVerity) {
    159         char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
    160         char propbuf[PROPERTY_VALUE_MAX];
    161         int i;
    162         bool any_changed = false;
    163 
    164         property_get("ro.secure", propbuf, "0");
    165         if (strcmp(propbuf, "1")) {
    166             WriteFdFmt(fd, "verity not enabled - ENG build\n");
    167             goto errout;
    168         }
    169 
    170         property_get("ro.debuggable", propbuf, "0");
    171         if (strcmp(propbuf, "1")) {
    172             WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
    173             goto errout;
    174         }
    175 
    176         property_get("ro.hardware", propbuf, "");
    177         snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s",
    178                  propbuf);
    179 
    180         fstab = fs_mgr_read_fstab(fstab_filename);
    181         if (!fstab) {
    182             WriteFdFmt(fd, "Failed to open %s\nMaybe run adb root?\n", fstab_filename);
    183             goto errout;
    184         }
    185 
    186         /* Loop through entries looking for ones that vold manages */
    187         for (i = 0; i < fstab->num_entries; i++) {
    188             if(fs_mgr_is_verified(&fstab->recs[i])) {
    189                 if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device,
    190                                               fstab->recs[i].mount_point,
    191                                               enable)) {
    192                     any_changed = true;
    193                 }
    194            }
    195         }
    196 
    197         if (any_changed) {
    198             WriteFdFmt(fd, "Now reboot your device for settings to take effect\n");
    199         }
    200     } else {
    201         WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
    202                    enable ? "enable" : "disable");
    203     }
    204 
    205 errout:
    206     adb_close(fd);
    207 }
    208