fs_mgr_remount.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (C) 2019 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. #include <errno.h>
  17. #include <getopt.h>
  18. #include <libavb_user/libavb_user.h>
  19. #include <stdio.h>
  20. #include <sys/mount.h>
  21. #include <sys/types.h>
  22. #include <sys/vfs.h>
  23. #include <unistd.h>
  24. #include <string>
  25. #include <utility>
  26. #include <vector>
  27. #include <android-base/file.h>
  28. #include <android-base/logging.h>
  29. #include <android-base/properties.h>
  30. #include <android-base/strings.h>
  31. #include <bootloader_message/bootloader_message.h>
  32. #include <cutils/android_reboot.h>
  33. #include <fec/io.h>
  34. #include <fs_mgr_overlayfs.h>
  35. #include <fs_mgr_priv.h>
  36. #include <fstab/fstab.h>
  37. namespace {
  38. [[noreturn]] void usage(int exit_status) {
  39. LOG(INFO) << getprogname()
  40. << " [-h] [-R] [-T fstab_file] [partition]...\n"
  41. "\t-h --help\tthis help\n"
  42. "\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
  43. "\t-T --fstab\tcustom fstab file location\n"
  44. "\tpartition\tspecific partition(s) (empty does all)\n"
  45. "\n"
  46. "Remount specified partition(s) read-write, by name or mount point.\n"
  47. "-R notwithstanding, verity must be disabled on partition(s).";
  48. ::exit(exit_status);
  49. }
  50. bool remountable_partition(const android::fs_mgr::FstabEntry& entry) {
  51. if (entry.fs_mgr_flags.vold_managed) return false;
  52. if (entry.fs_mgr_flags.recovery_only) return false;
  53. if (entry.fs_mgr_flags.slot_select_other) return false;
  54. if (!(entry.flags & MS_RDONLY)) return false;
  55. if (entry.fs_type == "vfat") return false;
  56. return true;
  57. }
  58. const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
  59. if (entry.mount_point == "/") return "/system";
  60. return entry.mount_point;
  61. }
  62. const android::fs_mgr::FstabEntry* is_wrapped(const android::fs_mgr::Fstab& overlayfs_candidates,
  63. const android::fs_mgr::FstabEntry& entry) {
  64. auto mount_point = system_mount_point(entry);
  65. auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(),
  66. [&mount_point](const auto& entry) {
  67. return android::base::StartsWith(mount_point,
  68. system_mount_point(entry) + "/");
  69. });
  70. if (it == overlayfs_candidates.end()) return nullptr;
  71. return &(*it);
  72. }
  73. void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
  74. const char* file, unsigned int line, const char* message) {
  75. static const char log_characters[] = "VD\0WEFF";
  76. if (severity < sizeof(log_characters)) {
  77. auto severity_char = log_characters[severity];
  78. if (severity_char) fprintf(stderr, "%c ", severity_char);
  79. }
  80. fprintf(stderr, "%s\n", message);
  81. static auto logd = android::base::LogdLogger();
  82. logd(id, severity, tag, file, line, message);
  83. }
  84. [[noreturn]] void reboot(bool dedupe) {
  85. if (dedupe) {
  86. LOG(INFO) << "The device will now reboot to recovery and attempt un-deduplication.";
  87. } else {
  88. LOG(INFO) << "Successfully disabled verity\nrebooting device";
  89. }
  90. ::sync();
  91. android::base::SetProperty(ANDROID_RB_PROPERTY, dedupe ? "reboot,recovery" : "reboot,remount");
  92. ::sleep(60);
  93. ::exit(0); // SUCCESS
  94. }
  95. } // namespace
  96. int main(int argc, char* argv[]) {
  97. android::base::InitLogging(argv, MyLogger);
  98. enum {
  99. SUCCESS,
  100. NOT_USERDEBUG,
  101. BADARG,
  102. NOT_ROOT,
  103. NO_FSTAB,
  104. UNKNOWN_PARTITION,
  105. INVALID_PARTITION,
  106. VERITY_PARTITION,
  107. BAD_OVERLAY,
  108. NO_MOUNTS,
  109. REMOUNT_FAILED,
  110. } retval = SUCCESS;
  111. // If somehow this executable is delivered on a "user" build, it can
  112. // not function, so providing a clear message to the caller rather than
  113. // letting if fall through and provide a lot of confusing failure messages.
  114. if (!ALLOW_ADBD_DISABLE_VERITY || (android::base::GetProperty("ro.debuggable", "0") != "1")) {
  115. LOG(ERROR) << "only functions on userdebug or eng builds";
  116. return NOT_USERDEBUG;
  117. }
  118. const char* fstab_file = nullptr;
  119. auto can_reboot = false;
  120. struct option longopts[] = {
  121. {"fstab", required_argument, nullptr, 'T'},
  122. {"help", no_argument, nullptr, 'h'},
  123. {"reboot", no_argument, nullptr, 'R'},
  124. {0, 0, nullptr, 0},
  125. };
  126. for (int opt; (opt = ::getopt_long(argc, argv, "hRT:", longopts, nullptr)) != -1;) {
  127. switch (opt) {
  128. case 'R':
  129. can_reboot = true;
  130. break;
  131. case 'T':
  132. if (fstab_file) {
  133. LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
  134. usage(BADARG);
  135. }
  136. fstab_file = optarg;
  137. break;
  138. default:
  139. LOG(ERROR) << "Bad Argument -" << char(opt);
  140. usage(BADARG);
  141. break;
  142. case 'h':
  143. usage(SUCCESS);
  144. break;
  145. }
  146. }
  147. // Make sure we are root.
  148. if (::getuid() != 0) {
  149. LOG(ERROR) << "must be run as root";
  150. return NOT_ROOT;
  151. }
  152. // Read the selected fstab.
  153. android::fs_mgr::Fstab fstab;
  154. auto fstab_read = false;
  155. if (fstab_file) {
  156. fstab_read = android::fs_mgr::ReadFstabFromFile(fstab_file, &fstab);
  157. } else {
  158. fstab_read = android::fs_mgr::ReadDefaultFstab(&fstab);
  159. // Manufacture a / entry from /proc/mounts if missing.
  160. if (!GetEntryForMountPoint(&fstab, "/system") && !GetEntryForMountPoint(&fstab, "/")) {
  161. android::fs_mgr::Fstab mounts;
  162. if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
  163. if (auto entry = GetEntryForMountPoint(&mounts, "/")) {
  164. if (entry->fs_type != "rootfs") fstab.emplace_back(*entry);
  165. }
  166. }
  167. }
  168. }
  169. if (!fstab_read || fstab.empty()) {
  170. PLOG(ERROR) << "Failed to read fstab";
  171. return NO_FSTAB;
  172. }
  173. // Generate the list of supported overlayfs mount points.
  174. auto overlayfs_candidates = fs_mgr_overlayfs_candidate_list(fstab);
  175. // Generate the all remountable partitions sub-list
  176. android::fs_mgr::Fstab all;
  177. for (auto const& entry : fstab) {
  178. if (!remountable_partition(entry)) continue;
  179. if (overlayfs_candidates.empty() ||
  180. GetEntryForMountPoint(&overlayfs_candidates, entry.mount_point) ||
  181. (is_wrapped(overlayfs_candidates, entry) == nullptr)) {
  182. all.emplace_back(entry);
  183. }
  184. }
  185. // Parse the unique list of valid partition arguments.
  186. android::fs_mgr::Fstab partitions;
  187. for (; argc > optind; ++optind) {
  188. auto partition = std::string(argv[optind]);
  189. if (partition.empty()) continue;
  190. if (partition == "/") partition = "/system";
  191. auto find_part = [&partition](const auto& entry) {
  192. const auto mount_point = system_mount_point(entry);
  193. if (partition == mount_point) return true;
  194. if (partition == android::base::Basename(mount_point)) return true;
  195. return false;
  196. };
  197. // Do we know about the partition?
  198. auto it = std::find_if(fstab.begin(), fstab.end(), find_part);
  199. if (it == fstab.end()) {
  200. LOG(ERROR) << "Unknown partition " << argv[optind] << ", skipping";
  201. retval = UNKNOWN_PARTITION;
  202. continue;
  203. }
  204. // Is that one covered by an existing overlayfs?
  205. auto wrap = is_wrapped(overlayfs_candidates, *it);
  206. if (wrap) {
  207. LOG(INFO) << "partition " << argv[optind] << " covered by overlayfs for "
  208. << wrap->mount_point << ", switching";
  209. partition = system_mount_point(*wrap);
  210. }
  211. // Is it a remountable partition?
  212. it = std::find_if(all.begin(), all.end(), find_part);
  213. if (it == all.end()) {
  214. LOG(ERROR) << "Invalid partition " << argv[optind] << ", skipping";
  215. retval = INVALID_PARTITION;
  216. continue;
  217. }
  218. if (GetEntryForMountPoint(&partitions, it->mount_point) == nullptr) {
  219. partitions.emplace_back(*it);
  220. }
  221. }
  222. if (partitions.empty() && !retval) {
  223. partitions = all;
  224. }
  225. // Check verity and optionally setup overlayfs backing.
  226. auto reboot_later = false;
  227. auto uses_overlayfs = fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported;
  228. auto just_disabled_verity = false;
  229. for (auto it = partitions.begin(); it != partitions.end();) {
  230. auto& entry = *it;
  231. auto& mount_point = entry.mount_point;
  232. if (fs_mgr_is_verity_enabled(entry)) {
  233. retval = VERITY_PARTITION;
  234. if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") != "locked") {
  235. if (AvbOps* ops = avb_ops_user_new()) {
  236. auto ret = avb_user_verity_set(
  237. ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
  238. false);
  239. avb_ops_user_free(ops);
  240. if (ret) {
  241. LOG(WARNING) << "Disabling verity for " << mount_point;
  242. just_disabled_verity = true;
  243. reboot_later = can_reboot;
  244. if (reboot_later) {
  245. // w/o overlayfs available, also check for dedupe
  246. if (!uses_overlayfs) {
  247. ++it;
  248. continue;
  249. }
  250. reboot(false);
  251. }
  252. } else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
  253. fec::io fh(entry.blk_device.c_str(), O_RDWR);
  254. if (fh && fh.set_verity_status(false)) {
  255. LOG(WARNING) << "Disabling verity for " << mount_point;
  256. just_disabled_verity = true;
  257. reboot_later = can_reboot;
  258. if (reboot_later && !uses_overlayfs) {
  259. ++it;
  260. continue;
  261. }
  262. }
  263. }
  264. }
  265. }
  266. LOG(ERROR) << "Skipping " << mount_point;
  267. it = partitions.erase(it);
  268. continue;
  269. }
  270. auto change = false;
  271. errno = 0;
  272. if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, just_disabled_verity)) {
  273. if (change) {
  274. LOG(INFO) << "Using overlayfs for " << mount_point;
  275. }
  276. } else if (errno) {
  277. PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
  278. retval = BAD_OVERLAY;
  279. it = partitions.erase(it);
  280. continue;
  281. }
  282. ++it;
  283. }
  284. if (partitions.empty()) {
  285. if (reboot_later) reboot(false);
  286. LOG(WARNING) << "No partitions to remount";
  287. return retval;
  288. }
  289. // Mount overlayfs.
  290. errno = 0;
  291. if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
  292. retval = BAD_OVERLAY;
  293. PLOG(ERROR) << "Can not mount overlayfs for partitions";
  294. }
  295. // Get actual mounts _after_ overlayfs has been added.
  296. android::fs_mgr::Fstab mounts;
  297. if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
  298. PLOG(ERROR) << "Failed to read /proc/mounts";
  299. retval = NO_MOUNTS;
  300. }
  301. // Remount selected partitions.
  302. for (auto& entry : partitions) {
  303. // unlock the r/o key for the mount point device
  304. if (entry.fs_mgr_flags.logical) {
  305. fs_mgr_update_logical_partition(&entry);
  306. }
  307. auto blk_device = entry.blk_device;
  308. auto mount_point = entry.mount_point;
  309. for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
  310. auto& rentry = *it;
  311. if (mount_point == rentry.mount_point) {
  312. blk_device = rentry.blk_device;
  313. break;
  314. }
  315. // Find overlayfs mount point?
  316. if ((mount_point == "/") && (rentry.mount_point == "/system")) {
  317. blk_device = rentry.blk_device;
  318. mount_point = "/system";
  319. break;
  320. }
  321. }
  322. if (blk_device == "/dev/root") {
  323. auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
  324. if (from_fstab) blk_device = from_fstab->blk_device;
  325. }
  326. fs_mgr_set_blk_ro(blk_device, false);
  327. // Find system-as-root mount point?
  328. if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
  329. GetEntryForMountPoint(&mounts, "/")) {
  330. mount_point = "/";
  331. }
  332. // Now remount!
  333. if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
  334. nullptr) == 0) {
  335. continue;
  336. }
  337. if ((errno == EINVAL) && (mount_point != entry.mount_point)) {
  338. mount_point = entry.mount_point;
  339. if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
  340. nullptr) == 0) {
  341. continue;
  342. }
  343. }
  344. PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
  345. // If errno is EROFS at this point, we are dealing with r/o
  346. // filesystem types like squashfs, erofs or ext4 dedupe. We will
  347. // consider such a device that does not have CONFIG_OVERLAY_FS
  348. // in the kernel as a misconfigured.
  349. if (errno == EROFS) {
  350. LOG(ERROR) << "Consider providing all the dependencies to enable overlayfs";
  351. }
  352. retval = REMOUNT_FAILED;
  353. }
  354. if (reboot_later) reboot(false);
  355. return retval;
  356. }