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 #define TRACE_TAG ADB 18 19 #include "sysdeps.h" 20 21 #include <errno.h> 22 #include <fcntl.h> 23 #include <mntent.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/mount.h> 28 #include <unistd.h> 29 30 #include <string> 31 32 #include "adb.h" 33 #include "adb_io.h" 34 #include "adb_utils.h" 35 #include "cutils/properties.h" 36 #include "fs_mgr.h" 37 38 // Returns the device used to mount a directory in /proc/mounts. 39 static std::string find_proc_mount(const char* dir) { 40 std::unique_ptr<FILE, int(*)(FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent); 41 if (!fp) { 42 return ""; 43 } 44 45 mntent* e; 46 while ((e = getmntent(fp.get())) != nullptr) { 47 if (strcmp(dir, e->mnt_dir) == 0) { 48 return e->mnt_fsname; 49 } 50 } 51 return ""; 52 } 53 54 // Returns the device used to mount a directory in the fstab. 55 static std::string find_fstab_mount(const char* dir) { 56 char propbuf[PROPERTY_VALUE_MAX]; 57 58 property_get("ro.hardware", propbuf, ""); 59 std::string fstab_filename = std::string("/fstab.") + propbuf; 60 struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str()); 61 struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir); 62 std::string dev = rec ? std::string(rec->blk_device) : ""; 63 fs_mgr_free_fstab(fstab); 64 return dev; 65 } 66 67 // The proc entry for / is full of lies, so check fstab instead. 68 // /proc/mounts lists rootfs and /dev/root, neither of which is what we want. 69 static std::string find_mount(const char* dir) { 70 if (strcmp(dir, "/") == 0) { 71 return find_fstab_mount(dir); 72 } else { 73 return find_proc_mount(dir); 74 } 75 } 76 77 bool make_block_device_writable(const std::string& dev) { 78 int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC); 79 if (fd == -1) { 80 return false; 81 } 82 83 int OFF = 0; 84 bool result = (ioctl(fd, BLKROSET, &OFF) != -1); 85 unix_close(fd); 86 return result; 87 } 88 89 static bool remount_partition(int fd, const char* dir) { 90 if (!directory_exists(dir)) { 91 return true; 92 } 93 std::string dev = find_mount(dir); 94 if (dev.empty()) { 95 return true; 96 } 97 if (!make_block_device_writable(dev)) { 98 WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n", 99 dir, dev.c_str(), strerror(errno)); 100 return false; 101 } 102 if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) { 103 WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno)); 104 return false; 105 } 106 return true; 107 } 108 109 void remount_service(int fd, void* cookie) { 110 if (getuid() != 0) { 111 WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n"); 112 adb_close(fd); 113 return; 114 } 115 116 char prop_buf[PROPERTY_VALUE_MAX]; 117 property_get("partition.system.verified", prop_buf, ""); 118 bool system_verified = (strlen(prop_buf) > 0); 119 120 property_get("partition.vendor.verified", prop_buf, ""); 121 bool vendor_verified = (strlen(prop_buf) > 0); 122 123 if (system_verified || vendor_verified) { 124 // Allow remount but warn of likely bad effects 125 bool both = system_verified && vendor_verified; 126 WriteFdFmt(fd, 127 "dm_verity is enabled on the %s%s%s partition%s.\n", 128 system_verified ? "system" : "", 129 both ? " and " : "", 130 vendor_verified ? "vendor" : "", 131 both ? "s" : ""); 132 WriteFdExactly(fd, 133 "Use \"adb disable-verity\" to disable verity.\n" 134 "If you do not, remount may succeed, however, you will still " 135 "not be able to write to these volumes.\n"); 136 } 137 138 bool success = true; 139 property_get("ro.build.system_root_image", prop_buf, ""); 140 bool system_root = !strcmp(prop_buf, "true"); 141 if (system_root) { 142 success &= remount_partition(fd, "/"); 143 } else { 144 success &= remount_partition(fd, "/system"); 145 } 146 success &= remount_partition(fd, "/vendor"); 147 success &= remount_partition(fd, "/oem"); 148 149 WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n"); 150 151 adb_close(fd); 152 } 153