@@ -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",
@@ -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,
new file mode 100644
@@ -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
@@ -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") */
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