extroot.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License version 2.1
  6. * as published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <sys/mount.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <sys/wait.h>
  21. #include <libgen.h>
  22. #include "libfstools.h"
  23. /*
  24. * This will execute "block extroot" and make use of mounted extroot or return
  25. * an error.
  26. */
  27. int mount_extroot(char const *extroot_prefix)
  28. {
  29. char ldlib_path[32];
  30. char block_path[32];
  31. char kmod_loader[64];
  32. struct stat s;
  33. pid_t pid;
  34. /* try finding the library directory */
  35. snprintf(ldlib_path, sizeof(ldlib_path), "%s/upper/lib", extroot_prefix);
  36. if (stat(ldlib_path, &s) || !S_ISDIR(s.st_mode))
  37. snprintf(ldlib_path, sizeof(ldlib_path), "%s/lib", extroot_prefix);
  38. /* try finding the block executable */
  39. snprintf(block_path, sizeof(block_path), "%s/upper/sbin/block", extroot_prefix);
  40. if (stat(block_path, &s) || !S_ISREG(s.st_mode))
  41. snprintf(block_path, sizeof(block_path), "%s/sbin/block", extroot_prefix);
  42. if (stat(block_path, &s) || !S_ISREG(s.st_mode))
  43. snprintf(block_path, sizeof(block_path), "/sbin/block");
  44. if (stat(block_path, &s) || !S_ISREG(s.st_mode))
  45. return -1;
  46. /* set LD_LIBRARY_PATH env var and load kmods from overlay if we found a lib directory there */
  47. if (!stat(ldlib_path, &s) && S_ISDIR(s.st_mode)) {
  48. ULOG_INFO("loading kmods from internal overlay\n");
  49. setenv("LD_LIBRARY_PATH", ldlib_path, 1);
  50. snprintf(kmod_loader, sizeof(kmod_loader),
  51. "/sbin/kmodloader %s/etc/modules-boot.d/", dirname(ldlib_path));
  52. if (system(kmod_loader))
  53. ULOG_ERR("failed to launch kmodloader from internal overlay\n");
  54. }
  55. pid = fork();
  56. if (!pid) {
  57. mkdir("/tmp/extroot", 0755);
  58. execl(block_path, block_path, "extroot", NULL);
  59. exit(-1);
  60. } else if (pid > 0) {
  61. int status;
  62. waitpid(pid, &status, 0);
  63. if (!WEXITSTATUS(status)) {
  64. if (find_mount("/tmp/extroot/mnt")) {
  65. mount("/dev/root", "/", NULL, MS_NOATIME | MS_REMOUNT | MS_RDONLY, 0);
  66. mkdir("/tmp/extroot/mnt/proc", 0755);
  67. mkdir("/tmp/extroot/mnt/dev", 0755);
  68. mkdir("/tmp/extroot/mnt/sys", 0755);
  69. mkdir("/tmp/extroot/mnt/tmp", 0755);
  70. mkdir("/tmp/extroot/mnt/rom", 0755);
  71. if (mount_move("/tmp/extroot", "", "/mnt")) {
  72. ULOG_ERR("moving pivotroot failed - continue normal boot\n");
  73. umount("/tmp/extroot/mnt");
  74. } else if (pivot("/mnt", "/rom")) {
  75. ULOG_ERR("switching to pivotroot failed - continue normal boot\n");
  76. umount("/mnt");
  77. } else {
  78. umount("/tmp/overlay");
  79. rmdir("/tmp/overlay");
  80. rmdir("/tmp/extroot/mnt");
  81. rmdir("/tmp/extroot");
  82. return 0;
  83. }
  84. } else if (find_mount("/tmp/extroot/overlay")) {
  85. if (mount_move("/tmp/extroot", "", "/overlay")) {
  86. ULOG_ERR("moving extroot failed - continue normal boot\n");
  87. umount("/tmp/extroot/overlay");
  88. } else if (fopivot("/overlay", "/rom")) {
  89. ULOG_ERR("switching to extroot failed - continue normal boot\n");
  90. umount("/overlay");
  91. } else {
  92. umount("/tmp/overlay");
  93. rmdir("/tmp/overlay");
  94. rmdir("/tmp/extroot/overlay");
  95. rmdir("/tmp/extroot");
  96. return 0;
  97. }
  98. }
  99. }
  100. }
  101. return -1;
  102. }