remount_service.cpp revision d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70a
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 173313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#define TRACE_TAG TRACE_ADB 183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "sysdeps.h" 203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert 2160299dfd6a5dca059a079bc8e11d45a1fecf02d0Mark Salyzyn#include <errno.h> 2260299dfd6a5dca059a079bc8e11d45a1fecf02d0Mark Salyzyn#include <fcntl.h> 23d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui#include <mntent.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 2560299dfd6a5dca059a079bc8e11d45a1fecf02d0Mark Salyzyn#include <stdlib.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/mount.h> 2860299dfd6a5dca059a079bc8e11d45a1fecf02d0Mark Salyzyn#include <unistd.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 30ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes#include <string> 31ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h" 33cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert#include "adb_io.h" 345830577bd82fdb7c39555da20a4cf585b8bb376aElliott Hughes#include "adb_utils.h" 357664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "cutils/properties.h" 36d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg#include "fs_mgr.h" 37d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg 38d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenbergconst std::string kFstab_Prefix = "/fstab."; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 405677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes// Returns the device used to mount a directory in /proc/mounts. 41d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenbergstatic std::string find_proc_mount(const char* dir) { 425677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes std::unique_ptr<FILE, int(*)(FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent); 435677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes if (!fp) { 445677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes return ""; 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 465677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes 475677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes mntent* e; 485677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes while ((e = getmntent(fp.get())) != nullptr) { 495677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes if (strcmp(dir, e->mnt_dir) == 0) { 505677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes return e->mnt_fsname; 51d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui } 52d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui } 535677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes return ""; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 56d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg// Returns the device used to mount a directory in the fstab. 57d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenbergstatic std::string find_fstab_mount(const char* dir) { 58d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg char propbuf[PROPERTY_VALUE_MAX]; 59d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg 60d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg property_get("ro.hardware", propbuf, ""); 61d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg std::string fstab_filename = kFstab_Prefix + propbuf; 62d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str()); 63d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir); 64d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg std::string dev = rec ? std::string(rec->blk_device) : ""; 65d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg fs_mgr_free_fstab(fstab); 66d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg return dev; 67d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg} 68d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg 69d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg// The proc entry for / is full of lies, so check fstab instead. 70d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg// /proc/mounts lists rootfs and /dev/root, neither of which is what we want. 71d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenbergstatic std::string find_mount(const char* dir) { 72d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg if (strcmp(dir, "/") == 0) { 73d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg return find_fstab_mount(dir); 74d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg } else { 75d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg return find_proc_mount(dir); 76d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg } 77d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg} 78d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg 799aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughesbool make_block_device_writable(const std::string& dev) { 80ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC); 81ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes if (fd == -1) { 829aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes return false; 83982089d83879c768eac3fd36f19665463a550b53Paul Lawrence } 84982089d83879c768eac3fd36f19665463a550b53Paul Lawrence 85ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes int OFF = 0; 869aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes bool result = (ioctl(fd, BLKROSET, &OFF) != -1); 876ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low unix_close(fd); 88ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes return result; 89ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes} 906084a0124f868c7ec43f6c415a27a168f27ff694Dan Albert 919aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughesstatic bool remount_partition(int fd, const char* dir) { 929aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes if (!directory_exists(dir)) { 939aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes return true; 9413449cd71464c3a644109c469a77bd7fd56c8af8Sami Tolvanen } 959aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes std::string dev = find_mount(dir); 969aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes if (dev.empty()) { 975677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes return true; 985677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes } 999aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes if (!make_block_device_writable(dev)) { 1009aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n", 1019aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes dir, dev.c_str(), strerror(errno)); 1029aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes return false; 1039aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes } 1049aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) { 1059aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno)); 1065677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes return false; 1075677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes } 108ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes return true; 109ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes} 110ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes 111ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesvoid remount_service(int fd, void* cookie) { 112268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich if (getuid() != 0) { 113e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n"); 114268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich adb_close(fd); 115268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich return; 116268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich } 117268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich 1185677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes char prop_buf[PROPERTY_VALUE_MAX]; 119454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen property_get("partition.system.verified", prop_buf, ""); 1205677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes bool system_verified = (strlen(prop_buf) > 0); 12134637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence 122454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen property_get("partition.vendor.verified", prop_buf, ""); 1235677c23e8d0c085be8d8429a5d125147d11e9bb2Elliott Hughes bool vendor_verified = (strlen(prop_buf) > 0); 12434637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence 12534637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence if (system_verified || vendor_verified) { 12634637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence // Allow remount but warn of likely bad effects 12734637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence bool both = system_verified && vendor_verified; 128ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes WriteFdFmt(fd, 129ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes "dm_verity is enabled on the %s%s%s partition%s.\n", 130ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes system_verified ? "system" : "", 131ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes both ? " and " : "", 132ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes vendor_verified ? "vendor" : "", 133ab52c181fa4c1c9891644635dc5653cda5b90e2bElliott Hughes both ? "s" : ""); 134e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes WriteFdExactly(fd, 135e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes "Use \"adb disable-verity\" to disable verity.\n" 136e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes "If you do not, remount may succeed, however, you will still " 137e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes "not be able to write to these volumes.\n"); 13834637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence } 13934637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence 140ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes bool success = true; 141d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg property_get("ro.build.system_root_image", prop_buf, ""); 142d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg bool system_root = !strcmp(prop_buf, "true"); 143d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg if (system_root) { 144d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg success &= remount_partition(fd, "/"); 145d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg } else { 146d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg success &= remount_partition(fd, "/system"); 147d6eba89f83a4028a4b25e44dc0f8bc59dd6ad70aDaniel Rosenberg } 1489aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes success &= remount_partition(fd, "/vendor"); 1499aa4fda4e64c1882faf019cc2a483ee4917e0c85Elliott Hughes success &= remount_partition(fd, "/oem"); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 151e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n"); 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_close(fd); 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 155