Skip to content

Instantly share code, notes, and snippets.

@lpereira
Created May 9, 2017 05:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lpereira/845fe060ba68a5db95827cbc5496bb6d to your computer and use it in GitHub Desktop.
Save lpereira/845fe060ba68a5db95827cbc5496bb6d to your computer and use it in GitHub Desktop.
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