logo

bootstrap-initrd

Linux initrd to bootstrap from a small binary seed git clone https://anongit.hacktivis.me/git/bootstrap-initrd.git/

init.c (2686B)


  1. // bootstrap-initrd: Linux initrd to bootstrap from a small binary seed
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #define _XOPEN_SOURCE 700 // mknod
  6. #include "src/oksh_tcc.h"
  7. #include <errno.h>
  8. #include <fcntl.h> // O_RDONLY
  9. #include <spawn.h> // posix_spawn
  10. #include <stdio.h> // fprintf
  11. #include <stdlib.h> // setenv
  12. #include <string.h> // strerror
  13. #include <sys/mount.h>
  14. #include <sys/stat.h> // mknod
  15. #include <sys/sysmacros.h> // makedev
  16. #include <sys/wait.h> // waitpid
  17. #include <unistd.h> // chdir, environ
  18. /* From SUS Chapter 8: Environment variable */
  19. extern char **environ;
  20. static int
  21. exec_wait(char *args[])
  22. {
  23. pid_t child = 0;
  24. // Allows to avoid a fork+exec
  25. int ret = posix_spawn(&child, args[0], NULL, NULL, args, environ);
  26. if(ret != 0)
  27. {
  28. fprintf(stderr, "Failed spawning command with argv[0] = '%s': %s\n", args[0], strerror(errno));
  29. return -1;
  30. }
  31. int stat;
  32. if(waitpid(child, &stat, 0) == -1)
  33. {
  34. fprintf(stderr, "Failed waiting for child of pid %d: %s\n", child, strerror(errno));
  35. return -1;
  36. }
  37. if(!WIFEXITED(stat))
  38. {
  39. fprintf(stderr, "'%s' did not exit normally\n", args[0]);
  40. return -1;
  41. }
  42. if(WEXITSTATUS(stat) != 0)
  43. {
  44. fprintf(stderr, "'%s' exited with code %d\n", args[0], WEXITSTATUS(stat));
  45. return -1;
  46. }
  47. return 0;
  48. }
  49. static int
  50. build_oksh()
  51. {
  52. chdir("/src/oksh-oksh-7.8");
  53. fprintf(stderr, "Compiling oksh-7.8\n");
  54. if(exec_wait(oksh_tcc_cmd) < 0) return -1;
  55. fprintf(stderr, "Compiled oksh !\n");
  56. return 0;
  57. }
  58. int
  59. main(int argc, char *argv[])
  60. {
  61. setenv("PATH", "/bin:/usr/bin:/usr/local/bin", 1);
  62. setenv("HOME", "/root", 1);
  63. setenv("LOGNAME", "root", 1);
  64. if(build_oksh() < 0) return 1;
  65. if(mount("sysfs", "/sys", "sysfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, NULL) < 0)
  66. fprintf(stderr, "Failed to mount /sys: %s\n", strerror(errno));
  67. if(mount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, "hidepid=2") <
  68. 0)
  69. fprintf(stderr, "Failed to mount /proc: %s\n", strerror(errno));
  70. if(mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID | MS_NOEXEC, NULL) < 0)
  71. fprintf(stderr, "Failed to mount /proc: %s\n", strerror(errno));
  72. errno = 0;
  73. if(mknod("/dev/null", S_IFCHR | 0666, makedev(0x1, 0x3)) < 0)
  74. {
  75. if(errno != 0 && errno != EEXIST)
  76. fprintf(stderr, "Failed to create /dev/null: %s\n", strerror(errno));
  77. }
  78. fprintf(stderr, "Launching: /bin/oksh /init.sh\n");
  79. if(execl("/bin/oksh", "-sh", "/init.sh", (char *)0) < 0)
  80. {
  81. fprintf(stderr, "Failed to execute: %s\n", strerror(errno));
  82. return 1;
  83. }
  84. fprintf(stderr, "Unreachable\n");
  85. }