summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-02-11 12:35:15 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-02-11 14:25:33 -0500
commit813862a47ca866082ca3002441df6c13b47f1b0d (patch)
tree958f71d7d77b3840ab70d25c54616141b32a69d6
parentb5e3302af7fd5e91ffab9567a6837a69398d5287 (diff)
add -c to cmd_unlock, to check if a device needs to be unlocked
-rw-r--r--Makefile5
-rw-r--r--cmd_key.c58
-rw-r--r--crypto.c8
-rw-r--r--crypto.h1
-rwxr-xr-xinitramfs/hook18
-rwxr-xr-xinitramfs/script25
6 files changed, 108 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 075257b..e773b46 100644
--- a/Makefile
+++ b/Makefile
@@ -37,8 +37,10 @@ LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` \
ifeq ($(PREFIX),/usr)
ROOT_SBINDIR=/sbin
+ INITRAMFS_DIR=$(PREFIX)/share/initramfs-tools
else
ROOT_SBINDIR=$(PREFIX)/sbin
+ INITRAMFS_DIR=/etc/initramfs-tools
endif
.PHONY: all
@@ -58,6 +60,9 @@ install: bcachefs
$(INSTALL) -m0755 bcachefs $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 fsck.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 mkfs.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
+ $(INSTALL) -m0755 -D initramfs/hook $(DESTDIR)$(INITRAMFS_DIR)/hooks/bcachefs
+ echo "copy_exec $(ROOT_SBINDIR)/bcachefs /sbin/bcachefs" >> $(DESTDIR)$(INITRAMFS_DIR)/hooks/bcachefs
+ $(INSTALL) -m0755 -D initramfs/script $(DESTDIR)$(INITRAMFS_DIR)/scripts/local-premount/bcachefs
$(INSTALL) -m0644 bcachefs.8 $(DESTDIR)$(PREFIX)/share/man/man8/
.PHONY: clean
diff --git a/cmd_key.c b/cmd_key.c
index e670b50..0ca591c 100644
--- a/cmd_key.c
+++ b/cmd_key.c
@@ -7,23 +7,61 @@
#include "crypto.h"
#include "libbcachefs.h"
+static void unlock_usage(void)
+{
+ puts("bcachefs unlock - unlock an encrypted filesystem so it can be mounted\n"
+ "Usage: bcachefs unlock [OPTION] device\n"
+ "\n"
+ "Options:\n"
+ " -c Check if a device is encrypted\n"
+ " -h Display this help and exit\n"
+ "Report bugs to <linux-bcache@vger.kernel.org>");
+}
+
int cmd_unlock(int argc, char *argv[])
{
+ bool check = false;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "ch")) != -1)
+ switch (opt) {
+ case 'c':
+ check = true;
+ break;
+ case 'h':
+ unlock_usage();
+ exit(EXIT_SUCCESS);
+ }
+ args_shift(optind);
+
+ char *dev = arg_pop();
+ if (!dev)
+ die("Please supply a device");
+
+ if (argc)
+ die("Too many arguments");
+
struct bch_opts opts = bch2_opts_empty();
- struct bch_sb_handle sb;
- char *passphrase;
- if (argc != 2)
- die("Please supply a single device");
+ opt_set(opts, noexcl, true);
+ opt_set(opts, nochanges, true);
- int ret = bch2_read_super(argv[1], &opts, &sb);
+ struct bch_sb_handle sb;
+ int ret = bch2_read_super(dev, &opts, &sb);
if (ret)
- die("Error opening %s: %s", argv[1], strerror(-ret));
+ die("Error opening %s: %s", dev, strerror(-ret));
+
+ if (!bch2_sb_is_encrypted(sb.sb))
+ die("%s is not encrypted", dev);
+
+ if (check)
+ exit(EXIT_SUCCESS);
- passphrase = read_passphrase("Enter passphrase: ");
+ char *passphrase = read_passphrase("Enter passphrase: ");
bch2_add_key(sb.sb, passphrase);
+ bch2_free_super(&sb);
memzero_explicit(passphrase, strlen(passphrase));
free(passphrase);
return 0;
@@ -38,6 +76,12 @@ int cmd_set_passphrase(int argc, char *argv[])
die("Please supply one or more devices");
opt_set(opts, nostart, true);
+
+ /*
+ * we use bch2_fs_open() here, instead of just reading the superblock,
+ * to make sure we're opening and updating every component device:
+ */
+
c = bch2_fs_open(argv + 1, argc - 1, opts);
if (IS_ERR(c))
die("Error opening %s: %s", argv[1], strerror(-PTR_ERR(c)));
diff --git a/crypto.c b/crypto.c
index 0e18b36..7f7fbd5 100644
--- a/crypto.c
+++ b/crypto.c
@@ -100,6 +100,14 @@ struct bch_key derive_passphrase(struct bch_sb_field_crypt *crypt,
return key;
}
+bool bch2_sb_is_encrypted(struct bch_sb *sb)
+{
+ struct bch_sb_field_crypt *crypt;
+
+ return (crypt = bch2_sb_get_crypt(sb)) &&
+ bch2_key_is_encrypted(&crypt->key);
+}
+
void bch2_passphrase_check(struct bch_sb *sb, const char *passphrase,
struct bch_key *passphrase_key,
struct bch_encrypted_key *sb_key)
diff --git a/crypto.h b/crypto.h
index d6c2061..7f523c0 100644
--- a/crypto.h
+++ b/crypto.h
@@ -12,6 +12,7 @@ char *read_passphrase(const char *);
char *read_passphrase_twice(const char *);
struct bch_key derive_passphrase(struct bch_sb_field_crypt *, const char *);
+bool bch2_sb_is_encrypted(struct bch_sb *);
void bch2_passphrase_check(struct bch_sb *, const char *,
struct bch_key *, struct bch_encrypted_key *);
void bch2_add_key(struct bch_sb *, const char *);
diff --git a/initramfs/hook b/initramfs/hook
new file mode 100755
index 0000000..aa91469
--- /dev/null
+++ b/initramfs/hook
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+. /usr/share/initramfs-tools/hook-functions
+
diff --git a/initramfs/script b/initramfs/script
new file mode 100755
index 0000000..bd64b41
--- /dev/null
+++ b/initramfs/script
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+# Check if it needs unlocking:
+if bcachefs unlock -c $ROOT >/dev/null 2>&1; then
+ echo "Unlocking $ROOT:"
+
+ while true; do
+ bcachefs unlock $ROOT && break
+ done
+fi