Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2008 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 "sysdeps.h"
     18 
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <sys/mount.h>
     25 #include <unistd.h>
     26 
     27 #include "cutils/properties.h"
     28 
     29 #define  TRACE_TAG  TRACE_ADB
     30 #include "adb.h"
     31 
     32 
     33 static int system_ro = 1;
     34 static int vendor_ro = 1;
     35 
     36 /* Returns the device used to mount a directory in /proc/mounts */
     37 static char *find_mount(const char *dir)
     38 {
     39     int fd;
     40     int res;
     41     char *token = NULL;
     42     const char delims[] = "\n";
     43     char buf[4096];
     44 
     45     fd = unix_open("/proc/mounts", O_RDONLY | O_CLOEXEC);
     46     if (fd < 0)
     47         return NULL;
     48 
     49     buf[sizeof(buf) - 1] = '\0';
     50     adb_read(fd, buf, sizeof(buf) - 1);
     51     adb_close(fd);
     52 
     53     token = strtok(buf, delims);
     54 
     55     while (token) {
     56         char mount_dev[256];
     57         char mount_dir[256];
     58         int mount_freq;
     59         int mount_passno;
     60 
     61         res = sscanf(token, "%255s %255s %*s %*s %d %d\n",
     62                      mount_dev, mount_dir, &mount_freq, &mount_passno);
     63         mount_dev[255] = 0;
     64         mount_dir[255] = 0;
     65         if (res == 4 && (strcmp(dir, mount_dir) == 0))
     66             return strdup(mount_dev);
     67 
     68         token = strtok(NULL, delims);
     69     }
     70     return NULL;
     71 }
     72 
     73 static int hasVendorPartition()
     74 {
     75     struct stat info;
     76     if (!lstat("/vendor", &info))
     77         if ((info.st_mode & S_IFMT) == S_IFDIR)
     78           return true;
     79     return false;
     80 }
     81 
     82 /* Init mounts /system as read only, remount to enable writes. */
     83 static int remount(const char* dir, int* dir_ro)
     84 {
     85     char *dev;
     86     int fd;
     87     int OFF = 0;
     88 
     89     if (dir_ro == 0) {
     90         return 0;
     91     }
     92 
     93     dev = find_mount(dir);
     94 
     95     if (!dev)
     96         return -1;
     97 
     98     fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
     99     if (fd < 0)
    100         return -1;
    101 
    102     ioctl(fd, BLKROSET, &OFF);
    103     adb_close(fd);
    104 
    105     *dir_ro = mount(dev, dir, "none", MS_REMOUNT, NULL);
    106 
    107     free(dev);
    108 
    109     return *dir_ro;
    110 }
    111 
    112 static void write_string(int fd, const char* str)
    113 {
    114     writex(fd, str, strlen(str));
    115 }
    116 
    117 void remount_service(int fd, void *cookie)
    118 {
    119     char buffer[200];
    120     char prop_buf[PROPERTY_VALUE_MAX];
    121 
    122     bool system_verified = false, vendor_verified = false;
    123     property_get("partition.system.verified", prop_buf, "0");
    124     if (!strcmp(prop_buf, "1")) {
    125         system_verified = true;
    126     }
    127 
    128     property_get("partition.vendor.verified", prop_buf, "0");
    129     if (!strcmp(prop_buf, "1")) {
    130         vendor_verified = true;
    131     }
    132 
    133     if (system_verified || vendor_verified) {
    134         // Allow remount but warn of likely bad effects
    135         bool both = system_verified && vendor_verified;
    136         snprintf(buffer, sizeof(buffer),
    137                  "dm_verity is enabled on the %s%s%s partition%s.\n",
    138                  system_verified ? "system" : "",
    139                  both ? " and " : "",
    140                  vendor_verified ? "vendor" : "",
    141                  both ? "s" : "");
    142         write_string(fd, buffer);
    143         snprintf(buffer, sizeof(buffer),
    144                  "Use \"adb disable-verity\" to disable verity.\n"
    145                  "If you do not, remount may succeed, however, you will still "
    146                  "not be able to write to these volumes.\n");
    147         write_string(fd, buffer);
    148     }
    149 
    150     if (remount("/system", &system_ro)) {
    151         snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
    152         write_string(fd, buffer);
    153     }
    154 
    155     if (hasVendorPartition()) {
    156         if (remount("/vendor", &vendor_ro)) {
    157             snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno));
    158             write_string(fd, buffer);
    159         }
    160     }
    161 
    162     if (!system_ro && (!vendor_ro || !hasVendorPartition()))
    163         write_string(fd, "remount succeeded\n");
    164     else {
    165         write_string(fd, "remount failed\n");
    166     }
    167 
    168     adb_close(fd);
    169 }
    170 
    171