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