All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] KEYS: Use preparsing in most key types
@ 2014-03-20 12:04 David Howells
  2014-03-20 12:04 ` [PATCH 01/12] KEYS: Provide a generic instantiation function David Howells
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:04 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel


Here are a set of patches that make all but encrypted and trusted keys use
preparsing.  Unfortunately, encrypted and trusted keys incorrectly use the
update op to alter a key, so other changes will need to be made for them.

These changes permit payload parsing when instantiating or updating a key to be
done before locks are taken and to determine the amount of quota that will be
required in advance.  The latter will make it possible to do LRU discard before
any locks are taken.

They can be found here also:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-preparse-1

David
---
David Howells (12):
      KEYS: Provide a generic instantiation function
      KEYS: struct key_preparsed_payload should have two payload pointers
      KEYS: Allow expiry time to be set when preparsing a key
      KEYS: Call ->free_preparse() even after ->preparse() returns an error
      KEYS: user: Use key preparsing
      KEYS: Ceph: Use key preparsing
      KEYS: Ceph: Use user_match()
      KEYS: DNS: Use key preparsing
      KEYS: RxRPC: Use key preparsing
      KEYS: big_key: Use key preparsing
      KEYS: keyring: Provide key preparsing
      KEYS: request_key_auth: Provide key preparsing


 Documentation/security/keys.txt          |   14 ++-
 crypto/asymmetric_keys/asymmetric_type.c |   27 -----
 crypto/asymmetric_keys/x509_public_key.c |    2 
 fs/nfs/idmap.c                           |    8 +
 include/keys/big_key-type.h              |    3 -
 include/keys/user-type.h                 |    3 -
 include/linux/key-type.h                 |    5 +
 net/ceph/crypto.c                        |   26 +++--
 net/dns_resolver/dns_key.c               |   43 +++++---
 net/rxrpc/ar-key.c                       |  165 ++++++++++++++++++------------
 security/keys/big_key.c                  |   41 +++++--
 security/keys/encrypted-keys/encrypted.c |    2 
 security/keys/key.c                      |   49 ++++++++-
 security/keys/keyring.c                  |   34 ++++--
 security/keys/request_key_auth.c         |   13 ++
 security/keys/user_defined.c             |   41 ++++---
 16 files changed, 291 insertions(+), 185 deletions(-)


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

* [PATCH 01/12] KEYS: Provide a generic instantiation function
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
@ 2014-03-20 12:04 ` David Howells
  2014-03-20 12:04 ` [PATCH 02/12] KEYS: struct key_preparsed_payload should have two payload pointers David Howells
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:04 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Provide a generic instantiation function for key types that use the preparse
hook.  This makes it easier to prereserve key quota before keyrings get locked
to retain the new key.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/asymmetric_type.c |   25 +------------------------
 include/linux/key-type.h                 |    2 ++
 security/keys/key.c                      |   30 ++++++++++++++++++++++++++++++
 3 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index b77eb5304788..c1fe0fcee8e3 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -164,29 +164,6 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
 }
 
 /*
- * Instantiate a asymmetric_key defined key.  The key was preparsed, so we just
- * have to transfer the data here.
- */
-static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-{
-	int ret;
-
-	pr_devel("==>%s()\n", __func__);
-
-	ret = key_payload_reserve(key, prep->quotalen);
-	if (ret == 0) {
-		key->type_data.p[0] = prep->type_data[0];
-		key->type_data.p[1] = prep->type_data[1];
-		key->payload.data = prep->payload;
-		prep->type_data[0] = NULL;
-		prep->type_data[1] = NULL;
-		prep->payload = NULL;
-	}
-	pr_devel("<==%s() = %d\n", __func__, ret);
-	return ret;
-}
-
-/*
  * dispose of the data dangling from the corpse of a asymmetric key
  */
 static void asymmetric_key_destroy(struct key *key)
@@ -205,7 +182,7 @@ struct key_type key_type_asymmetric = {
 	.name		= "asymmetric",
 	.preparse	= asymmetric_key_preparse,
 	.free_preparse	= asymmetric_key_free_preparse,
-	.instantiate	= asymmetric_key_instantiate,
+	.instantiate	= generic_key_instantiate,
 	.match		= asymmetric_key_match,
 	.destroy	= asymmetric_key_destroy,
 	.describe	= asymmetric_key_describe,
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index a74c3a84dfdd..88503dca2a57 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -159,5 +159,7 @@ static inline int key_negate_and_link(struct key *key,
 	return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey);
 }
 
+extern int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep);
+
 #endif /* CONFIG_KEYS */
 #endif /* _LINUX_KEY_TYPE_H */
diff --git a/security/keys/key.c b/security/keys/key.c
index 6e21c11e48bc..ee74c882d36d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1024,6 +1024,36 @@ void key_invalidate(struct key *key)
 EXPORT_SYMBOL(key_invalidate);
 
 /**
+ * generic_key_instantiate - Simple instantiation of a key from preparsed data
+ * @key: The key to be instantiated
+ * @prep: The preparsed data to load.
+ *
+ * Instantiate a key from preparsed data.  We assume we can just copy the data
+ * in directly and clear the old pointers.
+ *
+ * This can be pointed to directly by the key type instantiate op pointer.
+ */
+int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
+{
+	int ret;
+
+	pr_devel("==>%s()\n", __func__);
+
+	ret = key_payload_reserve(key, prep->quotalen);
+	if (ret == 0) {
+		key->type_data.p[0] = prep->type_data[0];
+		key->type_data.p[1] = prep->type_data[1];
+		rcu_assign_keypointer(key, prep->payload);
+		prep->type_data[0] = NULL;
+		prep->type_data[1] = NULL;
+		prep->payload = NULL;
+	}
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL(generic_key_instantiate);
+
+/**
  * register_key_type - Register a type of key.
  * @ktype: The new key type.
  *


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

* [PATCH 02/12] KEYS: struct key_preparsed_payload should have two payload pointers
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
  2014-03-20 12:04 ` [PATCH 01/12] KEYS: Provide a generic instantiation function David Howells
@ 2014-03-20 12:04 ` David Howells
  2014-03-20 12:04 ` [PATCH 03/12] KEYS: Allow expiry time to be set when preparsing a key David Howells
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:04 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

struct key_preparsed_payload should have two payload pointers to correspond
with those in struct key.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 crypto/asymmetric_keys/asymmetric_type.c |    2 +-
 crypto/asymmetric_keys/x509_public_key.c |    2 +-
 include/linux/key-type.h                 |    2 +-
 security/keys/encrypted-keys/encrypted.c |    2 +-
 security/keys/key.c                      |    6 ++++--
 5 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index c1fe0fcee8e3..21960a4e74e8 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -156,7 +156,7 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
 	pr_devel("==>%s()\n", __func__);
 
 	if (subtype) {
-		subtype->destroy(prep->payload);
+		subtype->destroy(prep->payload[0]);
 		module_put(subtype->owner);
 	}
 	kfree(prep->type_data[1]);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 382ef0d2ff2e..3fc8a0634ed7 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -177,7 +177,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 	__module_get(public_key_subtype.owner);
 	prep->type_data[0] = &public_key_subtype;
 	prep->type_data[1] = cert->fingerprint;
-	prep->payload = cert->pub;
+	prep->payload[0] = cert->pub;
 	prep->description = desc;
 	prep->quotalen = 100;
 
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 88503dca2a57..d2b4845d74bf 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -41,7 +41,7 @@ struct key_construction {
 struct key_preparsed_payload {
 	char		*description;	/* Proposed key description (or NULL) */
 	void		*type_data[2];	/* Private key-type data */
-	void		*payload;	/* Proposed payload */
+	void		*payload[2];	/* Proposed payload */
 	const void	*data;		/* Raw data */
 	size_t		datalen;	/* Raw datalen */
 	size_t		quotalen;	/* Quota length for proposed payload */
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 9e1e005c7596..9a3b29175530 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -811,7 +811,7 @@ static int encrypted_instantiate(struct key *key,
 		goto out;
 	}
 
-	rcu_assign_keypointer(key, epayload);
+	prep->payload[0] = epayload;
 out:
 	kfree(datablob);
 	return ret;
diff --git a/security/keys/key.c b/security/keys/key.c
index ee74c882d36d..686b10e81054 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1043,10 +1043,12 @@ int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 	if (ret == 0) {
 		key->type_data.p[0] = prep->type_data[0];
 		key->type_data.p[1] = prep->type_data[1];
-		rcu_assign_keypointer(key, prep->payload);
+		rcu_assign_keypointer(key, prep->payload[0]);
+		key->payload.data2[1] = prep->payload[1];
 		prep->type_data[0] = NULL;
 		prep->type_data[1] = NULL;
-		prep->payload = NULL;
+		prep->payload[0] = NULL;
+		prep->payload[1] = NULL;
 	}
 	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;


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

* [PATCH 03/12] KEYS: Allow expiry time to be set when preparsing a key
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
  2014-03-20 12:04 ` [PATCH 01/12] KEYS: Provide a generic instantiation function David Howells
  2014-03-20 12:04 ` [PATCH 02/12] KEYS: struct key_preparsed_payload should have two payload pointers David Howells
@ 2014-03-20 12:04 ` David Howells
  2014-03-20 12:05 ` [PATCH 04/12] KEYS: Call ->free_preparse() even after ->preparse() returns an error David Howells
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:04 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Allow a key type's preparsing routine to set the expiry time for a key.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/security/keys.txt |   10 +++++++---
 include/linux/key-type.h        |    1 +
 security/keys/key.c             |    8 ++++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index a4c33f1a7c6d..315cf96a41a2 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1150,20 +1150,24 @@ The structure has a number of fields, some of which are mandatory:
 		const void	*data;
 		size_t		datalen;
 		size_t		quotalen;
+		time_t		expiry;
 	};
 
      Before calling the method, the caller will fill in data and datalen with
      the payload blob parameters; quotalen will be filled in with the default
-     quota size from the key type and the rest will be cleared.
+     quota size from the key type; expiry will be set to TIME_T_MAX and the
+     rest will be cleared.
 
      If a description can be proposed from the payload contents, that should be
      attached as a string to the description field.  This will be used for the
      key description if the caller of add_key() passes NULL or "".
 
      The method can attach anything it likes to type_data[] and payload.  These
-     are merely passed along to the instantiate() or update() operations.
+     are merely passed along to the instantiate() or update() operations.  If
+     set, the expiry time will be applied to the key if it is instantiated from
+     this data.
 
-     The method should return 0 if success ful or a negative error code
+     The method should return 0 if successful or a negative error code
      otherwise.
 
      
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index d2b4845d74bf..44792ee649de 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -45,6 +45,7 @@ struct key_preparsed_payload {
 	const void	*data;		/* Raw data */
 	size_t		datalen;	/* Raw datalen */
 	size_t		quotalen;	/* Quota length for proposed payload */
+	time_t		expiry;		/* Expiry time of key */
 	bool		trusted;	/* True if key is trusted */
 };
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 686b10e81054..6a37856d428d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -437,6 +437,11 @@ static int __key_instantiate_and_link(struct key *key,
 			/* disable the authorisation key */
 			if (authkey)
 				key_revoke(authkey);
+
+			if (prep->expiry != TIME_T_MAX) {
+				key->expiry = prep->expiry;
+				key_schedule_gc(prep->expiry + key_gc_delay);
+			}
 		}
 	}
 
@@ -479,6 +484,7 @@ int key_instantiate_and_link(struct key *key,
 	prep.data = data;
 	prep.datalen = datalen;
 	prep.quotalen = key->type->def_datalen;
+	prep.expiry = TIME_T_MAX;
 	if (key->type->preparse) {
 		ret = key->type->preparse(&prep);
 		if (ret < 0)
@@ -811,6 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 	prep.datalen = plen;
 	prep.quotalen = index_key.type->def_datalen;
 	prep.trusted = flags & KEY_ALLOC_TRUSTED;
+	prep.expiry = TIME_T_MAX;
 	if (index_key.type->preparse) {
 		ret = index_key.type->preparse(&prep);
 		if (ret < 0) {
@@ -941,6 +948,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
 	prep.data = payload;
 	prep.datalen = plen;
 	prep.quotalen = key->type->def_datalen;
+	prep.expiry = TIME_T_MAX;
 	if (key->type->preparse) {
 		ret = key->type->preparse(&prep);
 		if (ret < 0)


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

* [PATCH 04/12] KEYS: Call ->free_preparse() even after ->preparse() returns an error
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (2 preceding siblings ...)
  2014-03-20 12:04 ` [PATCH 03/12] KEYS: Allow expiry time to be set when preparsing a key David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 05/12] KEYS: user: Use key preparsing David Howells
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Call the ->free_preparse() key type op even after ->preparse() returns an
error as it does cleaning up type stuff.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/security/keys.txt |    4 +++-
 security/keys/key.c             |    9 ++++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 315cf96a41a2..3bbec087fc5f 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1176,7 +1176,9 @@ The structure has a number of fields, some of which are mandatory:
      This method is only required if the preparse() method is provided,
      otherwise it is unused.  It cleans up anything attached to the
      description, type_data and payload fields of the key_preparsed_payload
-     struct as filled in by the preparse() method.
+     struct as filled in by the preparse() method.  If will always be called
+     after preparse() returns successfully, even if instantiate() or update()
+     succeed.
 
 
  (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
diff --git a/security/keys/key.c b/security/keys/key.c
index 6a37856d428d..c6c0e162c4ba 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -494,7 +494,7 @@ int key_instantiate_and_link(struct key *key,
 	if (keyring) {
 		ret = __key_link_begin(keyring, &key->index_key, &edit);
 		if (ret < 0)
-			goto error_free_preparse;
+			goto error;
 	}
 
 	ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit);
@@ -502,10 +502,9 @@ int key_instantiate_and_link(struct key *key,
 	if (keyring)
 		__key_link_end(keyring, &key->index_key, edit);
 
-error_free_preparse:
+error:
 	if (key->type->preparse)
 		key->type->free_preparse(&prep);
-error:
 	return ret;
 }
 
@@ -822,7 +821,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 		ret = index_key.type->preparse(&prep);
 		if (ret < 0) {
 			key_ref = ERR_PTR(ret);
-			goto error_put_type;
+			goto error_free_prep;
 		}
 		if (!index_key.description)
 			index_key.description = prep.description;
@@ -964,9 +963,9 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
 
 	up_write(&key->sem);
 
+error:
 	if (key->type->preparse)
 		key->type->free_preparse(&prep);
-error:
 	return ret;
 }
 EXPORT_SYMBOL(key_update);


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

* [PATCH 05/12] KEYS: user: Use key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (3 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 04/12] KEYS: Call ->free_preparse() even after ->preparse() returns an error David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 06/12] KEYS: Ceph: " David Howells
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Make use of key preparsing in user-defined and logon keys so that quota size
determination can take place prior to keyring locking when a key is being
added.

Also the idmapper key types need to change to match as they use the
user-defined key type routines.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/nfs/idmap.c               |    8 ++++++--
 include/keys/user-type.h     |    3 ++-
 security/keys/user_defined.c |   41 ++++++++++++++++++++++-------------------
 3 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 567983d2c0eb..59b217a3266d 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -174,7 +174,9 @@ static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
 
 static struct key_type key_type_id_resolver = {
 	.name		= "id_resolver",
-	.instantiate	= user_instantiate,
+	.preparse	= user_preparse,
+	.free_preparse	= user_free_preparse,
+	.instantiate	= generic_key_instantiate,
 	.match		= user_match,
 	.revoke		= user_revoke,
 	.destroy	= user_destroy,
@@ -394,7 +396,9 @@ static const struct rpc_pipe_ops idmap_upcall_ops = {
 
 static struct key_type key_type_id_resolver_legacy = {
 	.name		= "id_legacy",
-	.instantiate	= user_instantiate,
+	.preparse	= user_preparse,
+	.free_preparse	= user_free_preparse,
+	.instantiate	= generic_key_instantiate,
 	.match		= user_match,
 	.revoke		= user_revoke,
 	.destroy	= user_destroy,
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 5e452c84f1e6..3ab1873a4bfa 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -37,7 +37,8 @@ extern struct key_type key_type_logon;
 
 struct key_preparsed_payload;
 
-extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep);
+extern int user_preparse(struct key_preparsed_payload *prep);
+extern void user_free_preparse(struct key_preparsed_payload *prep);
 extern int user_update(struct key *key, struct key_preparsed_payload *prep);
 extern int user_match(const struct key *key, const void *criterion);
 extern void user_revoke(struct key *key);
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index faa2caeb593f..eee340011f2b 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -27,7 +27,9 @@ static int logon_vet_description(const char *desc);
 struct key_type key_type_user = {
 	.name			= "user",
 	.def_lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
-	.instantiate		= user_instantiate,
+	.preparse		= user_preparse,
+	.free_preparse		= user_free_preparse,
+	.instantiate		= generic_key_instantiate,
 	.update			= user_update,
 	.match			= user_match,
 	.revoke			= user_revoke,
@@ -47,7 +49,9 @@ EXPORT_SYMBOL_GPL(key_type_user);
 struct key_type key_type_logon = {
 	.name			= "logon",
 	.def_lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
-	.instantiate		= user_instantiate,
+	.preparse		= user_preparse,
+	.free_preparse		= user_free_preparse,
+	.instantiate		= generic_key_instantiate,
 	.update			= user_update,
 	.match			= user_match,
 	.revoke			= user_revoke,
@@ -58,38 +62,37 @@ struct key_type key_type_logon = {
 EXPORT_SYMBOL_GPL(key_type_logon);
 
 /*
- * instantiate a user defined key
+ * Preparse a user defined key payload
  */
-int user_instantiate(struct key *key, struct key_preparsed_payload *prep)
+int user_preparse(struct key_preparsed_payload *prep)
 {
 	struct user_key_payload *upayload;
 	size_t datalen = prep->datalen;
-	int ret;
 
-	ret = -EINVAL;
 	if (datalen <= 0 || datalen > 32767 || !prep->data)
-		goto error;
-
-	ret = key_payload_reserve(key, datalen);
-	if (ret < 0)
-		goto error;
+		return -EINVAL;
 
-	ret = -ENOMEM;
 	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
 	if (!upayload)
-		goto error;
+		return -ENOMEM;
 
 	/* attach the data */
+	prep->quotalen = datalen;
+	prep->payload[0] = upayload;
 	upayload->datalen = datalen;
 	memcpy(upayload->data, prep->data, datalen);
-	rcu_assign_keypointer(key, upayload);
-	ret = 0;
-
-error:
-	return ret;
+	return 0;
 }
+EXPORT_SYMBOL_GPL(user_preparse);
 
-EXPORT_SYMBOL_GPL(user_instantiate);
+/*
+ * Free a preparse of a user defined key payload
+ */
+void user_free_preparse(struct key_preparsed_payload *prep)
+{
+	kfree(prep->payload[0]);
+}
+EXPORT_SYMBOL_GPL(user_free_preparse);
 
 /*
  * update a user defined key


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

* [PATCH 06/12] KEYS: Ceph: Use key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (4 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 05/12] KEYS: user: Use key preparsing David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 07/12] KEYS: Ceph: Use user_match() David Howells
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, Sage Weil, linux-security-module, Tommi Virtanen, linux-kernel

Make use of key preparsing in Ceph so that quota size determination can take
place prior to keyring locking when a key is being added.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Tommi Virtanen <tommi.virtanen@dreamhost.com>
cc: Sage Weil <sage@newdream.net>
---

 net/ceph/crypto.c |   24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 6e7a236525b6..2c8078d990ee 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -423,8 +423,7 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
 	}
 }
 
-static int ceph_key_instantiate(struct key *key,
-				struct key_preparsed_payload *prep)
+static int ceph_key_preparse(struct key_preparsed_payload *prep)
 {
 	struct ceph_crypto_key *ckey;
 	size_t datalen = prep->datalen;
@@ -435,10 +434,6 @@ static int ceph_key_instantiate(struct key *key,
 	if (datalen <= 0 || datalen > 32767 || !prep->data)
 		goto err;
 
-	ret = key_payload_reserve(key, datalen);
-	if (ret < 0)
-		goto err;
-
 	ret = -ENOMEM;
 	ckey = kmalloc(sizeof(*ckey), GFP_KERNEL);
 	if (!ckey)
@@ -450,7 +445,8 @@ static int ceph_key_instantiate(struct key *key,
 	if (ret < 0)
 		goto err_ckey;
 
-	key->payload.data = ckey;
+	prep->payload[0] = ckey;
+	prep->quotalen = datalen;
 	return 0;
 
 err_ckey:
@@ -459,12 +455,20 @@ err:
 	return ret;
 }
 
+static void ceph_key_free_preparse(struct key_preparsed_payload *prep)
+{
+	struct ceph_crypto_key *ckey = prep->payload[0];
+	ceph_crypto_key_destroy(ckey);
+	kfree(ckey);
+}
+
 static int ceph_key_match(const struct key *key, const void *description)
 {
 	return strcmp(key->description, description) == 0;
 }
 
-static void ceph_key_destroy(struct key *key) {
+static void ceph_key_destroy(struct key *key)
+{
 	struct ceph_crypto_key *ckey = key->payload.data;
 
 	ceph_crypto_key_destroy(ckey);
@@ -473,7 +477,9 @@ static void ceph_key_destroy(struct key *key) {
 
 struct key_type key_type_ceph = {
 	.name		= "ceph",
-	.instantiate	= ceph_key_instantiate,
+	.preparse	= ceph_key_preparse,
+	.free_preparse	= ceph_key_free_preparse,
+	.instantiate	= generic_key_instantiate,
 	.match		= ceph_key_match,
 	.destroy	= ceph_key_destroy,
 };


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

* [PATCH 07/12] KEYS: Ceph: Use user_match()
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (5 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 06/12] KEYS: Ceph: " David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 08/12] KEYS: DNS: Use key preparsing David Howells
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings
  Cc: dhowells, Sage Weil, linux-security-module, Tommi Virtanen, linux-kernel

Ceph can use user_match() instead of defining its own identical function.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Tommi Virtanen <tommi.virtanen@dreamhost.com>
cc: Sage Weil <sage@newdream.net>
---

 net/ceph/crypto.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 2c8078d990ee..ffeba8f9dda9 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -8,6 +8,7 @@
 #include <linux/key-type.h>
 
 #include <keys/ceph-type.h>
+#include <keys/user-type.h>
 #include <linux/ceph/decode.h>
 #include "crypto.h"
 
@@ -462,11 +463,6 @@ static void ceph_key_free_preparse(struct key_preparsed_payload *prep)
 	kfree(ckey);
 }
 
-static int ceph_key_match(const struct key *key, const void *description)
-{
-	return strcmp(key->description, description) == 0;
-}
-
 static void ceph_key_destroy(struct key *key)
 {
 	struct ceph_crypto_key *ckey = key->payload.data;
@@ -480,7 +476,7 @@ struct key_type key_type_ceph = {
 	.preparse	= ceph_key_preparse,
 	.free_preparse	= ceph_key_free_preparse,
 	.instantiate	= generic_key_instantiate,
-	.match		= ceph_key_match,
+	.match		= user_match,
 	.destroy	= ceph_key_destroy,
 };
 


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

* [PATCH 08/12] KEYS: DNS: Use key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (6 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 07/12] KEYS: Ceph: Use user_match() David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 09/12] KEYS: RxRPC: " David Howells
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Make use of key preparsing in the DNS resolver so that quota size determination
can take place prior to keyring locking when a key is being added.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/dns_resolver/dns_key.c |   43 +++++++++++++++++++++++++------------------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index bf8584339048..f380b2c58178 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -46,7 +46,7 @@ const struct cred *dns_resolver_cache;
 #define	DNS_ERRORNO_OPTION	"dnserror"
 
 /*
- * Instantiate a user defined key for dns_resolver.
+ * Preparse instantiation data for a dns_resolver key.
  *
  * The data must be a NUL-terminated string, with the NUL char accounted in
  * datalen.
@@ -58,17 +58,15 @@ const struct cred *dns_resolver_cache;
  *        "ip1,ip2,...#foo=bar"
  */
 static int
-dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
+dns_resolver_preparse(struct key_preparsed_payload *prep)
 {
 	struct user_key_payload *upayload;
 	unsigned long derrno;
 	int ret;
-	size_t datalen = prep->datalen, result_len = 0;
+	int datalen = prep->datalen, result_len = 0;
 	const char *data = prep->data, *end, *opt;
 
-	kenter("%%%d,%s,'%*.*s',%zu",
-	       key->serial, key->description,
-	       (int)datalen, (int)datalen, data, datalen);
+	kenter("'%*.*s',%u", datalen, datalen, data, datalen);
 
 	if (datalen <= 1 || !data || data[datalen - 1] != '\0')
 		return -EINVAL;
@@ -95,8 +93,7 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
 			opt_len = next_opt - opt;
 			if (!opt_len) {
 				printk(KERN_WARNING
-				       "Empty option to dns_resolver key %d\n",
-				       key->serial);
+				       "Empty option to dns_resolver key\n");
 				return -EINVAL;
 			}
 
@@ -125,30 +122,28 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
 					goto bad_option_value;
 
 				kdebug("dns error no. = %lu", derrno);
-				key->type_data.x[0] = -derrno;
+				prep->type_data[0] = ERR_PTR(-derrno);
 				continue;
 			}
 
 		bad_option_value:
 			printk(KERN_WARNING
-			       "Option '%*.*s' to dns_resolver key %d:"
+			       "Option '%*.*s' to dns_resolver key:"
 			       " bad/missing value\n",
-			       opt_nlen, opt_nlen, opt, key->serial);
+			       opt_nlen, opt_nlen, opt);
 			return -EINVAL;
 		} while (opt = next_opt + 1, opt < end);
 	}
 
 	/* don't cache the result if we're caching an error saying there's no
 	 * result */
-	if (key->type_data.x[0]) {
-		kleave(" = 0 [h_error %ld]", key->type_data.x[0]);
+	if (prep->type_data[0]) {
+		kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0]));
 		return 0;
 	}
 
 	kdebug("store result");
-	ret = key_payload_reserve(key, result_len);
-	if (ret < 0)
-		return -EINVAL;
+	prep->quotalen = result_len;
 
 	upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL);
 	if (!upayload) {
@@ -159,13 +154,23 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
 	upayload->datalen = result_len;
 	memcpy(upayload->data, data, result_len);
 	upayload->data[result_len] = '\0';
-	rcu_assign_pointer(key->payload.data, upayload);
 
+	prep->payload[0] = upayload;
 	kleave(" = 0");
 	return 0;
 }
 
 /*
+ * Clean up the preparse data
+ */
+static void dns_resolver_free_preparse(struct key_preparsed_payload *prep)
+{
+	pr_devel("==>%s()\n", __func__);
+
+	kfree(prep->payload[0]);
+}
+
+/*
  * The description is of the form "[<type>:]<domain_name>"
  *
  * The domain name may be a simple name or an absolute domain name (which
@@ -234,7 +239,9 @@ static long dns_resolver_read(const struct key *key,
 
 struct key_type key_type_dns_resolver = {
 	.name		= "dns_resolver",
-	.instantiate	= dns_resolver_instantiate,
+	.preparse	= dns_resolver_preparse,
+	.free_preparse	= dns_resolver_free_preparse,
+	.instantiate	= generic_key_instantiate,
 	.match		= dns_resolver_match,
 	.revoke		= user_revoke,
 	.destroy	= user_destroy,


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

* [PATCH 09/12] KEYS: RxRPC: Use key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (7 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 08/12] KEYS: DNS: Use key preparsing David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:05 ` [PATCH 10/12] KEYS: big_key: " David Howells
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Make use of key preparsing in the RxRPC protocol so that quota size
determination can take place prior to keyring locking when a key is being
added.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-key.c |  165 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 97 insertions(+), 68 deletions(-)

diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index 7633a752c65e..58a3641227d4 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -26,8 +26,10 @@
 #include "ar-internal.h"
 
 static int rxrpc_vet_description_s(const char *);
-static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *);
-static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *);
+static int rxrpc_preparse(struct key_preparsed_payload *);
+static int rxrpc_preparse_s(struct key_preparsed_payload *);
+static void rxrpc_free_preparse(struct key_preparsed_payload *);
+static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
 static void rxrpc_destroy(struct key *);
 static void rxrpc_destroy_s(struct key *);
 static void rxrpc_describe(const struct key *, struct seq_file *);
@@ -39,7 +41,9 @@ static long rxrpc_read(const struct key *, char __user *, size_t);
  */
 struct key_type key_type_rxrpc = {
 	.name		= "rxrpc",
-	.instantiate	= rxrpc_instantiate,
+	.preparse	= rxrpc_preparse,
+	.free_preparse	= rxrpc_free_preparse,
+	.instantiate	= generic_key_instantiate,
 	.match		= user_match,
 	.destroy	= rxrpc_destroy,
 	.describe	= rxrpc_describe,
@@ -54,7 +58,9 @@ EXPORT_SYMBOL(key_type_rxrpc);
 struct key_type key_type_rxrpc_s = {
 	.name		= "rxrpc_s",
 	.vet_description = rxrpc_vet_description_s,
-	.instantiate	= rxrpc_instantiate_s,
+	.preparse	= rxrpc_preparse_s,
+	.free_preparse	= rxrpc_free_preparse_s,
+	.instantiate	= generic_key_instantiate,
 	.match		= user_match,
 	.destroy	= rxrpc_destroy_s,
 	.describe	= rxrpc_describe,
@@ -81,13 +87,13 @@ static int rxrpc_vet_description_s(const char *desc)
  * parse an RxKAD type XDR format token
  * - the caller guarantees we have at least 4 words
  */
-static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
-				       unsigned int toklen)
+static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
+				    size_t datalen,
+				    const __be32 *xdr, unsigned int toklen)
 {
 	struct rxrpc_key_token *token, **pptoken;
 	size_t plen;
 	u32 tktlen;
-	int ret;
 
 	_enter(",{%x,%x,%x,%x},%u",
 	       ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -103,9 +109,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
 		return -EKEYREJECTED;
 
 	plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
-	ret = key_payload_reserve(key, key->datalen + plen);
-	if (ret < 0)
-		return ret;
+	prep->quotalen = datalen + plen;
 
 	plen -= sizeof(*token);
 	token = kzalloc(sizeof(*token), GFP_KERNEL);
@@ -146,16 +150,16 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
 		       token->kad->ticket[6], token->kad->ticket[7]);
 
 	/* count the number of tokens attached */
-	key->type_data.x[0]++;
+	prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1);
 
 	/* attach the data */
-	for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
+	for (pptoken = (struct rxrpc_key_token **)&prep->payload[0];
 	     *pptoken;
 	     pptoken = &(*pptoken)->next)
 		continue;
 	*pptoken = token;
-	if (token->kad->expiry < key->expiry)
-		key->expiry = token->kad->expiry;
+	if (token->kad->expiry < prep->expiry)
+		prep->expiry = token->kad->expiry;
 
 	_leave(" = 0");
 	return 0;
@@ -418,8 +422,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
  * parse an RxK5 type XDR format token
  * - the caller guarantees we have at least 4 words
  */
-static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
-				      unsigned int toklen)
+static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep,
+				   size_t datalen,
+				   const __be32 *xdr, unsigned int toklen)
 {
 	struct rxrpc_key_token *token, **pptoken;
 	struct rxk5_key *rxk5;
@@ -432,9 +437,7 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
 
 	/* reserve some payload space for this subkey - the length of the token
 	 * is a reasonable approximation */
-	ret = key_payload_reserve(key, key->datalen + toklen);
-	if (ret < 0)
-		return ret;
+	prep->quotalen = datalen + toklen;
 
 	token = kzalloc(sizeof(*token), GFP_KERNEL);
 	if (!token)
@@ -520,14 +523,14 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
 	if (toklen != 0)
 		goto inval;
 
-	/* attach the payload to the key */
-	for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
+	/* attach the payload */
+	for (pptoken = (struct rxrpc_key_token **)&prep->payload[0];
 	     *pptoken;
 	     pptoken = &(*pptoken)->next)
 		continue;
 	*pptoken = token;
-	if (token->kad->expiry < key->expiry)
-		key->expiry = token->kad->expiry;
+	if (token->kad->expiry < prep->expiry)
+		prep->expiry = token->kad->expiry;
 
 	_leave(" = 0");
 	return 0;
@@ -545,16 +548,17 @@ error:
  * attempt to parse the data as the XDR format
  * - the caller guarantees we have more than 7 words
  */
-static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen)
+static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
 {
-	const __be32 *xdr = data, *token;
+	const __be32 *xdr = prep->data, *token;
 	const char *cp;
 	unsigned int len, tmp, loop, ntoken, toklen, sec_ix;
+	size_t datalen = prep->datalen;
 	int ret;
 
 	_enter(",{%x,%x,%x,%x},%zu",
 	       ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
-	       datalen);
+	       prep->datalen);
 
 	if (datalen > AFSTOKEN_LENGTH_MAX)
 		goto not_xdr;
@@ -635,13 +639,13 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
 
 		switch (sec_ix) {
 		case RXRPC_SECURITY_RXKAD:
-			ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
+			ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, toklen);
 			if (ret != 0)
 				goto error;
 			break;
 
 		case RXRPC_SECURITY_RXK5:
-			ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen);
+			ret = rxrpc_preparse_xdr_rxk5(prep, datalen, xdr, toklen);
 			if (ret != 0)
 				goto error;
 			break;
@@ -665,8 +669,9 @@ error:
 }
 
 /*
- * instantiate an rxrpc defined key
- * data should be of the form:
+ * Preparse an rxrpc defined key.
+ *
+ * Data should be of the form:
  *	OFFSET	LEN	CONTENT
  *	0	4	key interface version number
  *	4	2	security index (type)
@@ -678,7 +683,7 @@ error:
  *
  * if no data is provided, then a no-security key is made
  */
-static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep)
+static int rxrpc_preparse(struct key_preparsed_payload *prep)
 {
 	const struct rxrpc_key_data_v1 *v1;
 	struct rxrpc_key_token *token, **pp;
@@ -686,7 +691,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep
 	u32 kver;
 	int ret;
 
-	_enter("{%x},,%zu", key_serial(key), prep->datalen);
+	_enter("%zu", prep->datalen);
 
 	/* handle a no-security key */
 	if (!prep->data && prep->datalen == 0)
@@ -694,7 +699,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep
 
 	/* determine if the XDR payload format is being used */
 	if (prep->datalen > 7 * 4) {
-		ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen);
+		ret = rxrpc_preparse_xdr(prep);
 		if (ret != -EPROTO)
 			return ret;
 	}
@@ -743,9 +748,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep
 		goto error;
 
 	plen = sizeof(*token->kad) + v1->ticket_length;
-	ret = key_payload_reserve(key, plen + sizeof(*token));
-	if (ret < 0)
-		goto error;
+	prep->quotalen = plen + sizeof(*token);
 
 	ret = -ENOMEM;
 	token = kzalloc(sizeof(*token), GFP_KERNEL);
@@ -762,15 +765,16 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep
 	memcpy(&token->kad->session_key, &v1->session_key, 8);
 	memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
 
-	/* attach the data */
-	key->type_data.x[0]++;
+	/* count the number of tokens attached */
+	prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1);
 
-	pp = (struct rxrpc_key_token **)&key->payload.data;
+	/* attach the data */
+	pp = (struct rxrpc_key_token **)&prep->payload[0];
 	while (*pp)
 		pp = &(*pp)->next;
 	*pp = token;
-	if (token->kad->expiry < key->expiry)
-		key->expiry = token->kad->expiry;
+	if (token->kad->expiry < prep->expiry)
+		prep->expiry = token->kad->expiry;
 	token = NULL;
 	ret = 0;
 
@@ -781,20 +785,55 @@ error:
 }
 
 /*
- * instantiate a server secret key
- * data should be a pointer to the 8-byte secret key
+ * Free token list.
  */
-static int rxrpc_instantiate_s(struct key *key,
-			       struct key_preparsed_payload *prep)
+static void rxrpc_free_token_list(struct rxrpc_key_token *token)
+{
+	struct rxrpc_key_token *next;
+
+	for (; token; token = next) {
+		next = token->next;
+		switch (token->security_index) {
+		case RXRPC_SECURITY_RXKAD:
+			kfree(token->kad);
+			break;
+		case RXRPC_SECURITY_RXK5:
+			if (token->k5)
+				rxrpc_rxk5_free(token->k5);
+			break;
+		default:
+			printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
+			       token->security_index);
+			BUG();
+		}
+
+		kfree(token);
+	}
+}
+
+/*
+ * Clean up preparse data.
+ */
+static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
+{
+	rxrpc_free_token_list(prep->payload[0]);
+}
+
+/*
+ * Preparse a server secret key.
+ *
+ * The data should be the 8-byte secret key.
+ */
+static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
 {
 	struct crypto_blkcipher *ci;
 
-	_enter("{%x},,%zu", key_serial(key), prep->datalen);
+	_enter("%zu", prep->datalen);
 
 	if (prep->datalen != 8)
 		return -EINVAL;
 
-	memcpy(&key->type_data, prep->data, 8);
+	memcpy(&prep->type_data, prep->data, 8);
 
 	ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(ci)) {
@@ -805,36 +844,26 @@ static int rxrpc_instantiate_s(struct key *key,
 	if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0)
 		BUG();
 
-	key->payload.data = ci;
+	prep->payload[0] = ci;
 	_leave(" = 0");
 	return 0;
 }
 
 /*
+ * Clean up preparse data.
+ */
+static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
+{
+	if (prep->payload[0])
+		crypto_free_blkcipher(prep->payload[0]);
+}
+
+/*
  * dispose of the data dangling from the corpse of a rxrpc key
  */
 static void rxrpc_destroy(struct key *key)
 {
-	struct rxrpc_key_token *token;
-
-	while ((token = key->payload.data)) {
-		key->payload.data = token->next;
-		switch (token->security_index) {
-		case RXRPC_SECURITY_RXKAD:
-			kfree(token->kad);
-			break;
-		case RXRPC_SECURITY_RXK5:
-			if (token->k5)
-				rxrpc_rxk5_free(token->k5);
-			break;
-		default:
-			printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
-			       token->security_index);
-			BUG();
-		}
-
-		kfree(token);
-	}
+	rxrpc_free_token_list(key->payload.data);
 }
 
 /*


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

* [PATCH 10/12] KEYS: big_key: Use key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (8 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 09/12] KEYS: RxRPC: " David Howells
@ 2014-03-20 12:05 ` David Howells
  2014-03-20 12:06 ` [PATCH 11/12] KEYS: keyring: Provide " David Howells
  2014-03-20 12:06 ` [PATCH 12/12] KEYS: request_key_auth: " David Howells
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:05 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Make use of key preparsing in the big key type so that quota size determination
can take place prior to keyring locking when a key is being added.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/keys/big_key-type.h |    3 ++-
 security/keys/big_key.c     |   41 +++++++++++++++++++++++++----------------
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/include/keys/big_key-type.h b/include/keys/big_key-type.h
index d69bc8af3292..e0970a578188 100644
--- a/include/keys/big_key-type.h
+++ b/include/keys/big_key-type.h
@@ -16,7 +16,8 @@
 
 extern struct key_type key_type_big_key;
 
-extern int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep);
+extern int big_key_preparse(struct key_preparsed_payload *prep);
+extern void big_key_free_preparse(struct key_preparsed_payload *prep);
 extern void big_key_revoke(struct key *key);
 extern void big_key_destroy(struct key *key);
 extern void big_key_describe(const struct key *big_key, struct seq_file *m);
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 8137b27d641d..c2f91a0cf889 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -34,7 +34,9 @@ MODULE_LICENSE("GPL");
 struct key_type key_type_big_key = {
 	.name			= "big_key",
 	.def_lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
-	.instantiate		= big_key_instantiate,
+	.preparse		= big_key_preparse,
+	.free_preparse		= big_key_free_preparse,
+	.instantiate		= generic_key_instantiate,
 	.match			= user_match,
 	.revoke			= big_key_revoke,
 	.destroy		= big_key_destroy,
@@ -43,11 +45,11 @@ struct key_type key_type_big_key = {
 };
 
 /*
- * Instantiate a big key
+ * Preparse a big key
  */
-int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
+int big_key_preparse(struct key_preparsed_payload *prep)
 {
-	struct path *path = (struct path *)&key->payload.data2;
+	struct path *path = (struct path *)&prep->payload;
 	struct file *file;
 	ssize_t written;
 	size_t datalen = prep->datalen;
@@ -58,11 +60,9 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 		goto error;
 
 	/* Set an arbitrary quota */
-	ret = key_payload_reserve(key, 16);
-	if (ret < 0)
-		goto error;
+	prep->quotalen = 16;
 
-	key->type_data.x[1] = datalen;
+	prep->type_data[1] = (void *)(unsigned long)datalen;
 
 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
 		/* Create a shmem file to store the data in.  This will permit the data
@@ -73,7 +73,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 		file = shmem_kernel_file_setup("", datalen, 0);
 		if (IS_ERR(file)) {
 			ret = PTR_ERR(file);
-			goto err_quota;
+			goto error;
 		}
 
 		written = kernel_write(file, prep->data, prep->datalen, 0);
@@ -93,24 +93,33 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 	} else {
 		/* Just store the data in a buffer */
 		void *data = kmalloc(datalen, GFP_KERNEL);
-		if (!data) {
-			ret = -ENOMEM;
-			goto err_quota;
-		}
+		if (!data)
+			return -ENOMEM;
 
-		key->payload.data = memcpy(data, prep->data, prep->datalen);
+		prep->payload[0] = memcpy(data, prep->data, prep->datalen);
 	}
 	return 0;
 
 err_fput:
 	fput(file);
-err_quota:
-	key_payload_reserve(key, 0);
 error:
 	return ret;
 }
 
 /*
+ * Clear preparsement.
+ */
+void big_key_free_preparse(struct key_preparsed_payload *prep)
+{
+	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
+		struct path *path = (struct path *)&prep->payload;
+		path_put(path);
+	} else {
+		kfree(prep->payload[0]);
+	}
+}
+
+/*
  * dispose of the links from a revoked keyring
  * - called with the key sem write-locked
  */


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

* [PATCH 11/12] KEYS: keyring: Provide key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (9 preceding siblings ...)
  2014-03-20 12:05 ` [PATCH 10/12] KEYS: big_key: " David Howells
@ 2014-03-20 12:06 ` David Howells
  2014-03-20 12:06 ` [PATCH 12/12] KEYS: request_key_auth: " David Howells
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:06 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Provide key preparsing in the keyring so that we can make preparsing
mandatory.  For keyrings, however, only an empty payload is permitted.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 security/keys/keyring.c |   34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 2fb2576dc644..610c50a18db0 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -73,6 +73,8 @@ static inline unsigned keyring_hash(const char *desc)
  * can be treated as ordinary keys in addition to having their own special
  * operations.
  */
+static int keyring_preparse(struct key_preparsed_payload *prep);
+static void keyring_free_preparse(struct key_preparsed_payload *prep);
 static int keyring_instantiate(struct key *keyring,
 			       struct key_preparsed_payload *prep);
 static void keyring_revoke(struct key *keyring);
@@ -84,6 +86,8 @@ static long keyring_read(const struct key *keyring,
 struct key_type key_type_keyring = {
 	.name		= "keyring",
 	.def_datalen	= 0,
+	.preparse	= keyring_preparse,
+	.free_preparse	= keyring_free_preparse,
 	.instantiate	= keyring_instantiate,
 	.match		= user_match,
 	.revoke		= keyring_revoke,
@@ -123,6 +127,21 @@ static void keyring_publish_name(struct key *keyring)
 }
 
 /*
+ * Preparse a keyring payload
+ */
+static int keyring_preparse(struct key_preparsed_payload *prep)
+{
+	return prep->datalen != 0 ? -EINVAL : 0;
+}
+
+/*
+ * Free a preparse of a user defined key payload
+ */
+static void keyring_free_preparse(struct key_preparsed_payload *prep)
+{
+}
+
+/*
  * Initialise a keyring.
  *
  * Returns 0 on success, -EINVAL if given any data.
@@ -130,17 +149,10 @@ static void keyring_publish_name(struct key *keyring)
 static int keyring_instantiate(struct key *keyring,
 			       struct key_preparsed_payload *prep)
 {
-	int ret;
-
-	ret = -EINVAL;
-	if (prep->datalen == 0) {
-		assoc_array_init(&keyring->keys);
-		/* make the keyring available by name if it has one */
-		keyring_publish_name(keyring);
-		ret = 0;
-	}
-
-	return ret;
+	assoc_array_init(&keyring->keys);
+	/* make the keyring available by name if it has one */
+	keyring_publish_name(keyring);
+	return 0;
 }
 
 /*


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

* [PATCH 12/12] KEYS: request_key_auth: Provide key preparsing
  2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
                   ` (10 preceding siblings ...)
  2014-03-20 12:06 ` [PATCH 11/12] KEYS: keyring: Provide " David Howells
@ 2014-03-20 12:06 ` David Howells
  11 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2014-03-20 12:06 UTC (permalink / raw)
  To: keyrings; +Cc: dhowells, linux-security-module, linux-kernel

Provide key preparsing for the request_key_auth key type so that we can make
preparsing mandatory.  This does nothing as this type can only be set up
internally to the kernel.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 security/keys/request_key_auth.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 7495a93b4b90..842e6f410d50 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -20,6 +20,8 @@
 #include "internal.h"
 #include <keys/user-type.h>
 
+static int request_key_auth_preparse(struct key_preparsed_payload *);
+static void request_key_auth_free_preparse(struct key_preparsed_payload *);
 static int request_key_auth_instantiate(struct key *,
 					struct key_preparsed_payload *);
 static void request_key_auth_describe(const struct key *, struct seq_file *);
@@ -33,6 +35,8 @@ static long request_key_auth_read(const struct key *, char __user *, size_t);
 struct key_type key_type_request_key_auth = {
 	.name		= ".request_key_auth",
 	.def_datalen	= sizeof(struct request_key_auth),
+	.preparse	= request_key_auth_preparse,
+	.free_preparse	= request_key_auth_free_preparse,
 	.instantiate	= request_key_auth_instantiate,
 	.describe	= request_key_auth_describe,
 	.revoke		= request_key_auth_revoke,
@@ -40,6 +44,15 @@ struct key_type key_type_request_key_auth = {
 	.read		= request_key_auth_read,
 };
 
+int request_key_auth_preparse(struct key_preparsed_payload *prep)
+{
+	return 0;
+}
+
+void request_key_auth_free_preparse(struct key_preparsed_payload *prep)
+{
+}
+
 /*
  * Instantiate a request-key authorisation key.
  */


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

end of thread, other threads:[~2014-03-20 13:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-20 12:04 [PATCH 00/12] KEYS: Use preparsing in most key types David Howells
2014-03-20 12:04 ` [PATCH 01/12] KEYS: Provide a generic instantiation function David Howells
2014-03-20 12:04 ` [PATCH 02/12] KEYS: struct key_preparsed_payload should have two payload pointers David Howells
2014-03-20 12:04 ` [PATCH 03/12] KEYS: Allow expiry time to be set when preparsing a key David Howells
2014-03-20 12:05 ` [PATCH 04/12] KEYS: Call ->free_preparse() even after ->preparse() returns an error David Howells
2014-03-20 12:05 ` [PATCH 05/12] KEYS: user: Use key preparsing David Howells
2014-03-20 12:05 ` [PATCH 06/12] KEYS: Ceph: " David Howells
2014-03-20 12:05 ` [PATCH 07/12] KEYS: Ceph: Use user_match() David Howells
2014-03-20 12:05 ` [PATCH 08/12] KEYS: DNS: Use key preparsing David Howells
2014-03-20 12:05 ` [PATCH 09/12] KEYS: RxRPC: " David Howells
2014-03-20 12:05 ` [PATCH 10/12] KEYS: big_key: " David Howells
2014-03-20 12:06 ` [PATCH 11/12] KEYS: keyring: Provide " David Howells
2014-03-20 12:06 ` [PATCH 12/12] KEYS: request_key_auth: " David Howells

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.