* [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