All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] btrfs-progs: add encryption support
@ 2022-09-06  0:01 Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs Sweet Tea Dorminy
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

This changeset is a minimal set of changes to adapt to the kernel-side
changes for encryption in [1].

While the kernel-shared files could be updated to use fscrypt_names in
closer analogue to the kernel versions of the files, that is planned as
a followup.

[1] https://lore.kernel.org/linux-btrfs/cover.1662420176.git.sweettea-kernel@dorminy.me

Changelog: 

v2:
  - updated to match kernel changeset's fscrypt extent contexts and
    changed format storing encrypted context length.
v1: 
  - https://lore.kernel.org/linux-btrfs/cover.1660729916.git.sweettea-kernel@dorminy.me

Sweet Tea Dorminy (6):
  btrfs-progs: add fscrypt support to mkfs.
  btrfs-progs: update to match renamed dir_type
  btrfs-progs: interpret encrypted file extents.
  btrfs-progs: handle fscrypt context items
  btrfs-progs: escape unprintable characters in names
  btrfs-progs: check: update inline extent length checking

 check/main.c               | 32 ++++++++++---------
 check/mode-common.c        |  4 +--
 check/mode-lowmem.c        |  6 ++--
 cmds/restore.c             |  2 +-
 common/fsfeatures.c        | 10 ++++++
 kernel-shared/ctree.h      | 51 +++++++++++++++++++++++++++---
 kernel-shared/dir-item.c   |  8 ++---
 kernel-shared/fscrypt.h    | 27 ++++++++++++++++
 kernel-shared/inode.c      |  4 ++-
 kernel-shared/print-tree.c | 64 +++++++++++++++++++++++++++++++++++---
 libbtrfsutil/btrfs.h       |  2 ++
 libbtrfsutil/btrfs_tree.h  |  3 ++
 12 files changed, 178 insertions(+), 35 deletions(-)
 create mode 100644 kernel-shared/fscrypt.h

-- 
2.35.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs.
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  2022-09-09 11:39   ` David Sterba
  2022-09-06  0:01 ` [PATCH 2/6] btrfs-progs: update to match renamed dir_type Sweet Tea Dorminy
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

Add a new experimental option to allow use of encryption.

Arguably, since older kernels can technically read non-encrypted parts
of an encrypted filesystem, perhaps this doesn't need to be an incompat
feature.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 common/fsfeatures.c   | 10 ++++++++++
 kernel-shared/ctree.h |  4 +++-
 libbtrfsutil/btrfs.h  |  2 ++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index 90704959..ea185a3c 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -143,6 +143,16 @@ static const struct btrfs_feature mkfs_features[] = {
 		.desc		= "new extent tree format"
 	},
 #endif
+	{
+		.name		= "encrypt",
+		.flag		= BTRFS_FEATURE_INCOMPAT_FSCRYPT,
+		.sysfs_name	= "fscrypt",
+		VERSION_TO_STRING2(compat, 5,19),
+		VERSION_NULL(safe),
+		VERSION_NULL(default),
+		.desc		= "fs-level encryption"
+	},
+
 	/* Keep this one last */
 	{
 		.name = "list-all",
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index be39448f..e464f399 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -515,6 +515,7 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
 #define BTRFS_FEATURE_INCOMPAT_RAID1C34		(1ULL << 11)
 #define BTRFS_FEATURE_INCOMPAT_ZONED		(1ULL << 12)
 #define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2	(1ULL << 13)
+#define BTRFS_FEATURE_INCOMPAT_FSCRYPT		(1ULL << 14)
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
 
@@ -544,7 +545,8 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
 	 BTRFS_FEATURE_INCOMPAT_RAID1C34 |		\
 	 BTRFS_FEATURE_INCOMPAT_METADATA_UUID |		\
 	 BTRFS_FEATURE_INCOMPAT_ZONED |			\
-	 BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2)
+	 BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 |	\
+	 BTRFS_FEATURE_INCOMPAT_FSCRYPT)
 #else
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
 	(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |		\
diff --git a/libbtrfsutil/btrfs.h b/libbtrfsutil/btrfs.h
index 0d863d58..3d67f251 100644
--- a/libbtrfsutil/btrfs.h
+++ b/libbtrfsutil/btrfs.h
@@ -277,6 +277,8 @@ struct btrfs_ioctl_fs_info_args {
 #define BTRFS_FEATURE_INCOMPAT_RAID1C34		(1ULL << 11)
 #define BTRFS_FEATURE_INCOMPAT_ZONED		(1ULL << 12)
 
+#define BTRFS_FEATURE_INCOMPAT_FSCRYPT		(1ULL << 14)
+
 struct btrfs_ioctl_feature_flags {
 	__u64 compat_flags;
 	__u64 compat_ro_flags;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] btrfs-progs: update to match renamed dir_type
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 3/6] btrfs-progs: interpret encrypted file extents Sweet Tea Dorminy
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

For directories with encrypted files/filenames, we store a flag
indicating this fact in the top bit of dir_type. Since it's now a
combination of type and flags, we rename it to dir_flags to reflect its
new usage.

The new flag, FT_FSCRYPT, indicates a (perhaps partially) encrypted
directory, which is orthogonal to file type; therefore, add the new
flag, and make conversion from directory type to file type strip the
flag.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 check/main.c               |  4 ++--
 check/mode-common.c        |  4 ++--
 check/mode-lowmem.c        |  6 +++---
 cmds/restore.c             |  2 +-
 common/fsfeatures.c        |  2 +-
 kernel-shared/ctree.h      | 21 ++++++++++++++++++---
 kernel-shared/dir-item.c   |  8 ++++----
 kernel-shared/inode.c      |  4 +++-
 kernel-shared/print-tree.c |  2 +-
 libbtrfsutil/btrfs_tree.h  |  3 +++
 10 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/check/main.c b/check/main.c
index c3359574..3b133105 100644
--- a/check/main.c
+++ b/check/main.c
@@ -1421,7 +1421,7 @@ static int process_dir_item(struct extent_buffer *eb,
 		btrfs_dir_item_key_to_cpu(eb, di, &location);
 		name_len = btrfs_dir_name_len(eb, di);
 		data_len = btrfs_dir_data_len(eb, di);
-		filetype = btrfs_dir_type(eb, di);
+		filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(eb, di));
 
 		rec->found_size += name_len;
 		if (cur + sizeof(*di) + name_len > total ||
@@ -2125,7 +2125,7 @@ static int add_missing_dir_index(struct btrfs_root *root,
 	disk_key.offset = 0;
 
 	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
-	btrfs_set_dir_type(leaf, dir_item, imode_to_type(rec->imode));
+	btrfs_set_dir_flags(leaf, dir_item, imode_to_type(rec->imode));
 	btrfs_set_dir_data_len(leaf, dir_item, 0);
 	btrfs_set_dir_name_len(leaf, dir_item, backref->namelen);
 	name_ptr = (unsigned long)(dir_item + 1);
diff --git a/check/mode-common.c b/check/mode-common.c
index b867c350..0c5c7d6d 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -754,7 +754,7 @@ static int find_file_type_dir_index(struct btrfs_root *root, u64 ino, u64 dirid,
 	if (location.objectid != ino || location.type != BTRFS_INODE_ITEM_KEY ||
 	    location.offset != 0)
 		goto out;
-	filetype = btrfs_dir_type(path.nodes[0], di);
+	filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(path.nodes[0], di));
 	if (filetype >= BTRFS_FT_MAX || filetype == BTRFS_FT_UNKNOWN)
 		goto out;
 	len = min_t(u32, BTRFS_NAME_LEN,
@@ -813,7 +813,7 @@ static int find_file_type_dir_item(struct btrfs_root *root, u64 ino, u64 dirid,
 		    location.type != BTRFS_INODE_ITEM_KEY ||
 		    location.offset != 0)
 			continue;
-		filetype = btrfs_dir_type(path.nodes[0], di);
+		filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(path.nodes[0], di));
 		if (filetype >= BTRFS_FT_MAX || filetype == BTRFS_FT_UNKNOWN)
 			continue;
 		len = min_t(u32, BTRFS_NAME_LEN,
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index db650ae7..6ab709ea 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -857,7 +857,7 @@ loop:
 		    location.offset != 0)
 			goto next;
 
-		filetype = btrfs_dir_type(node, di);
+		filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(node, di));
 		if (file_type != filetype)
 			goto next;
 
@@ -955,7 +955,7 @@ static int find_dir_item(struct btrfs_root *root, struct btrfs_key *key,
 		    location.offset != location_key->offset)
 			goto next;
 
-		filetype = btrfs_dir_type(node, di);
+		filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(node, di));
 		if (file_type != filetype)
 			goto next;
 
@@ -1745,7 +1745,7 @@ begin:
 		(*size) += name_len;
 		read_extent_buffer(node, namebuf, (unsigned long)(di + 1),
 				   len);
-		filetype = btrfs_dir_type(node, di);
+		filetype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(node, di));
 
 		if (di_key->type == BTRFS_DIR_ITEM_KEY &&
 		    di_key->offset != btrfs_name_hash(namebuf, len)) {
diff --git a/cmds/restore.c b/cmds/restore.c
index b517c30c..84cc0724 100644
--- a/cmds/restore.c
+++ b/cmds/restore.c
@@ -991,7 +991,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
 		name_len = btrfs_dir_name_len(leaf, dir_item);
 		read_extent_buffer(leaf, filename, name_ptr, name_len);
 		filename[name_len] = '\0';
-		type = btrfs_dir_type(leaf, dir_item);
+		type = btrfs_dir_flags_to_ftype(btrfs_dir_flags(leaf, dir_item));
 		btrfs_dir_item_key_to_cpu(leaf, dir_item, &location);
 
 		/* full path from root of btrfs being restored */
diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index ea185a3c..cc143026 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -147,7 +147,7 @@ static const struct btrfs_feature mkfs_features[] = {
 		.name		= "encrypt",
 		.flag		= BTRFS_FEATURE_INCOMPAT_FSCRYPT,
 		.sysfs_name	= "fscrypt",
-		VERSION_TO_STRING2(compat, 5,19),
+		VERSION_TO_STRING2(compat, 5, 19),
 		VERSION_NULL(safe),
 		VERSION_NULL(default),
 		.desc		= "fs-level encryption"
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index e464f399..d8f81610 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -176,6 +176,14 @@ enum btrfs_csum_type {
 #define BTRFS_FT_XATTR		8
 #define BTRFS_FT_MAX		9
 
+/* Name is encrypted */
+#define BTRFS_FT_FSCRYPT_NAME	0x80
+
+static inline __u8 btrfs_dir_flags_to_ftype(__u8 flags)
+{
+	return flags & ~BTRFS_FT_FSCRYPT_NAME;
+}
+
 #define BTRFS_ROOT_SUBVOL_RDONLY	(1ULL << 0)
 
 /*
@@ -561,7 +569,8 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
 	 BTRFS_FEATURE_INCOMPAT_NO_HOLES |		\
 	 BTRFS_FEATURE_INCOMPAT_RAID1C34 |		\
 	 BTRFS_FEATURE_INCOMPAT_METADATA_UUID |		\
-	 BTRFS_FEATURE_INCOMPAT_ZONED)
+	 BTRFS_FEATURE_INCOMPAT_ZONED|			\
+	 BTRFS_FEATURE_INCOMPAT_FSCRYPT)
 #endif
 
 /*
@@ -2059,15 +2068,21 @@ BTRFS_SETGET_STACK_FUNCS(stack_root_ref_name_len, struct btrfs_root_ref, name_le
 
 /* struct btrfs_dir_item */
 BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
-BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
+BTRFS_SETGET_FUNCS(dir_flags, struct btrfs_dir_item, type, 8);
 BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
 BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
 
 BTRFS_SETGET_STACK_FUNCS(stack_dir_data_len, struct btrfs_dir_item, data_len, 16);
-BTRFS_SETGET_STACK_FUNCS(stack_dir_type, struct btrfs_dir_item, type, 8);
+BTRFS_SETGET_STACK_FUNCS(stack_dir_flags, struct btrfs_dir_item, type, 8);
 BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item, name_len, 16);
 BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item, transid, 64);
 
+static inline __u8 btrfs_dir_ftype(const struct extent_buffer *eb,
+				 const struct btrfs_dir_item *item)
+{
+	return btrfs_dir_flags_to_ftype(btrfs_dir_flags(eb, item));
+}
+
 static inline void btrfs_dir_item_key(struct extent_buffer *eb,
 				      struct btrfs_dir_item *item,
 				      struct btrfs_disk_key *key)
diff --git a/kernel-shared/dir-item.c b/kernel-shared/dir-item.c
index 27dfb362..27cf459d 100644
--- a/kernel-shared/dir-item.c
+++ b/kernel-shared/dir-item.c
@@ -89,7 +89,7 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
 	leaf = path->nodes[0];
 	btrfs_cpu_key_to_disk(&disk_key, &location);
 	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
-	btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR);
+	btrfs_set_dir_flags(leaf, dir_item, BTRFS_FT_XATTR);
 	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 	btrfs_set_dir_data_len(leaf, dir_item, data_len);
 	name_ptr = (unsigned long)(dir_item + 1);
@@ -141,7 +141,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
 	leaf = path->nodes[0];
 	btrfs_cpu_key_to_disk(&disk_key, location);
 	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
-	btrfs_set_dir_type(leaf, dir_item, type);
+	btrfs_set_dir_flags(leaf, dir_item, type);
 	btrfs_set_dir_data_len(leaf, dir_item, 0);
 	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 	name_ptr = (unsigned long)(dir_item + 1);
@@ -170,7 +170,7 @@ insert:
 	leaf = path->nodes[0];
 	btrfs_cpu_key_to_disk(&disk_key, location);
 	btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
-	btrfs_set_dir_type(leaf, dir_item, type);
+	btrfs_set_dir_flags(leaf, dir_item, type);
 	btrfs_set_dir_data_len(leaf, dir_item, 0);
 	btrfs_set_dir_name_len(leaf, dir_item, name_len);
 	name_ptr = (unsigned long)(dir_item + 1);
@@ -292,7 +292,7 @@ static int verify_dir_item(struct btrfs_root *root,
 		    struct btrfs_dir_item *dir_item)
 {
 	u16 namelen = BTRFS_NAME_LEN;
-	u8 type = btrfs_dir_type(leaf, dir_item);
+	u8 type = btrfs_dir_flags_to_ftype(btrfs_dir_flags(leaf, dir_item));
 
 	if (type == BTRFS_FT_XATTR)
 		namelen = XATTR_NAME_MAX;
diff --git a/kernel-shared/inode.c b/kernel-shared/inode.c
index 8dfe5b0d..66c16a98 100644
--- a/kernel-shared/inode.c
+++ b/kernel-shared/inode.c
@@ -541,6 +541,7 @@ int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 
 	if (dir_item) {
 		struct btrfs_key found_key;
+		u8 type;
 
 		/*
 		 * Already have conflicting name, check if it is a dir.
@@ -548,7 +549,8 @@ int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		 */
 		btrfs_dir_item_key_to_cpu(path->nodes[0], dir_item, &found_key);
 		ret_ino = found_key.objectid;
-		if (btrfs_dir_type(path->nodes[0], dir_item) != BTRFS_FT_DIR)
+		type = btrfs_dir_flags_to_ftype(btrfs_dir_flags(path->nodes[0], dir_item));
+		if (type != BTRFS_FT_DIR)
 			ret = -EEXIST;
 		goto out;
 	}
diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index fc4711b1..48028299 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -31,7 +31,7 @@
 static void print_dir_item_type(struct extent_buffer *eb,
                                 struct btrfs_dir_item *di)
 {
-	u8 type = btrfs_dir_type(eb, di);
+	u8 type = btrfs_dir_flags_to_ftype(btrfs_dir_flags(eb, di));
 	static const char* dir_item_str[] = {
 		[BTRFS_FT_REG_FILE]	= "FILE",
 		[BTRFS_FT_DIR] 		= "DIR",
diff --git a/libbtrfsutil/btrfs_tree.h b/libbtrfsutil/btrfs_tree.h
index 1df9efd6..fbe25037 100644
--- a/libbtrfsutil/btrfs_tree.h
+++ b/libbtrfsutil/btrfs_tree.h
@@ -322,6 +322,9 @@
 #define BTRFS_FT_XATTR		8
 #define BTRFS_FT_MAX		9
 
+/* Name is encrypted */
+#define BTRFS_FT_FSCRYPT_NAME	0x80
+
 /*
  * The key defines the order in the tree, and so it also defines (optimal)
  * block layout.
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] btrfs-progs: interpret encrypted file extents.
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 2/6] btrfs-progs: update to match renamed dir_type Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  2022-09-09 11:42   ` David Sterba
  2022-09-06  0:01 ` [PATCH 4/6] btrfs-progs: handle fscrypt context items Sweet Tea Dorminy
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

Encrypted file extents now have the 'encryption' field set to a
encryption type plus a context length, and have an extent context
appended to the item.  This necessitates adjusting the struct to have a
variable-length fscrypt_context member at the end, and printing contexts
if one is provided.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 check/main.c               |  4 +++-
 kernel-shared/ctree.h      | 24 +++++++++++++++++++++++-
 kernel-shared/fscrypt.h    | 27 +++++++++++++++++++++++++++
 kernel-shared/print-tree.c | 25 +++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 2 deletions(-)
 create mode 100644 kernel-shared/fscrypt.h

diff --git a/check/main.c b/check/main.c
index 3b133105..be9b0134 100644
--- a/check/main.c
+++ b/check/main.c
@@ -6565,6 +6565,7 @@ static int run_next_block(struct btrfs_root *root,
 		for (i = 0; i < nritems; i++) {
 			struct btrfs_file_extent_item *fi;
 			unsigned long inline_offset;
+			u8 ctxsize;
 
 			inline_offset = offsetof(struct btrfs_file_extent_item,
 						 disk_bytenr);
@@ -6700,8 +6701,9 @@ static int run_next_block(struct btrfs_root *root,
 				continue;
 
 			/* Prealloc/regular extent must have fixed item size */
+			ctxsize = btrfs_file_extent_encryption_ctxsize(buf, fi);
 			if (btrfs_item_size(buf, i) !=
-			    sizeof(struct btrfs_file_extent_item)) {
+			    sizeof(struct btrfs_file_extent_item) + ctxsize) {
 				ret = -EUCLEAN;
 				error(
 			"invalid file extent item size, have %u expect %zu",
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index d8f81610..4392393d 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -25,6 +25,7 @@
 #include "kerncompat.h"
 #include "common/extent-cache.h"
 #include "kernel-shared/extent_io.h"
+#include "kernel-shared/fscrypt.h"
 #include "ioctl.h"
 
 struct btrfs_root;
@@ -998,7 +999,11 @@ struct btrfs_file_extent_item {
 	 * uncompressed and without encoding.
 	 */
 	__le64 num_bytes;
-
+	/*
+	 * Fscrypt extent encryption context. Only present if extent is
+	 * encrypted (stored in the encryption field).
+	 */
+	__u8 fscrypt_context[0];
 } __attribute__ ((__packed__));
 
 struct btrfs_dev_stats_item {
@@ -2449,6 +2454,23 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
 		   encryption, 8);
 BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
 		   other_encoding, 16);
+static inline u8
+btrfs_file_extent_encryption_ctxsize(const struct extent_buffer *eb,
+				     struct btrfs_file_extent_item *e)
+{
+	u8 ctxsize;
+	btrfs_unpack_encryption(btrfs_file_extent_encryption(eb, e),
+				NULL, &ctxsize);
+	return ctxsize;
+}
+
+static inline u8
+btrfs_file_extent_ctxsize_from_item(const struct extent_buffer *leaf,
+				    const struct btrfs_path *path)
+{
+	return (btrfs_item_size(leaf, path->slots[0]) -
+		sizeof(struct btrfs_file_extent_item));
+}
 
 /* btrfs_qgroup_status_item */
 BTRFS_SETGET_FUNCS(qgroup_status_version, struct btrfs_qgroup_status_item,
diff --git a/kernel-shared/fscrypt.h b/kernel-shared/fscrypt.h
new file mode 100644
index 00000000..015c2d41
--- /dev/null
+++ b/kernel-shared/fscrypt.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef BTRFS_FSCRYPT_H
+#define BTRFS_FSCRYPT_H
+
+#define BTRFS_ENCRYPTION_POLICY_MASK 0x03
+#define BTRFS_ENCRYPTION_CTXSIZE_MASK 0xfc
+
+/* Actually from include/linux/fscrypt.h */
+#define FSCRYPT_EXTENT_CONTEXT_MAX_SIZE 33
+
+static inline void btrfs_unpack_encryption(u8 encryption,
+					   u8 *policy,
+					   u8 *ctxsize)
+{
+	if (policy)
+		*policy = encryption & BTRFS_ENCRYPTION_POLICY_MASK;
+	if (ctxsize)
+		*ctxsize = (encryption & BTRFS_ENCRYPTION_CTXSIZE_MASK) >> 2;
+}
+
+static inline u8 btrfs_pack_encryption(u8 policy, u8 ctxsize)
+{
+	return policy | (ctxsize << 2);
+}
+
+#endif // BTRFS_FSCRYPT_H
diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index 48028299..bb8db45c 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -354,6 +354,26 @@ static void compress_type_to_str(u8 compress_type, char *ret)
 	}
 }
 
+static void generate_encryption_string(struct extent_buffer *leaf,
+				       struct btrfs_file_extent_item *fi,
+				       char *ret)
+{
+	u8 encryption = btrfs_file_extent_encryption(leaf, fi);
+	u8 policy, ctxsize;
+	u8 ctx[FSCRYPT_EXTENT_CONTEXT_MAX_SIZE];
+	btrfs_unpack_encryption(encryption, &policy, &ctxsize);
+	if (ctxsize)
+		read_extent_buffer(leaf, ctx,
+				   (unsigned long)fi->fscrypt_context, ctxsize);
+	ret += sprintf(ret, "%hhu, %hhu", policy, ctxsize);
+	if (ctxsize) {
+		int i;
+		ret += sprintf(ret, ": context ");
+		for (i = 0; i < ctxsize; i++)
+			ret += sprintf(ret, "%02hhx", ctx[i]);
+	}
+}
+
 static const char* file_extent_type_to_str(u8 type)
 {
 	switch (type) {
@@ -370,9 +390,11 @@ static void print_file_extent_item(struct extent_buffer *eb,
 {
 	unsigned char extent_type = btrfs_file_extent_type(eb, fi);
 	char compress_str[16];
+	char encrypt_str[16];
 
 	compress_type_to_str(btrfs_file_extent_compression(eb, fi),
 			     compress_str);
+	generate_encryption_string(eb, fi, encrypt_str);
 
 	printf("\t\tgeneration %llu type %hhu (%s)\n",
 			btrfs_file_extent_generation(eb, fi),
@@ -405,6 +427,9 @@ static void print_file_extent_item(struct extent_buffer *eb,
 	printf("\t\textent compression %hhu (%s)\n",
 			btrfs_file_extent_compression(eb, fi),
 			compress_str);
+	printf("\t\textent encryption %hhu (%s)\n",
+			btrfs_file_extent_encryption(eb, fi),
+			encrypt_str);
 }
 
 /* Caller should ensure sizeof(*ret) >= 16("DATA|TREE_BLOCK") */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] btrfs-progs: handle fscrypt context items
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
                   ` (2 preceding siblings ...)
  2022-09-06  0:01 ` [PATCH 3/6] btrfs-progs: interpret encrypted file extents Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 5/6] btrfs-progs: escape unprintable characters in names Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 6/6] btrfs-progs: check: update inline extent length checking Sweet Tea Dorminy
  5 siblings, 0 replies; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

Encrypted inodes have a new associated item, the fscrypt context, which
can be printed as a pure hex string in dump-tree.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 kernel-shared/ctree.h      |  2 ++
 kernel-shared/print-tree.c | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 4392393d..2541a102 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1397,6 +1397,8 @@ static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info)
 #define BTRFS_VERITY_DESC_ITEM_KEY	36
 #define BTRFS_VERITY_MERKLE_ITEM_KEY	37
 
+#define BTRFS_FSCRYPT_CTXT_ITEM_KEY	41
+
 #define BTRFS_ORPHAN_ITEM_KEY		48
 
 #define BTRFS_DIR_LOG_ITEM_KEY  60
diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index bb8db45c..2163f833 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -97,6 +97,20 @@ static void print_dir_item(struct extent_buffer *eb, u32 size,
 	}
 }
 
+static void print_fscrypt_context(struct extent_buffer *eb, int slot)
+{
+	int i;
+	unsigned long ptr = btrfs_item_ptr_offset(eb, slot);
+	u32 item_size = btrfs_item_size(eb, slot);
+	u8 ctx_buf[item_size];
+
+	read_extent_buffer(eb, ctx_buf, ptr, item_size);
+	printf("\t\tvalue: ");
+	for(i = 0; i < item_size; i++)
+		printf("%02x", ctx_buf[i]);
+	printf("\n");
+}
+
 static void print_inode_extref_item(struct extent_buffer *eb, u32 size,
 		struct btrfs_inode_extref *extref)
 {
@@ -671,6 +685,7 @@ void print_key_type(FILE *stream, u64 objectid, u8 type)
 		[BTRFS_DIR_LOG_ITEM_KEY]	= "DIR_LOG_ITEM",
 		[BTRFS_DIR_LOG_INDEX_KEY]	= "DIR_LOG_INDEX",
 		[BTRFS_XATTR_ITEM_KEY]		= "XATTR_ITEM",
+		[BTRFS_FSCRYPT_CTXT_ITEM_KEY]   = "FSCRYPT_CTXT_ITEM",
 		[BTRFS_VERITY_DESC_ITEM_KEY]	= "VERITY_DESC_ITEM",
 		[BTRFS_VERITY_MERKLE_ITEM_KEY]	= "VERITY_MERKLE_ITEM",
 		[BTRFS_ORPHAN_ITEM_KEY]		= "ORPHAN_ITEM",
@@ -1378,6 +1393,9 @@ void btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode)
 		case BTRFS_XATTR_ITEM_KEY:
 			print_dir_item(eb, item_size, ptr);
 			break;
+		case BTRFS_FSCRYPT_CTXT_ITEM_KEY:
+			print_fscrypt_context(eb, i);
+			break;
 		case BTRFS_DIR_LOG_INDEX_KEY:
 		case BTRFS_DIR_LOG_ITEM_KEY: {
 			struct btrfs_dir_log_item *dlog;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] btrfs-progs: escape unprintable characters in names
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
                   ` (3 preceding siblings ...)
  2022-09-06  0:01 ` [PATCH 4/6] btrfs-progs: handle fscrypt context items Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  2022-09-06  0:01 ` [PATCH 6/6] btrfs-progs: check: update inline extent length checking Sweet Tea Dorminy
  5 siblings, 0 replies; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

There are several item types which have an associated name: inode refs
and dir items. While they could always be unprintable, the advent of
encryption makes it much more likely that the names contain characters
outside the normal ASCII range. As such, it's useful to print the
characters outside normal ASCII in hex format.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 kernel-shared/print-tree.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index 2163f833..6365d961 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -28,6 +28,19 @@
 #include "kernel-shared/volumes.h"
 #include "common/utils.h"
 
+static void print_name(const char *buf, size_t len)
+{
+	size_t i;
+	printf("name: ");
+	for(i = 0; i < len; i++) {
+		if (buf[i] >= ' ' && buf[i] <= '~')
+			printf("%c", buf[i]);
+		else
+			printf("\\x%02hhx", buf[i]);
+	}
+	printf("\n");
+}
+
 static void print_dir_item_type(struct extent_buffer *eb,
                                 struct btrfs_dir_item *di)
 {
@@ -77,7 +90,7 @@ static void print_dir_item(struct extent_buffer *eb, u32 size,
 		} else {
 			read_extent_buffer(eb, namebuf,
 					(unsigned long)(di + 1), len);
-			printf("\t\tname: %.*s\n", len, namebuf);
+			print_name(namebuf, len);
 		}
 
 		if (data_len) {
@@ -135,7 +148,7 @@ static void print_inode_extref_item(struct extent_buffer *eb, u32 size,
 		} else {
 			read_extent_buffer(eb, namebuf,
 					(unsigned long)extref->name, len);
-			printf("name: %.*s\n", len, namebuf);
+			print_name(namebuf, len);
 		}
 
 		len = sizeof(*extref) + name_len;
@@ -165,7 +178,7 @@ static void print_inode_ref_item(struct extent_buffer *eb, u32 size,
 		} else {
 			read_extent_buffer(eb, namebuf,
 					(unsigned long)(ref + 1), len);
-			printf("name: %.*s\n", len, namebuf);
+			print_name(namebuf, len);
 		}
 		len = sizeof(*ref) + name_len;
 		ref = (struct btrfs_inode_ref *)((char *)ref + len);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] btrfs-progs: check: update inline extent length checking
  2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
                   ` (4 preceding siblings ...)
  2022-09-06  0:01 ` [PATCH 5/6] btrfs-progs: escape unprintable characters in names Sweet Tea Dorminy
@ 2022-09-06  0:01 ` Sweet Tea Dorminy
  5 siblings, 0 replies; 9+ messages in thread
From: Sweet Tea Dorminy @ 2022-09-06  0:01 UTC (permalink / raw)
  To: linux-btrfs, kernel-team; +Cc: Sweet Tea Dorminy

As part of the encryption changes, encrypted inline file extents record
their actual data length in ram_bytes, like compressed inline file
extents, while the item's length records the actual size. As such,
encrypted inline extents must be treated like compressed ones for
inode length consistency checking.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
 check/main.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/check/main.c b/check/main.c
index be9b0134..5466f45d 100644
--- a/check/main.c
+++ b/check/main.c
@@ -1626,7 +1626,7 @@ static int process_file_extent(struct btrfs_root *root,
 	u64 mask = gfs_info->sectorsize - 1;
 	u32 max_inline_size = min_t(u32, mask,
 				BTRFS_MAX_INLINE_DATA_SIZE(gfs_info));
-	u8 compression;
+	u8 compression, encryption;
 	int extent_type;
 	int ret;
 
@@ -1651,25 +1651,25 @@ static int process_file_extent(struct btrfs_root *root,
 	fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
 	extent_type = btrfs_file_extent_type(eb, fi);
 	compression = btrfs_file_extent_compression(eb, fi);
+	encryption = btrfs_file_extent_encryption(eb, fi);
 
 	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-		num_bytes = btrfs_file_extent_ram_bytes(eb, fi);
-		if (num_bytes == 0)
+		u64 num_decoded_bytes = btrfs_file_extent_ram_bytes(eb, fi);
+		u64 num_disk_bytes =  btrfs_file_extent_inline_item_len(eb, slot);
+		if (num_decoded_bytes == 0)
 			rec->errors |= I_ERR_BAD_FILE_EXTENT;
-		if (compression) {
-			if (btrfs_file_extent_inline_item_len(eb, slot) >
-			    max_inline_size ||
-			    num_bytes > gfs_info->sectorsize)
+		if (compression || encryption) {
+			if (num_disk_bytes > max_inline_size ||
+			    num_decoded_bytes > gfs_info->sectorsize)
 				rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
 		} else {
-			if (num_bytes > max_inline_size)
+			if (num_decoded_bytes > max_inline_size)
 				rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE;
-			if (btrfs_file_extent_inline_item_len(eb, slot) !=
-			    num_bytes)
+			if (num_disk_bytes != num_decoded_bytes)
 				rec->errors |= I_ERR_INLINE_RAM_BYTES_WRONG;
 		}
-		rec->found_size += num_bytes;
-		num_bytes = (num_bytes + mask) & ~mask;
+		rec->found_size += num_decoded_bytes;
+		num_bytes = (num_decoded_bytes + mask) & ~mask;
 	} else if (extent_type == BTRFS_FILE_EXTENT_REG ||
 		   extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
 		num_bytes = btrfs_file_extent_num_bytes(eb, fi);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs.
  2022-09-06  0:01 ` [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs Sweet Tea Dorminy
@ 2022-09-09 11:39   ` David Sterba
  0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2022-09-09 11:39 UTC (permalink / raw)
  To: Sweet Tea Dorminy; +Cc: linux-btrfs, kernel-team

On Mon, Sep 05, 2022 at 08:01:02PM -0400, Sweet Tea Dorminy wrote:
> Add a new experimental option to allow use of encryption.
> 
> Arguably, since older kernels can technically read non-encrypted parts
> of an encrypted filesystem, perhaps this doesn't need to be an incompat
> feature.
> 
> Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
> ---
>  common/fsfeatures.c   | 10 ++++++++++
>  kernel-shared/ctree.h |  4 +++-
>  libbtrfsutil/btrfs.h  |  2 ++
>  3 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/common/fsfeatures.c b/common/fsfeatures.c
> index 90704959..ea185a3c 100644
> --- a/common/fsfeatures.c
> +++ b/common/fsfeatures.c
> @@ -143,6 +143,16 @@ static const struct btrfs_feature mkfs_features[] = {
>  		.desc		= "new extent tree format"
>  	},
>  #endif
> +	{
> +		.name		= "encrypt",

I'd like to call it fscrypt so it's clear what implementation it's
using.

> +		.flag		= BTRFS_FEATURE_INCOMPAT_FSCRYPT,
> +		.sysfs_name	= "fscrypt",
> +		VERSION_TO_STRING2(compat, 5,19),

The version will be at least 6.2

> +		VERSION_NULL(safe),
> +		VERSION_NULL(default),
> +		.desc		= "fs-level encryption"

That's too terse, please write something like "filesystem encryption
using fscrypt"

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/6] btrfs-progs: interpret encrypted file extents.
  2022-09-06  0:01 ` [PATCH 3/6] btrfs-progs: interpret encrypted file extents Sweet Tea Dorminy
@ 2022-09-09 11:42   ` David Sterba
  0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2022-09-09 11:42 UTC (permalink / raw)
  To: Sweet Tea Dorminy; +Cc: linux-btrfs, kernel-team

On Mon, Sep 05, 2022 at 08:01:04PM -0400, Sweet Tea Dorminy wrote:
> -
> +	/*
> +	 * Fscrypt extent encryption context. Only present if extent is
> +	 * encrypted (stored in the encryption field).
> +	 */
> +	__u8 fscrypt_context[0];
>  } __attribute__ ((__packed__));
>  
>  struct btrfs_dev_stats_item {
> @@ -2449,6 +2454,23 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
>  		   encryption, 8);
>  BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
>  		   other_encoding, 16);
> +static inline u8
> +btrfs_file_extent_encryption_ctxsize(const struct extent_buffer *eb,
> +				     struct btrfs_file_extent_item *e)

Please use same coding style as in kernel

> --- /dev/null
> +++ b/kernel-shared/fscrypt.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef BTRFS_FSCRYPT_H
> +#define BTRFS_FSCRYPT_H
> +
> +#define BTRFS_ENCRYPTION_POLICY_MASK 0x03
> +#define BTRFS_ENCRYPTION_CTXSIZE_MASK 0xfc

The definitions should match what's in kernel, the file will be
problably 1:1 so it can be synced once kernel side is finalized.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-09-09 11:47 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-06  0:01 [PATCH 0/6] btrfs-progs: add encryption support Sweet Tea Dorminy
2022-09-06  0:01 ` [PATCH 1/6] btrfs-progs: add fscrypt support to mkfs Sweet Tea Dorminy
2022-09-09 11:39   ` David Sterba
2022-09-06  0:01 ` [PATCH 2/6] btrfs-progs: update to match renamed dir_type Sweet Tea Dorminy
2022-09-06  0:01 ` [PATCH 3/6] btrfs-progs: interpret encrypted file extents Sweet Tea Dorminy
2022-09-09 11:42   ` David Sterba
2022-09-06  0:01 ` [PATCH 4/6] btrfs-progs: handle fscrypt context items Sweet Tea Dorminy
2022-09-06  0:01 ` [PATCH 5/6] btrfs-progs: escape unprintable characters in names Sweet Tea Dorminy
2022-09-06  0:01 ` [PATCH 6/6] btrfs-progs: check: update inline extent length checking Sweet Tea Dorminy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.