Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ uboot_env.modified | True if something has modified the U-Boot block and it diff
uboot_env.start | The block offset of the U-Boot environment. (512 byte blocks)
uboot_env.count | The number of blocks in the environment. Defaults to 256.
run_repl | True to run a REPL before booting. This is useful for debug. Defaults to `false`
dm_crypt.n.path | The extra encrypted filesystem path.Where `n` is the index of the extra filesystem.
dm_crypt.n.cipher | The cipher used to encrypt the extra filesystem. Where `n` is the index of the extra filesystem.
dm_crypt.n.secret | The secret key as hex digits for the extra filesystem. Where `n` is the index of the extra filesystem.

_for more information about configuring extra encrypted filesystems see [Mounting extra encrypted filesystems](#mounting-extra-encrypted-file-systems)_

Variables can be overridden using the Linux commandline. See your platform's
bootloader documentation for how to pass options to Linux. At the end of the
Expand Down Expand Up @@ -218,3 +223,22 @@ This is illustrative, but obviously quite insecure. The current route to
obtaining the secret key is to edit the C code to this project to integrate it
with platform-specific way of keeping or hiding secrets. It is hoped that
alternatives can be shared in the future.

### Mounting extra encrypted file systems

If you want to mount more encrypted file systems outside of the `rootfs` you
can use the `dm_crypt` variable to configure the extra filesystems. The
`dm_crypt` variable works using a number to under the `dm_crypt` variable
namespace like so: `dm_crypt.n.path`.

Here's an example configuration file with configuration two more filesystems:

```config
dm_crypt.1.path = "/dev/mmcblk0p3"
dm_crypt.1.cipher = "aes-cbc-plain"
dm_crypt.1.secret = "8e9c0780fd7f5d00c18a30812fe960cfce71f6074dd9cded6aab2897568cc856"

dm_crypt.1.path = "/dev/mmcblk0p4"
dm_crypt.2.cipher = "aes-cbc-plain"
dm_crypt.2.secret = "4e9c781fd7f5d00c18a30812fe970cfce56f6064dd9cded6aab2897575cc861"
```
92 changes: 81 additions & 11 deletions src/nerves_initramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,31 @@
#include "block_device.h"
#include "rootdisk.h"

#define MAX_EXTRA_ENCRYPTED_DEVS 8

// Global U-Boot environment data
struct uboot_env working_uboot_env;

static int losetup(int rootfs_fd)
static int losetup(int rootfs_fd, int loop_ix)
{
char loop_devname[16];
snprintf(loop_devname, sizeof(loop_devname), "/dev/loop%d", loop_ix);

// Assume loop0 is available since who else would be able to take it?
int loop_fd = open("/dev/loop0", O_RDONLY);
int loop_fd = open(loop_devname, O_RDONLY);
if (loop_fd < 0)
fatal("Enable CONFIG_BLK_DEV_LOOP in kernel");
fatal("Enable CONFIG_BLK_DEV_LOOP in kernel and check that at least %d loop devices", loop_ix + 1);

OK_OR_FATAL(ioctl(loop_fd, LOOP_SET_FD, rootfs_fd), "LOOP_SET_FD failed");

return loop_fd;
}

static int dm_create(off_t rootfs_blocks, const char *cipher, const char *secret)
static int dm_create(int map_ix,
const char *name,
off_t rootfs_blocks,
const char *cipher,
const char *secret)
{
int dm_control = open("/dev/mapper/control", O_RDWR);

Expand All @@ -54,8 +63,8 @@ static int dm_create(off_t rootfs_blocks, const char *cipher, const char *secret
dm->flags = 0;
dm->event_nr = 0;
dm->dev = 0;
strcpy(dm->name, "rootfs");
strcpy(dm->uuid, "CRYPT-PLAIN-rootfs");
strcpy(dm->name, name);
snprintf(dm->uuid, sizeof(dm->uuid), "CRYPT-PLAIN-%s", name);

OK_OR_FATAL(ioctl(dm_control, DM_DEV_CREATE, request_buffer), "Enable CONFIG_DM_CRYPT in kernel");

Expand All @@ -69,13 +78,13 @@ static int dm_create(off_t rootfs_blocks, const char *cipher, const char *secret
dm->open_count = 0;
dm->flags = DM_SECURE_DATA_FLAG;
dm->dev = 0;
strcpy(dm->name, "rootfs");
strcpy(dm->name, name);
struct dm_target_spec *target = (struct dm_target_spec *) &request_buffer[dm->data_start];
memset(target, 0, sizeof(struct dm_target_spec));
target->sector_start = 0;
target->length = rootfs_blocks;
strcpy(target->target_type, "crypt");
sprintf((char *) &request_buffer[dm->data_start + sizeof(struct dm_target_spec)], "%s %s 0 /dev/loop0 0", cipher, secret);
sprintf((char *) &request_buffer[dm->data_start + sizeof(struct dm_target_spec)], "%s %s %d /dev/loop%d 0", cipher, secret, map_ix, map_ix);
OK_OR_FATAL(ioctl(dm_control, DM_TABLE_LOAD, request_buffer), "Check CONFIG_DM_CRYPT and crypto algs enabled");


Expand All @@ -87,7 +96,7 @@ static int dm_create(off_t rootfs_blocks, const char *cipher, const char *secret
dm->data_start = sizeof(struct dm_ioctl);
dm->target_count = 0;
dm->flags = DM_SECURE_DATA_FLAG;
strcpy(dm->name, "rootfs");
strcpy(dm->name, name);
OK_OR_FATAL(ioctl(dm_control, DM_DEV_SUSPEND, request_buffer), "DM_DEV_SUSPEND failed");

close(dm_control);
Expand Down Expand Up @@ -208,17 +217,77 @@ static void mount_encrypted_fs(const char *rootfs_path, const char *rootfs_type,

off_t rootfs_blocks = rootfs_size / block_size;

int loop_fd = losetup(rootfs_fd);
int loop_fd = losetup(rootfs_fd, 0);
close(rootfs_fd);

dm_create(rootfs_blocks, cipher, secret);
dm_create(0, "rootfs", rootfs_blocks, cipher, secret);

OK_OR_FATAL(mount("/dev/dm-0", "/mnt", rootfs_type, MS_RDONLY, NULL), "Expecting %s filesystem on %s", rootfs_type, rootfs_path);

// It's ok to close loop_fd now that the mount happened.
close(loop_fd);
}

static void map_encrypted_device(int map_ix, const char *spec, const char *name, const char *cipher, const char *secret)
{
// Wait for the device to appear
char path[BLOCK_DEVICE_PATH_LEN];
int fd = open_block_device(spec, O_RDONLY, path);
off_t size = lseek(fd, 0, SEEK_END);
(void) lseek(fd, 0, SEEK_SET);

int loop_fd = losetup(fd, map_ix);
close(fd);

char dm_name[16];
snprintf(dm_name, sizeof(dm_name), "/dev/dm-%d", map_ix);

char link_name[32];
snprintf(link_name, sizeof(link_name), "/dev/mapper/%s", name);

dm_create(map_ix, name, size, cipher, secret);

OK_OR_WARN(symlink(link_name, dm_name), "Could not symlink %s -> %s", link_name, dm_name);

// Hmmmmm.... It's ok to close loop_fd now that the mount happened.
close(loop_fd);
}

static void map_extra_encrypted_devs()
{
for (int ix = 1; ix <= MAX_EXTRA_ENCRYPTED_DEVS; ix++) {
char base[12];
snprintf(base, sizeof(base), "dm_crypt.%d", ix);

char path_var[20];
char name_var[20];
char cipher_var[20];
char secret_var[20];

snprintf(path_var, sizeof(path_var), "%s.path", base);
snprintf(name_var, sizeof(name_var), "%s.name", base);
snprintf(cipher_var, sizeof(cipher_var), "%s.cipher", base);
snprintf(secret_var, sizeof(secret_var), "%s.secret", base);

const char *path = get_variable_as_string(path_var);
const char *name = get_variable_as_string(name_var);
const char *cipher = get_variable_as_string(cipher_var);
const char *secret = get_variable_as_string(secret_var);

if (*path != '\0') {
if (*name == '\0' ||
*cipher == '\0' ||
*secret == '\0') {
info("Not mapping %s. Make sure that %s.name, %s.cipher, and %s.secret are set",
path, base, base, base);
continue;
}
info("mapping other encrypted block device %s", path);
map_encrypted_device(ix, path, name, cipher, secret);
}
}
}

static void repl()
{
// Reset the terminal colors
Expand Down Expand Up @@ -324,6 +393,7 @@ int main(int argc, char *argv[])

// Finalize our setup of the root filesystem
create_rootdisk_symlinks(resolved_rootfs_path);
map_extra_encrypted_devs();

// Switch over to the new root filesystem
switch_root();
Expand Down
1 change: 1 addition & 0 deletions tests/001_all_defaults
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fixture: mount("sysfs", "/sys", "sysfs", 14, data)
fixture: mount("proc", "/proc", "proc", 14, data)
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/002_encrypted_fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fixture: ioctl(DM_TABLE_LOAD, data_size=16384, data_start=312, target_count=1, o
fixture: ioctl(DM_DEV_SUSPEND, data_size=16384, data_start=312, target_count=0, open_count=0, flags=32768, event_nr=0, dev=0x0, name=rootfs, uuid=
fixture: mount("/dev/dm-0", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/003_cmdline_override
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ fixture: mount("sysfs", "/sys", "sysfs", 14, data)
fixture: mount("proc", "/proc", "proc", 14, data)
fixture: mount("/dev/mmcblk0p2", "/mnt", "myfstype", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/004_bool_logic
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ true || !false == true
!false || false == true
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/005_arithmetic_operators
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Parentheses in arithmetic operations changes the order
0 is false
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
2 changes: 2 additions & 0 deletions tests/006_blkid
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ fixture: mount("proc", "/proc", "proc", 14, data)
/dev/mmcblk0p1: PARTUUID="5278721d-0089-4768-85df-b8f1b97e6684"
/dev/mmcblk0p2: PARTUUID="fcc205c8-2f1c-4dcd-bef4-7b209aa15cca"
/dev/mmcblk0p5: PARTUUID="7e7b6f06-8aaf-42c6-9c3b-6ede014885a6"
/dev/mmcblk0p6: PARTUUID="14e534d0-7adc-4b8e-a208-460104c3c24a"
/dev/mmcblk0: DISKUUID="b443fbeb-2c93-481b-88b3-0ecb0aeba911"
/dev/sda1: PARTUUID="3fc3e2d4-01"
/dev/sda2: PARTUUID="3fc3e2d4-02"
/dev/sda: DISKUUID="3fc3e2d4"
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/007_find_gpt_rootfs_by_uuid
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fixture: mount("sysfs", "/sys", "sysfs", 14, data)
fixture: mount("proc", "/proc", "proc", 14, data)
fixture: mount("/dev/mmcblk0p5", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/009_exec_fwup
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fixture: mount("proc", "/proc", "proc", 14, data)
Hello from fwup: a b c
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/010_read_from_exec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fixture: mount("proc", "/proc", "proc", 14, data)
Result is ABC1234567
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/011_exec_ignores_error_exit
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ nerves_initramfs: Ignoring non-zero exit from /usr/bin/faulty_program
Result is Oops
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/012_ls
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ ls /usr
bin <DIR>
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/013_uboot_setenv
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ newvar=hello
Found newvar
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/017_sleep
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fixture: mount("proc", "/proc", "proc", 14, data)
fixture: usleep(1000000)
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
1 change: 1 addition & 0 deletions tests/018_readfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ print(r)

fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
Expand Down
56 changes: 56 additions & 0 deletions tests/019_extra_encrypted_devices
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/sh

#
# Test adding 1 or more encrypted devices
#

cat >$CONFIG <<EOF
dm_crypt.1.path = "/dev/mmcblk0p5"
dm_crypt.1.name = "app"
dm_crypt.1.cipher = "aes-cbc-plain"
dm_crypt.1.secret = "8e9c0780fd7f5d00c18a30812fe960cfce71f6074dd9cded6aab2897568cc856"

dm_crypt.2.path = "/dev/mmcblk0p6"
dm_crypt.2.name = "provisioning"
dm_crypt.2.cipher = "aes-cbc-plain"
dm_crypt.2.secret = "4e9c781fd7f5d00c18a30812fe970cfce56f6064dd9cded6aab2897575cc861"
EOF


cat >$EXPECTED <<EOF
fixture: mkdir("/mnt", 755)
fixture: mkdir("/dev", 755)
fixture: mkdir("/sys", 555)
fixture: mkdir("/proc", 555)
fixture: mount("devtmpfs", "/dev", "devtmpfs", 10, data)
fixture: mount("sysfs", "/sys", "sysfs", 14, data)
fixture: mount("proc", "/proc", "proc", 14, data)
fixture: mount("/dev/mmcblk0p2", "/mnt", "squashfs", 1, data)
fixture: symlink("/dev/mmcblk0","/dev/rootdisk0")
fixture: symlink("/dev/mmcblk0p6","/dev/rootdisk0p6")
fixture: symlink("/dev/mmcblk0p5","/dev/rootdisk0p5")
fixture: symlink("/dev/mmcblk0p2","/dev/rootdisk0p2")
fixture: symlink("/dev/mmcblk0p1","/dev/rootdisk0p1")
nerves_initramfs: mapping other encrypted block device /dev/mmcblk0p5
fixture: ioctl(LOOP_SET_FD)
fixture: ioctl(DM_DEV_CREATE, data_size=16384, data_start=312, target_count=0, open_count=0, flags=0, event_nr=0, dev=0x0, name=app, uuid=CRYPT-PLAIN-app
fixture: ioctl(DM_TABLE_LOAD, data_size=16384, data_start=312, target_count=1, open_count=0, flags=32768, event_nr=0, dev=0x0, name=app, uuid=, target=0,327680,crypt (aes-cbc-plain 8e9c0780fd7f5d00c18a30812fe960cfce71f6074dd9cded6aab2897568cc856 1 /dev/loop1 0)
fixture: ioctl(DM_DEV_SUSPEND, data_size=16384, data_start=312, target_count=0, open_count=0, flags=32768, event_nr=0, dev=0x0, name=app, uuid=
fixture: symlink("/dev/mapper/app", "/dev/dm-1")
nerves_initramfs: mapping other encrypted block device /dev/mmcblk0p6
fixture: ioctl(LOOP_SET_FD)
fixture: ioctl(DM_DEV_CREATE, data_size=16384, data_start=312, target_count=0, open_count=0, flags=0, event_nr=0, dev=0x0, name=provisioning, uuid=CRYPT-PLAIN-provisioning
fixture: ioctl(DM_TABLE_LOAD, data_size=16384, data_start=312, target_count=1, open_count=0, flags=32768, event_nr=0, dev=0x0, name=provisioning, uuid=, target=0,393216,crypt (aes-cbc-plain 4e9c781fd7f5d00c18a30812fe970cfce56f6064dd9cded6aab2897575cc861 2 /dev/loop2 0)
fixture: ioctl(DM_DEV_SUSPEND, data_size=16384, data_start=312, target_count=0, open_count=0, flags=32768, event_nr=0, dev=0x0, name=provisioning, uuid=
fixture: symlink("/dev/mapper/provisioning", "/dev/dm-2")
fixture: mount("/dev", "/mnt/dev", "(null)", 8192, data)
fixture: umount("/sys")
fixture: umount("/proc")
fixture: unlinkat("bin", AT_REMOVEDIR)
fixture: unlinkat("usr", AT_REMOVEDIR)
fixture: rmdir("/sys")
fixture: rmdir("/proc")
fixture: mount(".", "/", "(null)", 8192, data)
fixture: chroot(.)
Hello from the chained /sbin/init
EOF
Binary file modified tests/gpt-disk.img
Binary file not shown.
Loading