No Description

roots.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Copyright (C) 2007 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 "roots.h"
  17. #include <ctype.h>
  18. #include <fcntl.h>
  19. #include <stdint.h>
  20. #include <dirent.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/mount.h>
  24. #include <sys/stat.h>
  25. #include <sys/types.h>
  26. #include <sys/wait.h>
  27. #include <unistd.h>
  28. #include <algorithm>
  29. #include <string>
  30. #include <vector>
  31. #include <android-base/logging.h>
  32. #include <android-base/properties.h>
  33. #include <android-base/stringprintf.h>
  34. #include <android-base/unique_fd.h>
  35. #include <cutils/fs.h>
  36. #include <cryptfs.h>
  37. #include <ext4_utils/wipe.h>
  38. #include <fs_mgr.h>
  39. #include "mounts.h"
  40. static struct fstab* fstab = nullptr;
  41. extern struct selabel_handle* sehandle;
  42. static void write_fstab_entry(const Volume *v, FILE *file)
  43. {
  44. if (v &&
  45. strcmp(v->fs_type, "mtd") != 0 && strcmp(v->fs_type, "emmc") != 0 &&
  46. strcmp(v->fs_type, "bml") != 0 && !fs_mgr_is_voldmanaged(v) &&
  47. strncmp(v->blk_device, "/", 1) == 0 &&
  48. strncmp(v->mount_point, "/", 1) == 0) {
  49. fprintf(file, "%s ", v->blk_device);
  50. fprintf(file, "%s ", v->mount_point);
  51. fprintf(file, "%s ", v->fs_type);
  52. fprintf(file, "%s 0 0\n", v->fs_options ? v->fs_options : "defaults");
  53. }
  54. }
  55. int get_num_volumes() {
  56. return fstab->num_entries;
  57. }
  58. Volume* get_device_volumes() {
  59. return fstab->recs;
  60. }
  61. void load_volume_table() {
  62. fstab = fs_mgr_read_fstab_default();
  63. if (!fstab) {
  64. LOG(ERROR) << "Failed to read default fstab";
  65. return;
  66. }
  67. int ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk");
  68. if (ret == -1) {
  69. LOG(ERROR) << "Failed to add /tmp entry to fstab";
  70. fs_mgr_free_fstab(fstab);
  71. fstab = nullptr;
  72. return;
  73. }
  74. // Create a boring /etc/fstab so tools like Busybox work
  75. FILE *file = fopen("/etc/fstab", "w");
  76. if (!file) {
  77. LOG(ERROR) << "Unable to create /etc/fstab";
  78. }
  79. printf("recovery filesystem table\n");
  80. printf("=========================\n");
  81. for (int i = 0; i < fstab->num_entries; ++i) {
  82. const Volume* v = &fstab->recs[i];
  83. printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length);
  84. if (file) {
  85. write_fstab_entry(v, file);
  86. }
  87. }
  88. printf("\n");
  89. if (file) {
  90. fclose(file);
  91. }
  92. }
  93. Volume* volume_for_mount_point(const std::string& mount_point) {
  94. return fs_mgr_get_entry_for_mount_point(fstab, mount_point);
  95. }
  96. // Finds the volume specified by the given path. fs_mgr_get_entry_for_mount_point() does exact match
  97. // only, so it attempts the prefixes recursively (e.g. "/cache/recovery/last_log",
  98. // "/cache/recovery", "/cache", "/" for a given path of "/cache/recovery/last_log") and returns the
  99. // first match or nullptr.
  100. static Volume* volume_for_path(const char* path) {
  101. if (path == nullptr || path[0] == '\0') return nullptr;
  102. std::string str(path);
  103. while (true) {
  104. Volume* result = fs_mgr_get_entry_for_mount_point(fstab, str);
  105. if (result != nullptr || str == "/") {
  106. return result;
  107. }
  108. size_t slash = str.find_last_of('/');
  109. if (slash == std::string::npos) return nullptr;
  110. if (slash == 0) {
  111. str = "/";
  112. } else {
  113. str = str.substr(0, slash);
  114. }
  115. }
  116. return nullptr;
  117. }
  118. Volume* volume_for_label(const char* label) {
  119. int i;
  120. for (i = 0; i < get_num_volumes(); i++) {
  121. Volume* v = get_device_volumes() + i;
  122. if (v->label && !strcmp(v->label, label)) {
  123. return v;
  124. }
  125. }
  126. return nullptr;
  127. }
  128. // Mount the volume specified by path at the given mount_point.
  129. int ensure_path_mounted_at(const char* path, const char* mount_point) {
  130. Volume* v = volume_for_path(path);
  131. if (v == nullptr) {
  132. LOG(ERROR) << "unknown volume for path [" << path << "]";
  133. return -1;
  134. }
  135. if (strcmp(v->fs_type, "ramdisk") == 0) {
  136. // The ramdisk is always mounted.
  137. return 0;
  138. }
  139. if (!scan_mounted_volumes()) {
  140. LOG(ERROR) << "Failed to scan mounted volumes";
  141. return -1;
  142. }
  143. if (!mount_point) {
  144. mount_point = v->mount_point;
  145. }
  146. if (!fs_mgr_is_voldmanaged(v)) {
  147. const MountedVolume* mv = find_mounted_volume_by_mount_point(mount_point);
  148. if (mv) {
  149. // volume is already mounted
  150. return 0;
  151. }
  152. }
  153. fs_mkdirs(mount_point, 0755); // in case it doesn't already exist
  154. if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "squashfs") == 0 ||
  155. strcmp(v->fs_type, "vfat") == 0) {
  156. int result = mount(v->blk_device, mount_point, v->fs_type, v->flags, v->fs_options);
  157. if (result == -1) {
  158. PLOG(ERROR) << "Failed to mount " << mount_point;
  159. return -1;
  160. }
  161. return 0;
  162. }
  163. LOG(ERROR) << "unknown fs_type \"" << v->fs_type << "\" for " << mount_point;
  164. return -1;
  165. }
  166. int ensure_volume_mounted(Volume* v) {
  167. if (v == nullptr) {
  168. LOG(ERROR) << "cannot mount unknown volume";
  169. return -1;
  170. }
  171. return ensure_path_mounted_at(v->mount_point, nullptr);
  172. }
  173. int ensure_path_mounted(const char* path) {
  174. // Mount at the default mount point.
  175. return ensure_path_mounted_at(path, nullptr);
  176. }
  177. int ensure_path_unmounted(const char* path, bool detach /* = false */) {
  178. const Volume* v;
  179. if (memcmp(path, "/storage/", 9) == 0) {
  180. char label[PATH_MAX];
  181. const char* p = path+9;
  182. const char* q = strchr(p, '/');
  183. memset(label, 0, sizeof(label));
  184. if (q) {
  185. memcpy(label, p, q-p);
  186. }
  187. else {
  188. strcpy(label, p);
  189. }
  190. v = volume_for_label(label);
  191. }
  192. else {
  193. v = volume_for_path(path);
  194. }
  195. return ensure_volume_unmounted(v, detach);
  196. }
  197. int ensure_volume_unmounted(const Volume* v, bool detach /* = false */) {
  198. if (v == nullptr) {
  199. LOG(ERROR) << "cannot unmount unknown volume";
  200. return -1;
  201. }
  202. if (strcmp(v->fs_type, "ramdisk") == 0) {
  203. // The ramdisk is always mounted; you can't unmount it.
  204. return -1;
  205. }
  206. if (!scan_mounted_volumes()) {
  207. LOG(ERROR) << "Failed to scan mounted volumes";
  208. return -1;
  209. }
  210. MountedVolume* mv = find_mounted_volume_by_mount_point(v->mount_point);
  211. if (mv == nullptr) {
  212. // Volume is already unmounted.
  213. return 0;
  214. }
  215. return (detach ?
  216. unmount_mounted_volume_detach(mv) :
  217. unmount_mounted_volume(mv));
  218. }
  219. static int exec_cmd(const std::vector<std::string>& args) {
  220. CHECK_NE(static_cast<size_t>(0), args.size());
  221. std::vector<char*> argv(args.size());
  222. std::transform(args.cbegin(), args.cend(), argv.begin(),
  223. [](const std::string& arg) { return const_cast<char*>(arg.c_str()); });
  224. argv.push_back(nullptr);
  225. pid_t child;
  226. if ((child = fork()) == 0) {
  227. execv(argv[0], argv.data());
  228. _exit(EXIT_FAILURE);
  229. }
  230. int status;
  231. waitpid(child, &status, 0);
  232. if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
  233. LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status);
  234. }
  235. return WEXITSTATUS(status);
  236. }
  237. static int64_t get_file_size(int fd, uint64_t reserve_len) {
  238. struct stat buf;
  239. int ret = fstat(fd, &buf);
  240. if (ret) return 0;
  241. int64_t computed_size;
  242. if (S_ISREG(buf.st_mode)) {
  243. computed_size = buf.st_size - reserve_len;
  244. } else if (S_ISBLK(buf.st_mode)) {
  245. uint64_t block_device_size = get_block_device_size(fd);
  246. if (block_device_size < reserve_len ||
  247. block_device_size > std::numeric_limits<int64_t>::max()) {
  248. computed_size = 0;
  249. } else {
  250. computed_size = block_device_size - reserve_len;
  251. }
  252. } else {
  253. computed_size = 0;
  254. }
  255. return computed_size;
  256. }
  257. int format_volume(const char* volume, const char* directory) {
  258. const Volume* v = volume_for_path(volume);
  259. if (v == nullptr) {
  260. LOG(ERROR) << "unknown volume \"" << volume << "\"";
  261. return -1;
  262. }
  263. if (strcmp(v->fs_type, "ramdisk") == 0) {
  264. LOG(ERROR) << "can't format_volume \"" << volume << "\"";
  265. return -1;
  266. }
  267. if (strcmp(v->mount_point, volume) != 0) {
  268. LOG(ERROR) << "can't give path \"" << volume << "\" to format_volume";
  269. return -1;
  270. }
  271. if (ensure_path_unmounted(volume) != 0) {
  272. LOG(ERROR) << "format_volume: Failed to unmount \"" << v->mount_point << "\"";
  273. return -1;
  274. }
  275. if (strcmp(v->fs_type, "ext4") != 0 && strcmp(v->fs_type, "f2fs") != 0) {
  276. LOG(ERROR) << "format_volume: fs_type \"" << v->fs_type << "\" unsupported";
  277. return -1;
  278. }
  279. // If there's a key_loc that looks like a path, it should be a block device for storing encryption
  280. // metadata. Wipe it too.
  281. if (v->key_loc != nullptr && v->key_loc[0] == '/') {
  282. LOG(INFO) << "Wiping " << v->key_loc;
  283. int fd = open(v->key_loc, O_WRONLY | O_CREAT, 0644);
  284. if (fd == -1) {
  285. PLOG(ERROR) << "format_volume: Failed to open " << v->key_loc;
  286. return -1;
  287. }
  288. wipe_block_device(fd, get_file_size(fd));
  289. close(fd);
  290. }
  291. int64_t length = 0;
  292. if (v->length > 0) {
  293. length = v->length;
  294. } else if (v->length < 0 ||
  295. (v->key_loc != nullptr && strcmp(v->key_loc, "footer") == 0)) {
  296. android::base::unique_fd fd(open(v->blk_device, O_RDONLY));
  297. if (fd == -1) {
  298. PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
  299. return -1;
  300. }
  301. length =
  302. get_file_size(fd.get(), v->length ? -v->length : CRYPT_FOOTER_OFFSET);
  303. if (length <= 0) {
  304. LOG(ERROR) << "get_file_size: invalid size " << length << " for "
  305. << v->blk_device;
  306. return -1;
  307. }
  308. }
  309. if (fs_mgr_is_voldmanaged(v)) {
  310. LOG(ERROR) << "can't format vold volume \"" << volume << "\"";
  311. return -1;
  312. }
  313. if (strcmp(v->fs_type, "ext4") == 0) {
  314. static constexpr int kBlockSize = 4096;
  315. std::vector<std::string> mke2fs_args = {
  316. "/sbin/mke2fs_static", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize),
  317. };
  318. int raid_stride = v->logical_blk_size / kBlockSize;
  319. int raid_stripe_width = v->erase_blk_size / kBlockSize;
  320. // stride should be the max of 8KB and logical block size
  321. if (v->logical_blk_size != 0 && v->logical_blk_size < 8192) {
  322. raid_stride = 8192 / kBlockSize;
  323. }
  324. if (v->erase_blk_size != 0 && v->logical_blk_size != 0) {
  325. mke2fs_args.push_back("-E");
  326. mke2fs_args.push_back(
  327. android::base::StringPrintf("stride=%d,stripe-width=%d", raid_stride, raid_stripe_width));
  328. }
  329. mke2fs_args.push_back(v->blk_device);
  330. if (length != 0) {
  331. mke2fs_args.push_back(std::to_string(length / kBlockSize));
  332. }
  333. int result = exec_cmd(mke2fs_args);
  334. if (result == 0 && directory != nullptr) {
  335. std::vector<std::string> e2fsdroid_args = {
  336. "/sbin/e2fsdroid_static",
  337. "-e",
  338. "-f",
  339. directory,
  340. "-a",
  341. volume,
  342. v->blk_device,
  343. };
  344. result = exec_cmd(e2fsdroid_args);
  345. }
  346. if (result != 0) {
  347. PLOG(ERROR) << "format_volume: Failed to make ext4 on " << v->blk_device;
  348. return -1;
  349. }
  350. return 0;
  351. }
  352. // Has to be f2fs because we checked earlier.
  353. static constexpr int kSectorSize = 4096;
  354. std::string cmd("/sbin/mkfs.f2fs");
  355. // clang-format off
  356. std::vector<std::string> make_f2fs_cmd = {
  357. cmd,
  358. "-d1",
  359. "-f",
  360. "-O", "encrypt",
  361. "-O", "quota",
  362. "-O", "verity",
  363. "-w", std::to_string(kSectorSize),
  364. v->blk_device,
  365. };
  366. // clang-format on
  367. if (length >= kSectorSize) {
  368. make_f2fs_cmd.push_back(std::to_string(length / kSectorSize));
  369. }
  370. int result = exec_cmd(make_f2fs_cmd);
  371. if (result == 0 && directory != nullptr) {
  372. cmd = "/sbin/sload.f2fs";
  373. // clang-format off
  374. std::vector<std::string> sload_f2fs_cmd = {
  375. cmd,
  376. "-f", directory,
  377. "-t", volume,
  378. v->blk_device,
  379. };
  380. // clang-format on
  381. result = exec_cmd(sload_f2fs_cmd);
  382. }
  383. if (result != 0) {
  384. PLOG(ERROR) << "format_volume: Failed " << cmd << " on " << v->blk_device;
  385. return -1;
  386. }
  387. return 0;
  388. }
  389. int format_volume(const char* volume) {
  390. return format_volume(volume, nullptr);
  391. }
  392. int setup_install_mounts() {
  393. if (fstab == nullptr) {
  394. LOG(ERROR) << "can't set up install mounts: no fstab loaded";
  395. return -1;
  396. }
  397. for (int i = 0; i < fstab->num_entries; ++i) {
  398. const Volume* v = fstab->recs + i;
  399. // We don't want to do anything with "/".
  400. if (strcmp(v->mount_point, "/") == 0) {
  401. continue;
  402. }
  403. if (strcmp(v->mount_point, "/tmp") == 0 || strcmp(v->mount_point, "/cache") == 0) {
  404. if (ensure_path_mounted(v->mount_point) != 0) {
  405. LOG(ERROR) << "Failed to mount " << v->mount_point;
  406. return -1;
  407. }
  408. } else {
  409. // datam must be unmounted with the detach flag to ensure that FUSE works.
  410. bool detach = false;
  411. if (strcmp(v->mount_point, "/data") == 0) {
  412. detach = true;
  413. }
  414. if (ensure_volume_unmounted(v, detach) != 0) {
  415. LOG(ERROR) << "Failed to unmount " << v->mount_point;
  416. return -1;
  417. }
  418. }
  419. }
  420. return 0;
  421. }