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