remount_service.cpp revision 454742392f72079dbdb0d23ea24e01b5703c1aa5
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"
347664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "cutils/properties.h"
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int system_ro = 1;
37686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenbergstatic int vendor_ro = 1;
38ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesstatic int oem_ro = 1;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40c880ee0265a4057fd5086f4b9e8e5fae6e053087Colin Cross/* Returns the device used to mount a directory in /proc/mounts */
41ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesstatic std::string find_mount(const char *dir) {
42d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    FILE* fp;
43d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    struct mntent* mentry;
44d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    char* device = NULL;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
47c880ee0265a4057fd5086f4b9e8e5fae6e053087Colin Cross        return NULL;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
49d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    while ((mentry = getmntent(fp)) != NULL) {
50d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui        if (strcmp(dir, mentry->mnt_dir) == 0) {
51ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes            device = mentry->mnt_fsname;
52d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui            break;
53d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui        }
54d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    }
55d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    endmntent(fp);
56d6bd9bf45968cb97ed88a4e06c40a127625897b1Yabin Cui    return device;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesstatic bool has_partition(const char* path) {
60ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    struct stat sb;
61ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    return (lstat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
62686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg}
63686bce6390db802bfd2cb4e78f9270596b6decb2Daniel Rosenberg
64ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesint make_block_device_writable(const std::string& dev) {
65ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
66ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    if (fd == -1) {
67ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes        return -1;
68982089d83879c768eac3fd36f19665463a550b53Paul Lawrence    }
69982089d83879c768eac3fd36f19665463a550b53Paul Lawrence
70ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    int result = -1;
71ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    int OFF = 0;
72ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    if (!ioctl(fd, BLKROSET, &OFF)) {
73ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes        result = 0;
746084a0124f868c7ec43f6c415a27a168f27ff694Dan Albert    }
75ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    adb_close(fd);
766084a0124f868c7ec43f6c415a27a168f27ff694Dan Albert
77ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    return result;
78ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes}
796084a0124f868c7ec43f6c415a27a168f27ff694Dan Albert
80ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes// Init mounts /system as read only, remount to enable writes.
81ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesstatic int remount(const char* dir, int* dir_ro) {
82ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    std::string dev(find_mount(dir));
83ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    if (dev.empty() || make_block_device_writable(dev)) {
84ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes        return -1;
8513449cd71464c3a644109c469a77bd7fd56c8af8Sami Tolvanen    }
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    int rc = mount(dev.c_str(), dir, "none", MS_REMOUNT, NULL);
8813449cd71464c3a644109c469a77bd7fd56c8af8Sami Tolvanen    *dir_ro = rc;
896084a0124f868c7ec43f6c415a27a168f27ff694Dan Albert    return rc;
9081416fdb186070fe4db3ca5fed2e713a4eecaac1Mårten Kongstad}
9181416fdb186070fe4db3ca5fed2e713a4eecaac1Mårten Kongstad
92ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesstatic bool remount_partition(int fd, const char* partition, int* ro) {
93ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes  if (!has_partition(partition)) {
94ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    return true;
95ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes  }
96ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes  if (remount(partition, ro)) {
97ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    char buf[200];
98ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
99ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    WriteStringFully(fd, buf);
100ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    return false;
101ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes  }
102ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes  return true;
103ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes}
104ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes
105ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughesvoid remount_service(int fd, void* cookie) {
10634637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence    char prop_buf[PROPERTY_VALUE_MAX];
10734637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence
108268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich    if (getuid() != 0) {
109268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich        WriteStringFully(fd, "Not running as root. Try \"adb root\" first.\n");
110268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich        adb_close(fd);
111268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich        return;
112268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich    }
113268eb4f3846d551c73eb4fc5a505f9a70d47b638Nick Kralevich
11434637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence    bool system_verified = false, vendor_verified = false;
115454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen    property_get("partition.system.verified", prop_buf, "");
116454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen    if (strlen(prop_buf) > 0) {
11734637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence        system_verified = true;
11834637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence    }
11934637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence
120454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen    property_get("partition.vendor.verified", prop_buf, "");
121454742392f72079dbdb0d23ea24e01b5703c1aa5Sami Tolvanen    if (strlen(prop_buf) > 0) {
12234637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence        vendor_verified = true;
12334637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence    }
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;
128ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes        char buffer[200];
12934637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence        snprintf(buffer, sizeof(buffer),
13034637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 "dm_verity is enabled on the %s%s%s partition%s.\n",
13134637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 system_verified ? "system" : "",
13234637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 both ? " and " : "",
13334637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 vendor_verified ? "vendor" : "",
13434637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 both ? "s" : "");
135cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert        WriteStringFully(fd, buffer);
13634637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence        snprintf(buffer, sizeof(buffer),
13734637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 "Use \"adb disable-verity\" to disable verity.\n"
13834637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 "If you do not, remount may succeed, however, you will still "
13934637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence                 "not be able to write to these volumes.\n");
140cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert        WriteStringFully(fd, buffer);
14134637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence    }
14234637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence
143ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    bool success = true;
144ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    success &= remount_partition(fd, "/system", &system_ro);
145ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    success &= remount_partition(fd, "/vendor", &vendor_ro);
146ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    success &= remount_partition(fd, "/oem", &oem_ro);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148ec7a66713144a16361724fe88332b28bbf3f4b3cElliott Hughes    WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152