remount_service.cpp revision 3313426fad9eaaf53017cdbde889ebcec91358ec
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; 11534637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence property_get("partition.system.verified", prop_buf, "0"); 11634637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence if (!strcmp(prop_buf, "1")) { 11734637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence system_verified = true; 11834637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence } 11934637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence 12034637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence property_get("partition.vendor.verified", prop_buf, "0"); 12134637555c25a6663658b1ff45e98272b10b449f4Paul Lawrence if (!strcmp(prop_buf, "1")) { 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