]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io/encrypt: support specifying crypto data unit size
authorEric Biggers <ebiggers@google.com>
Fri, 13 Oct 2023 06:26:39 +0000 (23:26 -0700)
committerCarlos Maiolino <cem@kernel.org>
Mon, 18 Dec 2023 13:57:48 +0000 (14:57 +0100)
Add an '-s' option to the 'set_encpolicy' command of xfs_io to allow
exercising the log2_data_unit_size field that is being added to struct
fscrypt_policy_v2 (kernel patch:
https://lore.kernel.org/linux-fscrypt/20230925055451.59499-6-ebiggers@kernel.org).

The xfs_io support is needed for xfstests
(https://lore.kernel.org/fstests/20231013061403.138425-1-ebiggers@kernel.org),
which currently relies on xfs_io to access the encryption ioctls.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
configure.ac
include/builddefs.in
io/encrypt.c
m4/package_libcdev.m4
man/man8/xfs_io.8

index febd0c09bc02fb8f93f3784bc179bc45abc4ffd5..2034f02e59edba65adb6aeaed450dd3975ad7c71 100644 (file)
@@ -187,6 +187,7 @@ AC_HAVE_FSETXATTR
 AC_HAVE_MREMAP
 AC_NEED_INTERNAL_FSXATTR
 AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG
+AC_NEED_INTERNAL_FSCRYPT_POLICY_V2
 AC_HAVE_GETFSMAP
 AC_HAVE_STATFS_FLAGS
 AC_HAVE_MAP_SYNC
index 147c9b9866da0f51096aac6c0f4bffe5669a7847..43025ba4fccc9ded8851d69b2a2c53fa3cdd16dc 100644 (file)
@@ -110,6 +110,7 @@ HAVE_FSETXATTR = @have_fsetxattr@
 HAVE_MREMAP = @have_mremap@
 NEED_INTERNAL_FSXATTR = @need_internal_fsxattr@
 NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG = @need_internal_fscrypt_add_key_arg@
+NEED_INTERNAL_FSCRYPT_POLICY_V2 = @need_internal_fscrypt_policy_v2@
 HAVE_GETFSMAP = @have_getfsmap@
 HAVE_STATFS_FLAGS = @have_statfs_flags@
 HAVE_MAP_SYNC = @have_map_sync@
@@ -157,6 +158,9 @@ endif
 ifeq ($(NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG),yes)
 PCFLAGS+= -DOVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG
 endif
+ifeq ($(NEED_INTERNAL_FSCRYPT_POLICY_V2),yes)
+PCFLAGS+= -DOVERRIDE_SYSTEM_FSCRYPT_POLICY_V2
+endif
 ifeq ($(HAVE_GETFSMAP),yes)
 PCFLAGS+= -DHAVE_GETFSMAP
 endif
index 1b347dc1afdb55c43139e55cbc0a5809db86b317..79061b07c961b049ac8f6773c3ffa59451664663 100644 (file)
@@ -7,6 +7,10 @@
 #ifdef OVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG
 #  define fscrypt_add_key_arg sys_fscrypt_add_key_arg
 #endif
+#ifdef OVERRIDE_SYSTEM_FSCRYPT_POLICY_V2
+#  define fscrypt_policy_v2 sys_fscrypt_policy_v2
+#  define fscrypt_get_policy_ex_arg sys_fscrypt_get_policy_ex_arg
+#endif
 #include "platform_defs.h"
 #include "command.h"
 #include "init.h"
 #define FS_IOC_GET_ENCRYPTION_POLICY           _IOW('f', 21, struct fscrypt_policy)
 #endif
 
+/*
+ * Since the log2_data_unit_size field was added later than fscrypt_policy_v2
+ * itself, we may need to override the system definition to get that field.
+ * And also fscrypt_get_policy_ex_arg since it contains fscrypt_policy_v2.
+ */
+#if !defined(FS_IOC_GET_ENCRYPTION_POLICY_EX) || \
+       defined(OVERRIDE_SYSTEM_FSCRYPT_POLICY_V2)
+#undef fscrypt_policy_v2
+struct fscrypt_policy_v2 {
+       __u8 version;
+       __u8 contents_encryption_mode;
+       __u8 filenames_encryption_mode;
+       __u8 flags;
+       __u8 log2_data_unit_size;
+       __u8 __reserved[3];
+       __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
+};
+
+#undef fscrypt_get_policy_ex_arg
+struct fscrypt_get_policy_ex_arg {
+       __u64 policy_size; /* input/output */
+       union {
+               __u8 version;
+               struct fscrypt_policy_v1 v1;
+               struct fscrypt_policy_v2 v2;
+       } policy; /* output */
+};
+#endif
+
 /*
  * Second batch of ioctls (Linux headers v5.4+), plus some renamings from FS_ to
  * FSCRYPT_.  We don't bother defining the old names here.
@@ -69,26 +102,12 @@ struct fscrypt_policy_v1 {
 
 #define FSCRYPT_POLICY_V2              2
 #define FSCRYPT_KEY_IDENTIFIER_SIZE    16
-struct fscrypt_policy_v2 {
-       __u8 version;
-       __u8 contents_encryption_mode;
-       __u8 filenames_encryption_mode;
-       __u8 flags;
-       __u8 __reserved[4];
-       __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
-};
+/* struct fscrypt_policy_v2 was defined earlier */
 
 #define FSCRYPT_MAX_KEY_SIZE           64
 
 #define FS_IOC_GET_ENCRYPTION_POLICY_EX                _IOWR('f', 22, __u8[9]) /* size + version */
-struct fscrypt_get_policy_ex_arg {
-       __u64 policy_size; /* input/output */
-       union {
-               __u8 version;
-               struct fscrypt_policy_v1 v1;
-               struct fscrypt_policy_v2 v2;
-       } policy; /* output */
-};
+/* struct fscrypt_get_policy_ex_arg was defined earlier */
 
 #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR       1
 #define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER       2
@@ -205,6 +224,7 @@ set_encpolicy_help(void)
 " -c MODE -- contents encryption mode\n"
 " -n MODE -- filenames encryption mode\n"
 " -f FLAGS -- policy flags\n"
+" -s LOG2_DUSIZE -- log2 of data unit size\n"
 " -v VERSION -- policy version\n"
 "\n"
 " MODE can be numeric or one of the following predefined values:\n"));
@@ -588,6 +608,7 @@ set_encpolicy_f(int argc, char **argv)
        __u8 contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
        __u8 filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
        __u8 flags = FSCRYPT_POLICY_FLAGS_PAD_16;
+       __u8 log2_data_unit_size = 0;
        int version = -1; /* unspecified */
        struct fscrypt_key_specifier key_spec;
        union {
@@ -596,7 +617,7 @@ set_encpolicy_f(int argc, char **argv)
                struct fscrypt_policy_v2 v2;
        } policy;
 
-       while ((c = getopt(argc, argv, "c:n:f:v:")) != EOF) {
+       while ((c = getopt(argc, argv, "c:n:f:s:v:")) != EOF) {
                switch (c) {
                case 'c':
                        if (!parse_mode(optarg, &contents_encryption_mode)) {
@@ -624,6 +645,14 @@ set_encpolicy_f(int argc, char **argv)
                                return 0;
                        }
                        break;
+               case 's':
+                       if (!parse_byte_value(optarg, &log2_data_unit_size)) {
+                               fprintf(stderr, _("invalid log2_dusize: %s\n"),
+                                       optarg);
+                               exitcode = 1;
+                               return 0;
+                       }
+                       break;
                case 'v': {
                        __u8 val;
 
@@ -673,9 +702,16 @@ set_encpolicy_f(int argc, char **argv)
                policy.v2.contents_encryption_mode = contents_encryption_mode;
                policy.v2.filenames_encryption_mode = filenames_encryption_mode;
                policy.v2.flags = flags;
+               policy.v2.log2_data_unit_size = log2_data_unit_size;
                memcpy(policy.v2.master_key_identifier, key_spec.u.identifier,
                       FSCRYPT_KEY_IDENTIFIER_SIZE);
        } else {
+               if (log2_data_unit_size != 0) {
+                       fprintf(stderr,
+                               "v1 policy does not support selecting the data unit size\n");
+                       exitcode = 1;
+                       return 0;
+               }
                /*
                 * xfstests passes .version = 255 for testing.  Just use
                 * 'struct fscrypt_policy_v1' for both v1 and unknown versions.
@@ -908,7 +944,7 @@ encrypt_init(void)
        set_encpolicy_cmd.name = "set_encpolicy";
        set_encpolicy_cmd.cfunc = set_encpolicy_f;
        set_encpolicy_cmd.args =
-               _("[-c mode] [-n mode] [-f flags] [-v version] [keyspec]");
+               _("[-c mode] [-n mode] [-f flags] [-s log2_dusize] [-v version] [keyspec]");
        set_encpolicy_cmd.argmin = 0;
        set_encpolicy_cmd.argmax = -1;
        set_encpolicy_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
index f987aa4ab7b5b8de475bc7cc237a915f9cf15902..174070651ecf766355ab2aa7c266250a3fb90dc9 100644 (file)
@@ -326,6 +326,27 @@ AC_DEFUN([AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG],
     AC_SUBST(need_internal_fscrypt_add_key_arg)
   ])
 
+#
+# Check if we need to override the system struct fscrypt_policy_v2
+# with the internal definition.  This /only/ happens if the system
+# actually defines struct fscrypt_policy_v2 /and/ the system
+# definition is missing certain fields.
+#
+AC_DEFUN([AC_NEED_INTERNAL_FSCRYPT_POLICY_V2],
+  [
+    AC_CHECK_TYPE(struct fscrypt_policy_v2,
+      [
+        AC_CHECK_MEMBER(struct fscrypt_policy_v2.log2_data_unit_size,
+          ,
+          need_internal_fscrypt_policy_v2=yes,
+          [#include <linux/fs.h>]
+        )
+      ],,
+      [#include <linux/fs.h>]
+    )
+    AC_SUBST(need_internal_fscrypt_policy_v2)
+  ])
+
 #
 # Check if we have a FS_IOC_GETFSMAP ioctl (Linux)
 #
index ef7087b3d0908e937f7030aa392f4b86d303d3f6..52f04dd73844adf361e0740c0ab5745adec609c4 100644 (file)
@@ -713,7 +713,7 @@ Swaps extent forks between files. The current open file is the target. The donor
 file is specified by path. Note that file data is not copied (file content moves
 with the fork(s)).
 .TP
-.BI "set_encpolicy [ \-c " mode " ] [ \-n " mode " ] [ \-f " flags " ] [ \-v " version " ] [ " keyspec " ]"
+.BI "set_encpolicy [ \-c " mode " ] [ \-n " mode " ] [ \-f " flags " ] [ \-s " log2_dusize " ] [ \-v " version " ] [ " keyspec " ]"
 On filesystems that support encryption, assign an encryption policy to the
 current file.
 .I keyspec
@@ -736,6 +736,9 @@ filenames encryption mode (e.g. AES-256-CTS)
 .BI \-f " flags"
 policy flags (numeric)
 .TP
+.BI \-s " log2_dusize"
+log2 of data unit size.  Not supported by v1 policies.
+.TP
 .BI \-v " version"
 policy version.  Defaults to 1 or 2 depending on the length of
 .IR keyspec ;