diff mbox series

[RFC,2/2] dm-crypt: Use any key type which is registered

Message ID 1551456599-10603-3-git-send-email-franck.lenormand@nxp.com (mailing list archive)
State New, archived
Headers show
Series Create CAAM HW key in linux keyring and use in dmcrypt | expand

Commit Message

Franck Lenormand March 1, 2019, 4:09 p.m. UTC
There was only 2 key_type supported by dm-crypt which limits other
implementations.

This patch allows to use any key_type which is registered obtaining
the key_type from key framework.

This also remove the compilation dependency between dm-crypt and
key implementations.

Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
---
 drivers/md/dm-crypt.c    | 11 ++++++-----
 include/linux/key-type.h |  2 ++
 security/keys/key.c      | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 5 deletions(-)

Comments

Maik Otto Jan. 17, 2020, 11:52 a.m. UTC | #1
Hi

little bug fix, because this version chrashed with access violation
on an i.MX6Quad with a Mainline Kernel 4.19.88

> There was only 2 key_type supported by dm-crypt which limits other
> implementations.
>
> This patch allows to use any key_type which is registered obtaining
> the key_type from key framework.
>
> This also remove the compilation dependency between dm-crypt and
> key implementations.
>
> Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
> ---
>   drivers/md/dm-crypt.c    | 11 ++++++-----
>   include/linux/key-type.h |  2 ++
>   security/keys/key.c      | 42 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 50 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index dd538e6..e25efc2 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -35,6 +35,7 @@
>   #include <crypto/authenc.h>
>   #include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
>   #include <keys/user-type.h>
> +#include <linux/key-type.h>
>   
>   #include <linux/device-mapper.h>
>   
> @@ -2010,6 +2011,7 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
>   	int ret;
>   	struct key *key;
>   	const struct user_key_payload *ukp;
> +	struct key_type *type;
>   
>   	/*
>   	 * Reject key_string with whitespace. dm core currently lacks code for
> @@ -2025,16 +2027,15 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
>   	if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
>   		return -EINVAL;
>   
> -	if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
> -	    strncmp(key_string, "user:", key_desc - key_string + 1))
> -		return -EINVAL;
> +	type = get_key_type(key_string, key_desc - key_string);
> +	if (!type)
> +		return -ENOENT;
>   
>   	new_key_string = kstrdup(key_string, GFP_KERNEL);
>   	if (!new_key_string)
>   		return -ENOMEM;
>   
> -	key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
> -			  key_desc + 1, NULL);
> +	key = request_key(type, key_desc + 1, NULL);
>   	if (IS_ERR(key)) {
>   		kzfree(new_key_string);
>   		return PTR_ERR(key);
> diff --git a/include/linux/key-type.h b/include/linux/key-type.h
> index bc9af55..2b2167b 100644
> --- a/include/linux/key-type.h
> +++ b/include/linux/key-type.h
> @@ -176,6 +176,8 @@ extern struct key_type key_type_keyring;
>   extern int register_key_type(struct key_type *ktype);
>   extern void unregister_key_type(struct key_type *ktype);
>   
> +extern struct key_type *get_key_type(const char *type_name, size_t string_size);
> +
>   extern int key_payload_reserve(struct key *key, size_t datalen);
>   extern int key_instantiate_and_link(struct key *key,
>   				    const void *data,
> diff --git a/security/keys/key.c b/security/keys/key.c
> index 44a80d6..ef76114 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -1156,6 +1156,48 @@ void unregister_key_type(struct key_type *ktype)
>   }
>   EXPORT_SYMBOL(unregister_key_type);
>   
> +/**
> + * get_key_type - Get the type of key using its name
> + * @type_name: Name of the key type to get
> + * @string_size: Size of the string to match
> + *
> + * The functions support null ended string (string_size == 0) as well as
> + * pointer on a string matching a number of characters (string_size > 0)
> + *
> + * Returns a pointer on the key type if successful, -ENOENT if the key type
> + * is not registered.
> + */
> +struct key_type *get_key_type(const char *type_name, size_t string_size)
> +{
> +	struct key_type *p;
> +	struct key_type *ktype = ERR_PTR(-ENOENT);
> +
> +	if (!type_name)
> +		return ktype;
> +
> +	down_write(&key_types_sem);

down_write(&key_types_sem);  changed to down_read(&key_types_sem);

> +
> +	/* Search the key type in the list */
> +	list_for_each_entry(p, &key_types_list, link) {
> +		if (string_size) {
> +			if (strncmp(p->name, type_name, string_size) == 0) {
> +				ktype = p;
> +				break;
> +			}
> +		} else {
> +			if (strcmp(p->name, type_name) == 0) {
> +				ktype = p;
> +				break;
> +			}
> +		}
> +	}
> +
> +	up_read(&key_types_sem);
> +
> +	return ktype;
> +}
> +EXPORT_SYMBOL(get_key_type);
> +
>   /*
>    * Initialise the key management state.
>    */
>
James Bottomley Jan. 18, 2020, 5:55 p.m. UTC | #2
On Fri, 2019-03-01 at 17:09 +0100, Franck LENORMAND wrote:
> @@ -2025,16 +2027,15 @@ static int crypt_set_keyring_key(struct
> crypt_config *cc, const char *key_string
>  	if (!key_desc || key_desc == key_string || !strlen(key_desc
> + 1))
>  		return -EINVAL;
>  
> -	if (strncmp(key_string, "logon:", key_desc - key_string + 1)
> &&
> -	    strncmp(key_string, "user:", key_desc - key_string + 1))
> -		return -EINVAL;
> +	type = get_key_type(key_string, key_desc - key_string);
> +	if (!type)
> +		return -ENOENT;

You can't do this.  This check ensures that the key responds correctly
to user_key_payload_locked() lower down.  To do that, the payload has
to be in a specific form.  You ensured that yours are, but dm-crypt
will now accept any key type, load the user payload blindly and create
all sorts of mayhem in the kernel because of the structural differences
in payload types.

James
diff mbox series

Patch

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index dd538e6..e25efc2 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -35,6 +35,7 @@ 
 #include <crypto/authenc.h>
 #include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
 #include <keys/user-type.h>
+#include <linux/key-type.h>
 
 #include <linux/device-mapper.h>
 
@@ -2010,6 +2011,7 @@  static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
 	int ret;
 	struct key *key;
 	const struct user_key_payload *ukp;
+	struct key_type *type;
 
 	/*
 	 * Reject key_string with whitespace. dm core currently lacks code for
@@ -2025,16 +2027,15 @@  static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
 	if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
 		return -EINVAL;
 
-	if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
-	    strncmp(key_string, "user:", key_desc - key_string + 1))
-		return -EINVAL;
+	type = get_key_type(key_string, key_desc - key_string);
+	if (!type)
+		return -ENOENT;
 
 	new_key_string = kstrdup(key_string, GFP_KERNEL);
 	if (!new_key_string)
 		return -ENOMEM;
 
-	key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
-			  key_desc + 1, NULL);
+	key = request_key(type, key_desc + 1, NULL);
 	if (IS_ERR(key)) {
 		kzfree(new_key_string);
 		return PTR_ERR(key);
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index bc9af55..2b2167b 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -176,6 +176,8 @@  extern struct key_type key_type_keyring;
 extern int register_key_type(struct key_type *ktype);
 extern void unregister_key_type(struct key_type *ktype);
 
+extern struct key_type *get_key_type(const char *type_name, size_t string_size);
+
 extern int key_payload_reserve(struct key *key, size_t datalen);
 extern int key_instantiate_and_link(struct key *key,
 				    const void *data,
diff --git a/security/keys/key.c b/security/keys/key.c
index 44a80d6..ef76114 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1156,6 +1156,48 @@  void unregister_key_type(struct key_type *ktype)
 }
 EXPORT_SYMBOL(unregister_key_type);
 
+/**
+ * get_key_type - Get the type of key using its name
+ * @type_name: Name of the key type to get
+ * @string_size: Size of the string to match
+ *
+ * The functions support null ended string (string_size == 0) as well as
+ * pointer on a string matching a number of characters (string_size > 0)
+ *
+ * Returns a pointer on the key type if successful, -ENOENT if the key type
+ * is not registered.
+ */
+struct key_type *get_key_type(const char *type_name, size_t string_size)
+{
+	struct key_type *p;
+	struct key_type *ktype = ERR_PTR(-ENOENT);
+
+	if (!type_name)
+		return ktype;
+
+	down_write(&key_types_sem);
+
+	/* Search the key type in the list */
+	list_for_each_entry(p, &key_types_list, link) {
+		if (string_size) {
+			if (strncmp(p->name, type_name, string_size) == 0) {
+				ktype = p;
+				break;
+			}
+		} else {
+			if (strcmp(p->name, type_name) == 0) {
+				ktype = p;
+				break;
+			}
+		}
+	}
+
+	up_read(&key_types_sem);
+
+	return ktype;
+}
+EXPORT_SYMBOL(get_key_type);
+
 /*
  * Initialise the key management state.
  */