diff --git a/src/cryptsetup.c b/src/cryptsetup.c | |
index 8920c1e..f945764 100644 | |
--- a/src/cryptsetup.c | |
+++ b/src/cryptsetup.c | |
@@ -23,6 +23,13 @@ | |
#include "cryptsetup.h" | |
+#include <linux/kexec.h> | |
+#include <linux/reboot.h> | |
+#include <sys/mount.h> | |
+#include <sys/reboot.h> | |
+#include <sys/syscall.h> | |
+#include <unistd.h> | |
+ | |
static const char *opt_cipher = NULL; | |
static const char *opt_hash = NULL; | |
static int opt_verify_passphrase = 0; | |
@@ -1513,7 +1520,7 @@ static int run_action(struct action_type *action) | |
return translate_errno(r); | |
} | |
-int main(int argc, const char **argv) | |
+static int cryptsetup_main(int argc, const char **argv) | |
{ | |
static char *popt_tmp; | |
static struct poptOption popt_help_options[] = { | |
@@ -1827,3 +1834,90 @@ int main(int argc, const char **argv) | |
poptFreeContext(popt_context); | |
return r; | |
} | |
+ | |
+static long kexec_file_load(int kfd, int ifd, unsigned long cmdline_len, | |
+ const char *cmdline, unsigned long flags) | |
+{ | |
+ return syscall(SYS_kexec_file_load, kfd, ifd, cmdline_len, cmdline, flags); | |
+} | |
+ | |
+int main(int argc, char *argv[]) | |
+{ | |
+ static const char *open_boot_part_args[] = { | |
+ "/usr/bin/cryptsetup", | |
+ "open", | |
+ "--type", | |
+ "luks", | |
+ "/dev/sda1", | |
+ "bootpart", | |
+ }; | |
+ static const char cmdline[] = "quiet root=/dev/sda6 rw"; | |
+ static const int rw_mount_flags = MS_NOSUID | MS_NOEXEC; | |
+ static const int ro_mount_flags = MS_NOSUID | MS_NOEXEC | MS_RDONLY; | |
+ int initrd_fd, vmlinuz_fd; | |
+ | |
+ if (mkdir("/proc", 0755) < 0) { | |
+ printf("Could not create /proc mount point\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (mount("proc", "/proc", "proc", rw_mount_flags, NULL) < 0) { | |
+ printf("Could not mount /proc partition\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (mount("dev", "/dev", "devtmpfs", rw_mount_flags, NULL) < 0) { | |
+ printf("Could not mount /dev partition\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (cryptsetup_main(sizeof(open_boot_part_args)/sizeof(open_boot_part_args[0]), | |
+ open_boot_part_args) != EXIT_SUCCESS) { | |
+ printf("Could not open boot partition\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (mkdir("/boot", 0755) < 0) { | |
+ printf("Could not create /boot mount point\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (mount("/dev/mapper/bootpart", "/boot", "ext4", ro_mount_flags, NULL) < 0) { | |
+ printf("Could not mount /boot partition\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ initrd_fd = open("/boot/initrd-linux.img", O_RDONLY | O_CLOEXEC); | |
+ if (initrd_fd < 0) { | |
+ printf("Could not open initrd\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ vmlinuz_fd = open("/boot/vmlinuz-linux", O_RDONLY | O_CLOEXEC); | |
+ if (vmlinuz_fd < 0) { | |
+ printf("Could not open vmlinuz\n"); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ if (kexec_file_load(vmlinuz_fd, initrd_fd, | |
+ sizeof(cmdline), cmdline, 0) < 0) { | |
+ | |
+ printf("Could not kexec: %s\n", strerror(errno)); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+ } | |
+ | |
+ reboot(LINUX_REBOOT_CMD_KEXEC); | |
+ | |
+ printf("kexec failed: %s\n", strerror(errno)); | |
+ sleep(5); | |
+ return EXIT_FAILURE; | |
+} | |
diff --git a/src/utils_password.c b/src/utils_password.c | |
index 0366b16..32ccae0 100644 | |
--- a/src/utils_password.c | |
+++ b/src/utils_password.c | |
@@ -20,6 +20,7 @@ | |
*/ | |
#include "cryptsetup.h" | |
+#include <sys/time.h> | |
#include <termios.h> | |
int opt_force_password = 0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment