]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_io/encrypt: support passing a keyring key to add_enckey
authorEric Biggers <ebiggers@google.com>
Sun, 1 Mar 2020 17:33:38 +0000 (12:33 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Sun, 1 Mar 2020 17:33:38 +0000 (12:33 -0500)
Add a '-k' option to the 'add_enckey' xfs_io command to allow exercising
the key_id field that is being added to struct fscrypt_add_key_arg.

This is needed for the corresponding test in xfstests.

For more details, see the corresponding xfstests patches as well as
kernel commit 93edd392cad7 ("fscrypt: support passing a keyring key to
FS_IOC_ADD_ENCRYPTION_KEY").

Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
configure.ac
include/builddefs.in
io/encrypt.c
m4/package_libcdev.m4
man/man8/xfs_io.8

index 5eb7c14b7287a948f53d224b7158b4a01e8701ef..f9348a0c2d44288096c077e6365f775bcc333e08 100644 (file)
@@ -176,6 +176,7 @@ AC_HAVE_READDIR
 AC_HAVE_FSETXATTR
 AC_HAVE_MREMAP
 AC_NEED_INTERNAL_FSXATTR
+AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG
 AC_HAVE_GETFSMAP
 AC_HAVE_STATFS_FLAGS
 AC_HAVE_MAP_SYNC
index 1dd27f760306dc78ed6461df5aaa07d385ff8806..2987f0b8972240d2f689b676fcc15f9317c15c1d 100644 (file)
@@ -102,6 +102,7 @@ HAVE_FLS = @have_fls@
 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@
 HAVE_GETFSMAP = @have_getfsmap@
 HAVE_STATFS_FLAGS = @have_statfs_flags@
 HAVE_MAP_SYNC = @have_map_sync@
@@ -141,6 +142,9 @@ endif
 ifeq ($(NEED_INTERNAL_FSXATTR),yes)
 PCFLAGS+= -DOVERRIDE_SYSTEM_FSXATTR
 endif
+ifeq ($(NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG),yes)
+PCFLAGS+= -DOVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG
+endif
 ifeq ($(HAVE_GETFSMAP),yes)
 PCFLAGS+= -DHAVE_GETFSMAP
 endif
index de48c50c5e19924de8d41d0da844539f5e89a1a8..01b7e0df8a6e1976472e45807173072645caa1ad 100644 (file)
@@ -4,6 +4,9 @@
  * Author: Eric Biggers <ebiggers@google.com>
  */
 
+#ifdef OVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG
+#  define fscrypt_add_key_arg sys_fscrypt_add_key_arg
+#endif
 #include "platform_defs.h"
 #include "command.h"
 #include "init.h"
@@ -99,13 +102,7 @@ struct fscrypt_key_specifier {
        } u;
 };
 
-#define FS_IOC_ADD_ENCRYPTION_KEY              _IOWR('f', 23, struct fscrypt_add_key_arg)
-struct fscrypt_add_key_arg {
-       struct fscrypt_key_specifier key_spec;
-       __u32 raw_size;
-       __u32 __reserved[9];
-       __u8 raw[];
-};
+/* FS_IOC_ADD_ENCRYPTION_KEY is defined later */
 
 #define FS_IOC_REMOVE_ENCRYPTION_KEY           _IOWR('f', 24, struct fscrypt_remove_key_arg)
 #define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
@@ -136,6 +133,26 @@ struct fscrypt_get_key_status_arg {
 
 #endif /* !FS_IOC_GET_ENCRYPTION_POLICY_EX */
 
+/*
+ * Since the key_id field was added later than struct fscrypt_add_key_arg
+ * itself, we may need to override the system definition to get that field.
+ */
+#if !defined(FS_IOC_ADD_ENCRYPTION_KEY) || \
+       defined(OVERRIDE_SYSTEM_FSCRYPT_ADD_KEY_ARG)
+#undef fscrypt_add_key_arg
+struct fscrypt_add_key_arg {
+       struct fscrypt_key_specifier key_spec;
+       __u32 raw_size;
+       __u32 key_id;
+       __u32 __reserved[8];
+       __u8 raw[];
+};
+#endif
+
+#ifndef FS_IOC_ADD_ENCRYPTION_KEY
+#  define FS_IOC_ADD_ENCRYPTION_KEY            _IOWR('f', 23, struct fscrypt_add_key_arg)
+#endif
+
 static const struct {
        __u8 mode;
        const char *name;
@@ -217,8 +234,9 @@ add_enckey_help(void)
 " 'add_enckey' - add key for v2 policies\n"
 " 'add_enckey -d 0000111122223333' - add key for v1 policies w/ given descriptor\n"
 "\n"
-"The key in binary is read from standard input.\n"
+"Unless -k is given, the key in binary is read from standard input.\n"
 " -d DESCRIPTOR -- master_key_descriptor\n"
+" -k KEY_ID -- ID of fscrypt-provisioning key containing the raw key\n"
 "\n"));
 }
 
@@ -431,6 +449,21 @@ str2keyspec(const char *str, int policy_version,
        return policy_version;
 }
 
+static int
+parse_key_id(const char *arg)
+{
+       long value;
+       char *tmp;
+
+       value = strtol(arg, &tmp, 0);
+       if (value <= 0 || value > INT_MAX || tmp == arg || *tmp != '\0') {
+               fprintf(stderr, _("invalid key ID: %s\n"), arg);
+               /* 0 is never a valid Linux key ID. */
+               return 0;
+       }
+       return value;
+}
+
 static void
 test_for_v2_policy_support(void)
 {
@@ -689,13 +722,18 @@ add_enckey_f(int argc, char **argv)
 
        arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
 
-       while ((c = getopt(argc, argv, "d:")) != EOF) {
+       while ((c = getopt(argc, argv, "d:k:")) != EOF) {
                switch (c) {
                case 'd':
                        arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
                        if (!str2keydesc(optarg, arg->key_spec.u.descriptor))
                                goto out;
                        break;
+               case 'k':
+                       arg->key_id = parse_key_id(optarg);
+                       if (arg->key_id == 0)
+                               goto out;
+                       break;
                default:
                        retval = command_usage(&add_enckey_cmd);
                        goto out;
@@ -709,21 +747,23 @@ add_enckey_f(int argc, char **argv)
                goto out;
        }
 
-       raw_size = read_until_limit_or_eof(STDIN_FILENO, arg->raw,
-                                          FSCRYPT_MAX_KEY_SIZE + 1);
-       if (raw_size < 0) {
-               fprintf(stderr, _("Error reading key from stdin: %s\n"),
-                       strerror(errno));
-               exitcode = 1;
-               goto out;
-       }
-       if (raw_size > FSCRYPT_MAX_KEY_SIZE) {
-               fprintf(stderr,
-                       _("Invalid key; got > FSCRYPT_MAX_KEY_SIZE (%d) bytes on stdin!\n"),
-                       FSCRYPT_MAX_KEY_SIZE);
-               goto out;
-       }
-       arg->raw_size = raw_size;
+       if (arg->key_id == 0) {
+               raw_size = read_until_limit_or_eof(STDIN_FILENO, arg->raw,
+                                                  FSCRYPT_MAX_KEY_SIZE + 1);
+               if (raw_size < 0) {
+                       fprintf(stderr, _("Error reading key from stdin: %s\n"),
+                               strerror(errno));
+                       exitcode = 1;
+                       goto out;
+               }
+               if (raw_size > FSCRYPT_MAX_KEY_SIZE) {
+                       fprintf(stderr,
+                               _("Invalid key; got > FSCRYPT_MAX_KEY_SIZE (%d) bytes on stdin!\n"),
+                               FSCRYPT_MAX_KEY_SIZE);
+                       goto out;
+               }
+               arg->raw_size = raw_size;
+       } /* else, raw key is given via key with ID 'key_id' */
 
        if (ioctl(file->fd, FS_IOC_ADD_ENCRYPTION_KEY, arg) != 0) {
                fprintf(stderr, _("Error adding encryption key: %s\n"),
@@ -859,7 +899,7 @@ encrypt_init(void)
 
        add_enckey_cmd.name = "add_enckey";
        add_enckey_cmd.cfunc = add_enckey_f;
-       add_enckey_cmd.args = _("[-d descriptor]");
+       add_enckey_cmd.args = _("[-d descriptor] [-k key_id]");
        add_enckey_cmd.argmin = 0;
        add_enckey_cmd.argmax = -1;
        add_enckey_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
index 2c0c72ce60c59ce89a16f29f4f8e93903ddaaa17..adab9bb9773a857da82c103f009706a0d4f8043a 100644 (file)
@@ -278,6 +278,27 @@ AC_DEFUN([AC_NEED_INTERNAL_FSXATTR],
     AC_SUBST(need_internal_fsxattr)
   ])
 
+#
+# Check if we need to override the system struct fscrypt_add_key_arg
+# with the internal definition.  This /only/ happens if the system
+# actually defines struct fscrypt_add_key_arg /and/ the system
+# definition is missing certain fields.
+#
+AC_DEFUN([AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG],
+  [
+    AC_CHECK_TYPE(struct fscrypt_add_key_arg,
+      [
+        AC_CHECK_MEMBER(struct fscrypt_add_key_arg.key_id,
+          ,
+          need_internal_fscrypt_add_key_arg=yes,
+          [#include <linux/fs.h>]
+        )
+      ],,
+      [#include <linux/fs.h>]
+    )
+    AC_SUBST(need_internal_fscrypt_add_key_arg)
+  ])
+
 #
 # Check if we have a FS_IOC_GETFSMAP ioctl (Linux)
 #
index f5431a8c053692b4431211b45af5548c7803c858..b9dcc312949a3c02ba90469b98d3398fe85dbe38 100644 (file)
@@ -749,10 +749,10 @@ Test whether v2 encryption policies are supported.  Prints "supported",
 .RE
 .PD
 .TP
-.BI "add_enckey [ \-d " descriptor " ]"
+.BI "add_enckey [ \-d " descriptor " ] [ \-k " key_id " ]"
 On filesystems that support encryption, add an encryption key to the filesystem
-containing the currently open file.  The key in binary (typically 64 bytes long)
-is read from standard input.
+containing the currently open file.  By default, the raw key in binary
+(typically 64 bytes long) is read from standard input.
 .RS 1.0i
 .PD 0
 .TP 0.4i
@@ -761,6 +761,10 @@ key descriptor, as a 16-character hex string (8 bytes).  If given, the key will
 be available for use by v1 encryption policies that use this descriptor.
 Otherwise, the key is added as a v2 policy key, and on success the resulting
 "key identifier" will be printed.
+.TP
+.BI \-k " key_id"
+ID of kernel keyring key of type "fscrypt-provisioning".  If given, the raw key
+will be taken from here rather than from standard input.
 .RE
 .PD
 .TP