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 <android-base/properties.h> 33 34 #include "adb.h" 35 #include "adb_io.h" 36 #include "adb_utils.h" 37 #include "fs_mgr.h" 38 39 // Returns the device used to mount a directory in /proc/mounts. 40 static std::string find_proc_mount(const char* dir) { 41 std::unique_ptr<FILE, int(*)(FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent); 42 if (!fp) { 43 return ""; 44 } 45 46 mntent* e; 47 while ((e = getmntent(fp.get())) != nullptr) { 48 if (strcmp(dir, e->mnt_dir) == 0) { 49 return e->mnt_fsname; 50 } 51 } 52 return ""; 53 } 54 55 // Returns the device used to mount a directory in the fstab. 56 static std::string find_fstab_mount(const char* dir) { 57 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), 58 fs_mgr_free_fstab); 59 struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), dir); 60 return rec ? rec->blk_device : ""; 61 } 62 63 // The proc entry for / is full of lies, so check fstab instead. 64 // /proc/mounts lists rootfs and /dev/root, neither of which is what we want. 65 static std::string find_mount(const char* dir, bool is_root) { 66 if (is_root) { 67 return find_fstab_mount(dir); 68 } else { 69 return find_proc_mount(dir); 70 } 71 } 72 73 bool make_block_device_writable(const std::string& dev) { 74 int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC); 75 if (fd == -1) { 76 return false; 77 } 78 79 int OFF = 0; 80 bool result = (ioctl(fd, BLKROSET, &OFF) != -1); 81 unix_close(fd); 82 return result; 83 } 84 85 static bool remount_partition(int fd, const char* dir) { 86 if (!directory_exists(dir)) { 87 return true; 88 } 89 bool is_root = strcmp(dir, "/") == 0; 90 std::string dev = find_mount(dir, is_root); 91 // Even if the device for the root is not found, we still try to remount it 92 // as rw. This typically only happens when running Android in a container: 93 // the root will almost always be in a loop device, which is dynamic, so 94 // it's not convenient to put in the fstab. 95 if (dev.empty() && !is_root) { 96 return true; 97 } 98 if (!dev.empty() && !make_block_device_writable(dev)) { 99 WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n", 100 dir, dev.c_str(), strerror(errno)); 101 return false; 102 } 103 if (mount(dev.c_str(), dir, "none", MS_REMOUNT | MS_BIND, nullptr) == -1) { 104 // This is useful for cases where the superblock is already marked as 105 // read-write, but the mount itself is read-only, such as containers 106 // where the remount with just MS_REMOUNT is forbidden by the kernel. 107 WriteFdFmt(fd, "remount of the %s mount failed: %s.\n", dir, strerror(errno)); 108 return false; 109 } 110 if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) { 111 WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno)); 112 return false; 113 } 114 return true; 115 } 116 117 void remount_service(int fd, void* cookie) { 118 if (getuid() != 0) { 119 WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n"); 120 adb_close(fd); 121 return; 122 } 123 124 bool system_verified = !(android::base::GetProperty("partition.system.verified", "").empty()); 125 bool vendor_verified = !(android::base::GetProperty("partition.vendor.verified", "").empty()); 126 127 if (system_verified || vendor_verified) { 128 // Allow remount but warn of likely bad effects 129 bool both = system_verified && vendor_verified; 130 WriteFdFmt(fd, 131 "dm_verity is enabled on the %s%s%s partition%s.\n", 132 system_verified ? "system" : "", 133 both ? " and " : "", 134 vendor_verified ? "vendor" : "", 135 both ? "s" : ""); 136 WriteFdExactly(fd, 137 "Use \"adb disable-verity\" to disable verity.\n" 138 "If you do not, remount may succeed, however, you will still " 139 "not be able to write to these volumes.\n"); 140 } 141 142 bool success = true; 143 if (android::base::GetBoolProperty("ro.build.system_root_image", false)) { 144 success &= remount_partition(fd, "/"); 145 } else { 146 success &= remount_partition(fd, "/system"); 147 } 148 success &= remount_partition(fd, "/odm"); 149 success &= remount_partition(fd, "/oem"); 150 success &= remount_partition(fd, "/product"); 151 success &= remount_partition(fd, "/vendor"); 152 153 WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n"); 154 155 adb_close(fd); 156 } 157