From 7f4191a202ea4558ca2d5eb8a47daea33c9999c7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 11 Dec 2016 14:45:48 -0900 Subject: [PATCH] add support for maximum journal entry size also rip out prototype crypto support code - real code is in the dev branch, with the new superblock format --- Makefile | 11 ++-- bcache-format.c | 32 +++--------- bcache-key.c | 52 ------------------- bcache-ondisk.h | 16 +----- bcache.c | 4 -- bcache.h | 1 - crypto.c | 132 ------------------------------------------------ crypto.h | 24 --------- libbcache.c | 29 ++++------- libbcache.h | 2 +- util.c | 27 +++++----- util.h | 8 ++- 12 files changed, 50 insertions(+), 288 deletions(-) delete mode 100644 bcache-key.c delete mode 100644 crypto.c delete mode 100644 crypto.h diff --git a/Makefile b/Makefile index 5c5ea5fc..e11f6060 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ LDFLAGS+=-static PKGCONFIG_LIBS="blkid uuid" CFLAGS+=`pkg-config --cflags ${PKGCONFIG_LIBS}` -LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lscrypt -lsodium -lkeyutils -lm +LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lm ifeq ($(PREFIX),/usr) ROOT_SBINDIR=/sbin @@ -24,7 +24,7 @@ libccan.a: $(CCANOBJS) $(AR) r $@ $(CCANOBJS) bcache-objs = bcache.o bcache-assemble.o bcache-device.o bcache-format.o\ - bcache-fs.o bcache-run.o bcache-key.o libbcache.o crypto.o util.o + bcache-fs.o bcache-run.o libbcache.o util.o -include $(bcache-objs:.o=.d) @@ -44,4 +44,9 @@ clean: .PHONY: deb deb: all - debuild -nc -us -uc -i -I + debuild --unsigned-source \ + --unsigned-changes \ + --no-pre-clean \ + --build=binary \ + --diff-ignore \ + --tar-ignore diff --git a/bcache-format.c b/bcache-format.c index 1b20b551..ca04433e 100644 --- a/bcache-format.c +++ b/bcache-format.c @@ -26,7 +26,6 @@ #include "bcache.h" #include "libbcache.h" -#include "crypto.h" /* Open a block device, do magic blkid stuff: */ static int open_for_format(const char *dev, bool force) @@ -80,9 +79,9 @@ static void usage(void) " --metadata_checksum_type=(none|crc32c|crc64)\n" " --data_checksum_type=(none|crc32c|crc64)\n" " --compression_type=(none|lz4|gzip)\n" - " --encrypted\n" " --error_action=(continue|readonly|panic)\n" " Action to take on filesystem error\n" + " --max_journal_entry_size=size\n" " -l, --label=label\n" " --uuid=uuid\n" " -f, --force\n" @@ -108,8 +107,8 @@ static void usage(void) OPT(0, metadata_checksum_type, required_argument) \ OPT(0, data_checksum_type, required_argument) \ OPT(0, compression_type, required_argument) \ - OPT(0, encrypted, no_argument) \ OPT('e', error_action, required_argument) \ + OPT(0, max_journal_entry_size, required_argument) \ OPT('L', label, required_argument) \ OPT('U', uuid, required_argument) \ OPT('f', force, no_argument) \ @@ -144,7 +143,6 @@ int cmd_format(int argc, char *argv[]) unsigned meta_csum_type = BCH_CSUM_CRC32C; unsigned data_csum_type = BCH_CSUM_CRC32C; unsigned compression_type = BCH_COMPRESSION_NONE; - bool encrypted = false; unsigned on_error_action = BCH_ON_ERROR_RO; char *label = NULL; uuid_le uuid; @@ -155,6 +153,7 @@ int cmd_format(int argc, char *argv[]) unsigned bucket_size = 0; unsigned tier = 0; bool discard = false; + unsigned max_journal_entry_size = 0; char *passphrase = NULL; int opt; @@ -187,14 +186,15 @@ int cmd_format(int argc, char *argv[]) compression_type = read_string_list_or_die(optarg, compression_types, "compression type"); break; - case Opt_encrypted: - encrypted = true; - break; case Opt_error_action: case 'e': on_error_action = read_string_list_or_die(optarg, error_actions, "error action"); break; + case Opt_max_journal_entry_size: + max_journal_entry_size = hatoi_validate(optarg, + "journal entry size"); + break; case Opt_label: case 'L': label = strdup(optarg); @@ -242,22 +242,6 @@ int cmd_format(int argc, char *argv[]) if (uuid_is_null(uuid.b)) uuid_generate(uuid.b); - if (encrypted) { - char *pass2; - - passphrase = read_passphrase("Enter passphrase: "); - pass2 = read_passphrase("Enter same passphrase again: "); - - if (strcmp(passphrase, pass2)) { - memzero_explicit(passphrase, strlen(passphrase)); - memzero_explicit(pass2, strlen(pass2)); - die("Passphrases do not match"); - } - - memzero_explicit(pass2, strlen(pass2)); - free(pass2); - } - darray_foreach(dev, devices) dev->fd = open_for_format(dev->path, force); @@ -267,10 +251,10 @@ int cmd_format(int argc, char *argv[]) meta_csum_type, data_csum_type, compression_type, - passphrase, 1, 1, on_error_action, + max_journal_entry_size, label, uuid); diff --git a/bcache-key.c b/bcache-key.c deleted file mode 100644 index 3cd6d09c..00000000 --- a/bcache-key.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include - -#include "bcache.h" -#include "libbcache.h" -#include "crypto.h" - -int cmd_unlock(int argc, char *argv[]) -{ - struct bcache_disk_key disk_key; - struct bcache_key key; - struct cache_sb *sb; - char *passphrase; - char uuid[40]; - char description[60]; - - if (argc != 2) - die("please supply a single device"); - - sb = bcache_super_read(argv[1]); - - if (!CACHE_SET_ENCRYPTION_KEY(sb)) - die("filesystem is not encrypted"); - - memcpy(&disk_key, sb->encryption_key, sizeof(disk_key)); - - if (!memcmp(&disk_key, bch_key_header, sizeof(bch_key_header))) - die("filesystem does not have encryption key"); - - passphrase = read_passphrase("Enter passphrase: "); - - derive_passphrase(&key, passphrase); - disk_key_encrypt(sb, &disk_key, &key); - - if (memcmp(&disk_key, bch_key_header, sizeof(bch_key_header))) - die("incorrect passphrase"); - - uuid_unparse_lower(sb->user_uuid.b, uuid); - sprintf(description, "bcache:%s", uuid); - - if (add_key("logon", description, &key, sizeof(key), - KEY_SPEC_USER_KEYRING) < 0) - die("add_key error: %s", strerror(errno)); - - memzero_explicit(&disk_key, sizeof(disk_key)); - memzero_explicit(&key, sizeof(key)); - memzero_explicit(passphrase, strlen(passphrase)); - free(passphrase); - return 0; -} diff --git a/bcache-ondisk.h b/bcache-ondisk.h index f737511f..c141923c 100644 --- a/bcache-ondisk.h +++ b/bcache-ondisk.h @@ -813,21 +813,7 @@ LE64_BITMASK(CACHE_SET_ROOT_RESERVE, struct cache_sb, flags2, 0, 6); */ LE64_BITMASK(CACHE_SET_CLEAN, struct cache_sb, flags2, 6, 7); -/* - * If nonzero, encryption is enabled; overrides DATA/META_CSUM_TYPE. Also - * indicates encryption algorithm in use, if/when we get more than one: - * - */ -LE64_BITMASK(CACHE_SET_ENCRYPTION_TYPE, struct cache_sb, flags2, 6, 10); - -/* - * If nonzero, we have an encryption key in the superblock, which is the key - * used to encrypt all other data/metadata. The key will normally be encrypted - * with the key userspace provides, but if encryption has been turned off we'll - * just store the master key unencrypted in the superblock so we can access the - * previously encrypted data. - */ -LE64_BITMASK(CACHE_SET_ENCRYPTION_KEY, struct cache_sb, flags2, 10, 11); +LE64_BITMASK(CACHE_SET_JOURNAL_ENTRY_SIZE, struct cache_sb, flags2, 7, 15); /* options: */ diff --git a/bcache.c b/bcache.c index 04955b34..177ef529 100644 --- a/bcache.c +++ b/bcache.c @@ -30,7 +30,6 @@ static void usage(void) "\n" "Commands for formatting, startup and shutdown\n" " format Format a new filesystem\n" - " unlock Unlock an encrypted filesystem prior to running/mounting\n" " assemble Assemble an existing multi device filesystem\n" " incremental Incrementally assemble an existing multi device filesystem\n" " run Start a partially assembled filesystem\n" @@ -84,9 +83,6 @@ int main(int argc, char *argv[]) if (!strcmp(cmd, "device_remove")) return cmd_device_remove(argc, argv); - if (!strcmp(cmd, "unlock")) - return cmd_unlock(argc, argv); - usage(); return 0; } diff --git a/bcache.h b/bcache.h index 949f6094..7ad53e79 100644 --- a/bcache.h +++ b/bcache.h @@ -11,7 +11,6 @@ int cmd_format(int argc, char *argv[]); -int cmd_unlock(int argc, char *argv[]); int cmd_assemble(int argc, char *argv[]); int cmd_incremental(int argc, char *argv[]); int cmd_run(int argc, char *argv[]); diff --git a/crypto.c b/crypto.c deleted file mode 100644 index e98e4867..00000000 --- a/crypto.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "crypto.h" - -char *read_passphrase(const char *prompt) -{ - struct termios old, new; - char *buf = NULL; - size_t buflen = 0; - - fprintf(stderr, "%s", prompt); - fflush(stderr); - - if (tcgetattr(fileno(stdin), &old)) - die("error getting terminal attrs"); - - new = old; - new.c_lflag &= ~ECHO; - if (tcsetattr(fileno(stdin), TCSAFLUSH, &new)) - die("error setting terminal attrs"); - - if (getline(&buf, &buflen, stdin) <= 0) - die("error reading passphrase"); - - tcsetattr(fileno(stdin), TCSAFLUSH, &old); - fprintf(stderr, "\n"); - return buf; -} - -void derive_passphrase(struct bcache_key *key, const char *passphrase) -{ - const unsigned char salt[] = "bcache"; - int ret; - - ret = libscrypt_scrypt((void *) passphrase, strlen(passphrase), - salt, sizeof(salt), - SCRYPT_N, SCRYPT_r, SCRYPT_p, - (void *) key, sizeof(*key)); - if (ret) - die("scrypt error: %i", ret); -} - -void disk_key_encrypt(struct cache_sb *sb, - struct bcache_disk_key *disk_key, - struct bcache_key *key) -{ - __le32 nonce[2]; - int ret; - - memcpy(nonce, &sb->set_magic, sizeof(sb->set_magic)); - - ret = crypto_stream_chacha20_xor((void *) disk_key, - (void *) disk_key, sizeof(*disk_key), - (void *) nonce, - (void *) key); - if (ret) - die("chacha20 error: %i", ret); -} - -void disk_key_init(struct bcache_disk_key *disk_key) -{ - ssize_t ret; - - memcpy(&disk_key->header, bch_key_header, sizeof(bch_key_header)); -#if 0 - ret = getrandom(disk_key->key, sizeof(disk_key->key), GRND_RANDOM); - if (ret != sizeof(disk_key->key)) - die("error getting random bytes for key"); -#else - int fd = open("/dev/random", O_RDONLY|O_NONBLOCK); - if (fd < 0) - die("error opening /dev/random"); - - size_t n = 0; - struct timespec start; - bool printed = false; - - clock_gettime(CLOCK_MONOTONIC, &start); - - while (n < sizeof(disk_key->key)) { - struct timeval timeout = { 1, 0 }; - fd_set set; - - FD_ZERO(&set); - FD_SET(fd, &set); - - if (select(fd + 1, &set, NULL, NULL, &timeout) < 0) - die("select error"); - - ret = read(fd, - (void *) disk_key->key + n, - sizeof(disk_key->key) - n); - if (ret == -1 && errno != EINTR && errno != EAGAIN) - die("error reading from /dev/random"); - if (ret > 0) - n += ret; - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - now.tv_sec -= start.tv_sec; - now.tv_nsec -= start.tv_nsec; - - while (now.tv_nsec < 0) { - long nsec_per_sec = 1000 * 1000 * 1000; - long sec = now.tv_nsec / nsec_per_sec - 1; - now.tv_nsec -= sec * nsec_per_sec; - now.tv_sec += sec; - } - - if (!printed && now.tv_sec >= 3) { - printf("Reading from /dev/random is taking a long time...\n)"); - printed = true; - } - } - close(fd); -#endif -} diff --git a/crypto.h b/crypto.h deleted file mode 100644 index f4f7ff8e..00000000 --- a/crypto.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _CRYPTO_H -#define _CRYPTO_H - -#include "util.h" - -struct bcache_key { - u64 key[4]; -}; - -struct bcache_disk_key { - u64 header; - u64 key[4]; -}; - -static const char bch_key_header[8] = BCACHE_MASTER_KEY_HEADER; -static const struct nonce bch_master_key_nonce = BCACHE_MASTER_KEY_NONCE; - -char *read_passphrase(const char *); -void derive_passphrase(struct bcache_key *, const char *); -void disk_key_encrypt(struct cache_sb *sb, struct bcache_disk_key *, - struct bcache_key *); -void disk_key_init(struct bcache_disk_key *); - -#endif /* _CRYPTO_H */ diff --git a/libbcache.c b/libbcache.c index 9bc41ac1..5b2cac5b 100644 --- a/libbcache.c +++ b/libbcache.c @@ -15,7 +15,6 @@ #include "bcache-ondisk.h" #include "libbcache.h" -#include "crypto.h" const char * const cache_state[] = { "active", @@ -125,10 +124,10 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs, unsigned meta_csum_type, unsigned data_csum_type, unsigned compression_type, - const char *passphrase, unsigned meta_replicas, unsigned data_replicas, unsigned on_error_action, + unsigned max_journal_entry_size, char *label, uuid_le uuid) { @@ -191,6 +190,13 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs, btree_node_size = min(btree_node_size, i->bucket_size); } + if (!max_journal_entry_size) { + /* 2 MB default: */ + max_journal_entry_size = 4096; + } + + max_journal_entry_size = roundup_pow_of_two(max_journal_entry_size); + sb = calloc(1, sizeof(*sb) + sizeof(struct cache_member) * nr_devs); sb->offset = __cpu_to_le64(SB_SECTOR); @@ -221,22 +227,7 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs, SET_CACHE_SET_DATA_REPLICAS_HAVE(sb, data_replicas); SET_CACHE_SET_ERROR_ACTION(sb, on_error_action); SET_CACHE_SET_STR_HASH_TYPE(sb, BCH_STR_HASH_SIPHASH); - - if (passphrase) { - struct bcache_key key; - struct bcache_disk_key disk_key; - - derive_passphrase(&key, passphrase); - disk_key_init(&disk_key); - disk_key_encrypt(sb, &disk_key, &key); - - memcpy(sb->encryption_key, &disk_key, sizeof(disk_key)); - SET_CACHE_SET_ENCRYPTION_TYPE(sb, 1); - SET_CACHE_SET_ENCRYPTION_KEY(sb, 1); - - memzero_explicit(&disk_key, sizeof(disk_key)); - memzero_explicit(&key, sizeof(key)); - } + SET_CACHE_SET_JOURNAL_ENTRY_SIZE(sb, ilog2(max_journal_entry_size)); for (i = devs; i < devs + nr_devs; i++) { struct cache_member *m = sb->members + (i - devs); @@ -286,6 +277,7 @@ void bcache_super_print(struct cache_sb *sb, int units) "Version: %llu\n" "Block_size: %s\n" "Btree node size: %s\n" + "Max journal entry size: %s\n" "Error action: %s\n" "Clean: %llu\n" @@ -308,6 +300,7 @@ void bcache_super_print(struct cache_sb *sb, int units) le64_to_cpu(sb->version), pr_units(le16_to_cpu(sb->block_size), units).b, pr_units(CACHE_SET_BTREE_NODE_SIZE(sb), units).b, + pr_units(1U << CACHE_SET_JOURNAL_ENTRY_SIZE(sb), units).b, CACHE_SET_ERROR_ACTION(sb) < BCH_NR_ERROR_ACTIONS ? error_actions[CACHE_SET_ERROR_ACTION(sb)] diff --git a/libbcache.h b/libbcache.h index 920a9c51..9dfc6471 100644 --- a/libbcache.h +++ b/libbcache.h @@ -31,10 +31,10 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs, unsigned meta_csum_type, unsigned data_csum_type, unsigned compression_type, - const char *passphrase, unsigned meta_replicas, unsigned data_replicas, unsigned on_error_action, + unsigned max_journal_entry_size, char *label, uuid_le uuid); diff --git a/util.c b/util.c index 73d35f72..1bab7daf 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -21,23 +22,13 @@ /* Integer stuff: */ -u64 rounddown_pow_of_two(u64 n) -{ - u64 ret; - - do { - ret = n; - n &= n - 1; - } while (n); - - return ret; -} - unsigned ilog2(u64 n) { unsigned ret = 0; - while (n) { + assert(n > 0); + + while (n > 1) { ret++; n >>= 1; } @@ -45,6 +36,16 @@ unsigned ilog2(u64 n) return ret; } +u64 rounddown_pow_of_two(u64 n) +{ + return 1ULL << ilog2(n); +} + +u64 roundup_pow_of_two(u64 n) +{ + return 1ULL << (ilog2(n - 1) + 1); +} + char *skip_spaces(const char *str) { while (isspace(*str)) diff --git a/util.h b/util.h index 5ac3acdf..b5ea071f 100644 --- a/util.h +++ b/util.h @@ -58,14 +58,20 @@ static inline void le64_add_cpu(__le64 *var, u64 val) (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; }) + #define die(arg, ...) \ do { \ fprintf(stderr, arg "\n", ##__VA_ARGS__); \ exit(EXIT_FAILURE); \ } while (0) -u64 rounddown_pow_of_two(u64); unsigned ilog2(u64); +u64 rounddown_pow_of_two(u64); +u64 roundup_pow_of_two(u64); char *skip_spaces(const char *str); char *strim(char *s);