From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from userp1040.oracle.com ([156.151.31.81]:24938 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757879AbcIMNir (ORCPT ); Tue, 13 Sep 2016 09:38:47 -0400 From: Anand Jain To: linux-btrfs@vger.kernel.org Cc: clm@fb.com, dsterba@suse.cz Subject: [PATCH 2/2] btrfs-progs: add encryption support Date: Tue, 13 Sep 2016 21:39:49 +0800 Message-Id: <1473773990-3071-4-git-send-email-anand.jain@oracle.com> In-Reply-To: <1473773990-3071-1-git-send-email-anand.jain@oracle.com> References: <1473773990-3071-1-git-send-email-anand.jain@oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-btrfs-owner@vger.kernel.org List-ID: Based on v4.7.2 Depends on keyctl-utils and libscrypt packages. Signed-off-by: Anand Jain --- Makefile.in | 5 +- btrfs-list.c | 23 +++ cmds-filesystem.c | 4 +- cmds-restore.c | 16 ++ cmds-subvolume.c | 101 +++++++++++- commands.h | 1 + ctree.h | 5 +- encrypt.c | 455 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ encrypt.h | 46 ++++++ props.c | 4 + utils.h | 1 + 11 files changed, 654 insertions(+), 7 deletions(-) create mode 100644 encrypt.c create mode 100644 encrypt.h diff --git a/Makefile.in b/Makefile.in index fd68b3eeeba7..6e857b763213 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,8 @@ DISABLE_BTRFSCONVERT = @DISABLE_BTRFSCONVERT@ BTRFSCONVERT_EXT2 = @BTRFSCONVERT_EXT2@ EXTRA_CFLAGS := -EXTRA_LDFLAGS := +# asj fixme, remove path hardcode +EXTRA_LDFLAGS := /usr/lib/libscrypt.so.0 /usr/lib/libkeyutils.so DEBUG_CFLAGS_DEFAULT = -O0 -U_FORTIFY_SOURCE -ggdb3 DEBUG_CFLAGS_INTERNAL = @@ -87,7 +88,7 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ extent-cache.o extent_io.o volumes.o utils.o repair.o \ qgroup.o raid6.o free-space-cache.o list_sort.o props.o \ ulist.o qgroup-verify.o backref.o string-table.o task-utils.o \ - inode.o file.o find-root.o free-space-tree.o help.o + inode.o file.o find-root.o free-space-tree.o help.o encrypt.o cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \ cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \ cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \ diff --git a/btrfs-list.c b/btrfs-list.c index 4e67fe28b9b5..34722731b652 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -1923,3 +1923,26 @@ int wait_for_commit(int fd) return ret; return ioctl(fd, BTRFS_IOC_WAIT_SYNC, NULL); } + +/* + * Fixme: A kind of workaround as of now, actual fix needs + * per subvol sync instead of entire FS. + */ +int wait_for_commit_subvol(char *subvol) +{ + int fd; + int ret; + DIR *ds; + + fd = open_file_or_dir3(subvol, &ds, O_RDWR); + if (fd == -1) { + ret = -errno; + fprintf(stderr, "ERROR: open '%s' failed: %s\n", + subvol, strerror(-ret)); + return ret; + } + + ret = wait_for_commit(fd); + close_file_or_dir(fd, ds); + return ret; +} diff --git a/cmds-filesystem.c b/cmds-filesystem.c index 76ea82edf23c..4a866c28420a 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -952,6 +952,8 @@ static int parse_compress_type(char *s) return BTRFS_COMPRESS_ZLIB; else if (strcmp(optarg, "lzo") == 0) return BTRFS_COMPRESS_LZO; + else if (strcmp(optarg, "ctr(aes)") == 0) + return BTRFS_ENCRYPT_AES; else { error("unknown compression type %s", s); exit(1); @@ -964,7 +966,7 @@ static const char * const cmd_filesystem_defrag_usage[] = { "", "-v be verbose", "-r defragment files recursively", - "-c[zlib,lzo] compress the file while defragmenting", + "-c[zlib,lzo,ctr(aes)] compress/encrypt the file while defragmenting if it wasn't", "-f flush data to disk immediately after defragmenting", "-s start defragment only from byte onward", "-l len defragment only up to len bytes", diff --git a/cmds-restore.c b/cmds-restore.c index b491f083b72b..bed0aba77740 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -155,6 +155,19 @@ static int decompress_lzo(struct btrfs_root *root, unsigned char *inbuf, return 0; } +static int decrypt_ctr_aes(struct btrfs_root *root, unsigned char *inbuf, + char *outbuf, u64 compress_len, u64 *decompress_len) +{ + /* + * fixme: This is only for testing, which works only with + * kernel option BTRFS_CRYPTO_TEST_BYDUMMYENC, where + * ciphertext == plaintext + */ + memcpy(outbuf, inbuf, compress_len); + *decompress_len = compress_len; + return 0; +} + static int decompress(struct btrfs_root *root, char *inbuf, char *outbuf, u64 compress_len, u64 *decompress_len, int compress) { @@ -165,6 +178,9 @@ static int decompress(struct btrfs_root *root, char *inbuf, char *outbuf, case BTRFS_COMPRESS_LZO: return decompress_lzo(root, (unsigned char *)inbuf, outbuf, compress_len, decompress_len); + case BTRFS_ENCRYPT_AES: + return decrypt_ctr_aes(root, (unsigned char *)inbuf, outbuf, + compress_len, decompress_len); default: break; } diff --git a/cmds-subvolume.c b/cmds-subvolume.c index 5df7af56c7f8..452e71755d39 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "kerncompat.h" #include "ioctl.h" @@ -36,6 +38,7 @@ #include "commands.h" #include "utils.h" #include "btrfs-list.h" +#include "encrypt.h" static int is_subvolume_cleaned(int fd, u64 subvolid) { @@ -104,13 +107,14 @@ static const char * const subvolume_cmd_group_usage[] = { }; static const char * const cmd_subvol_create_usage[] = { - "btrfs subvolume create [-i ] [/]", + "btrfs subvolume create [-i ] [-e ] [/]", "Create a subvolume", "Create a subvolume in . If is not given", "subvolume will be created in the current directory.", "", "-i add the newly created subvolume to a qgroup. This", " option can be given multiple times.", + "-e enable encryption", NULL }; @@ -125,9 +129,11 @@ static int cmd_subvol_create(int argc, char **argv) char *dst; struct btrfs_qgroup_inherit *inherit = NULL; DIR *dirstream = NULL; + int encrypt = 0; + char *cipher_name = NULL; while (1) { - int c = getopt(argc, argv, "c:i:v"); + int c = getopt(argc, argv, "e:c:i:v"); if (c < 0) break; @@ -146,6 +152,16 @@ static int cmd_subvol_create(int argc, char **argv) goto out; } break; + case 'e': + encrypt = 1; + if (!is_encryption_type_supported(optarg)) { + error("Unsupported cipher '%s', check '/proc/crypto'\n", + optarg); + retval = -EPROTONOSUPPORT; + goto out; + } + cipher_name = strdup(optarg); + break; default: usage(cmd_subvol_create_usage); } @@ -212,6 +228,13 @@ static int cmd_subvol_create(int argc, char **argv) goto out; } + if (encrypt) { + res = btrfs_set_subvol_encrypt(dst, cipher_name); + if (res) + warning("Subvol is created, but failed to enable encryption: %s\n", + strerror(-res)); + } + retval = 0; /* success */ out: close_file_or_dir(fddst, dirstream); @@ -901,6 +924,9 @@ static int cmd_subvol_show(int argc, char **argv) int fd = -1; int ret = 1; DIR *dirstream1 = NULL; + key_serial_t key_serial; + char key_algo[BTRFS_KEY_ALGO_MAX_LEN + 1]; + char key_tag[BTRFS_KEY_TAG_MAX_LEN + 1]; clean_args_no_options(argc, argv, cmd_subvol_show_usage); @@ -978,6 +1004,23 @@ static int cmd_subvol_show(int argc, char **argv) else printf("\tFlags: \t\t\t-\n"); + key_serial = 0; + memset(key_algo, '\0', BTRFS_KEY_ALGO_MAX_LEN + 1); + memset(key_tag, '\0', BTRFS_KEY_TAG_MAX_LEN + 1); + + ret = btrfs_subvol_key_info(fullpath, key_algo, key_tag, &key_serial); + if (strlen(key_tag)) { + char key_state[256] = {0}; + if (key_serial == -1) + snprintf(key_state, 256, "(%s)", strerror(-ret)); + else + snprintf(key_state, 256, "(%d)", key_serial); + + printf("\tEncryption: \t\t%s@%s %s\n", key_algo, key_tag, key_state); + } else { + printf("\tEncryption: \t\t%s\n", "none"); + } + /* print the snapshots of the given subvol if any*/ printf("\tSnapshot(s):\n"); filter_set = btrfs_list_alloc_filter_set(); @@ -1005,6 +1048,59 @@ out: return !!ret; } +static const char * const cmd_subvol_encrypt_usage[] = { + "btrfs subvolume encrypt