logo

bootstrap-initrd

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

init.c (2612B)


  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 "loksh_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. if(waitpid(child, NULL, 0) == -1)
  32. {
  33. fprintf(stderr, "Failed waiting for child of pid %d: %s\n", child, strerror(errno));
  34. return -1;
  35. }
  36. return 0;
  37. }
  38. static int
  39. build_loksh()
  40. {
  41. chdir("/loksh-7.5");
  42. fprintf(stderr, "Compiling loksh-7.5\n");
  43. if(exec_wait(loksh_tcc_cmd) < 0) return -1;
  44. fprintf(stderr, "Compiled loksh !\n");
  45. return 0;
  46. }
  47. int
  48. main(int argc, char *argv[])
  49. {
  50. setenv("PATH", "/bin:/usr/bin:/usr/local/bin", 1);
  51. setenv("HOME", "/root", 1);
  52. setenv("LOGNAME", "root", 1);
  53. if(build_loksh() < 0) return 1;
  54. if(mount("sysfs", "/sys", "sysfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, NULL) < 0)
  55. fprintf(stderr, "Failed to mount /sys: %s\n", strerror(errno));
  56. if(mount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, "hidepid=2") <
  57. 0)
  58. fprintf(stderr, "Failed to mount /proc: %s\n", strerror(errno));
  59. if(mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID | MS_NOEXEC, NULL) < 0)
  60. fprintf(stderr, "Failed to mount /proc: %s\n", strerror(errno));
  61. errno = 0;
  62. if(mknod("/dev/null", S_IFCHR | 0666, makedev(0x1, 0x3)) < 0)
  63. {
  64. if(errno != 0 && errno != EEXIST)
  65. fprintf(stderr, "Failed to create /dev/null: %s\n", strerror(errno));
  66. }
  67. // PS1 shouldn't be exported but '\h\$ ' is an *awful* default
  68. // and oksh also doesn't sources ksh-specific files by default
  69. setenv("PS1", "$? $PWD # ", 1);
  70. fprintf(stderr, "Launching: /bin/loksh /init.sh\n");
  71. if(execl("/bin/loksh", "/bin/loksh", "/init.sh", (char *)0) < 0)
  72. {
  73. fprintf(stderr, "Failed to execute: %s\n", strerror(errno));
  74. return 1;
  75. }
  76. fprintf(stderr, "Unreachable\n");
  77. }