add -c to cmd_unlock, to check if a device needs to be unlocked

This commit is contained in:
Kent Overstreet 2018-02-11 12:35:15 -05:00
parent b5e3302af7
commit 813862a47c
6 changed files with 109 additions and 8 deletions

View File

@ -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

View File

@ -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();
opt_set(opts, noexcl, true);
opt_set(opts, nochanges, true);
struct bch_sb_handle sb;
char *passphrase;
if (argc != 2)
die("Please supply a single device");
int ret = bch2_read_super(argv[1], &opts, &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));
passphrase = read_passphrase("Enter passphrase: ");
if (!bch2_sb_is_encrypted(sb.sb))
die("%s is not encrypted", dev);
if (check)
exit(EXIT_SUCCESS);
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)));

View File

@ -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)

View File

@ -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 *);

18
initramfs/hook Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions

25
initramfs/script Executable file
View File

@ -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