summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-09-16 17:32:16 +0100
committerDavid Howells <dhowells@redhat.com>2014-09-16 17:32:16 +0100
commit68c45c7feaf1a8adebc6d9d77aa0a2018d974085 (patch)
tree3723e1d847b0626e07837db7c648ba63ade7e1a5
parentac60ab4b4968b54fb5af20eac9dd78e36ad910c1 (diff)
parentcecf5d2e1208da512a4c951c24acd66c54a4d06c (diff)
Merge tag 'keys-fixes-20140916' into keys-next
Merge in keyrings fixes, at least some of which later patches depend on: (1) Reinstate the production of EPERM for key types beginning with '.' in requests from userspace. (2) Tidy up the cleanup of PKCS#7 message signed information blocks and fix a bug this made more obvious. Signed-off-by: David Howells <dhowells@redhat.coM>
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c61
-rw-r--r--security/keys/keyctl.c2
2 files changed, 35 insertions, 28 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 42e56aa7d277..1e9861da7ee4 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -31,6 +31,18 @@ struct pkcs7_parse_context {
unsigned sinfo_index;
};
+/*
+ * Free a signed information block.
+ */
+static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
+{
+ if (sinfo) {
+ mpi_free(sinfo->sig.mpi[0]);
+ kfree(sinfo->sig.digest);
+ kfree(sinfo);
+ }
+}
+
/**
* pkcs7_free_message - Free a PKCS#7 message
* @pkcs7: The PKCS#7 message to free
@@ -54,9 +66,7 @@ void pkcs7_free_message(struct pkcs7_message *pkcs7)
while (pkcs7->signed_infos) {
sinfo = pkcs7->signed_infos;
pkcs7->signed_infos = sinfo->next;
- mpi_free(sinfo->sig.mpi[0]);
- kfree(sinfo->sig.digest);
- kfree(sinfo);
+ pkcs7_free_signed_info(sinfo);
}
kfree(pkcs7);
}
@@ -71,51 +81,46 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message);
struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
{
struct pkcs7_parse_context *ctx;
- struct pkcs7_message *msg;
- long ret;
+ struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
+ int ret;
- ret = -ENOMEM;
- msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
- if (!msg)
- goto error_no_sig;
ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
if (!ctx)
- goto error_no_ctx;
+ goto out_no_ctx;
+ ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
+ if (!ctx->msg)
+ goto out_no_msg;
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
if (!ctx->sinfo)
- goto error_no_sinfo;
+ goto out_no_sinfo;
- ctx->msg = msg;
ctx->data = (unsigned long)data;
ctx->ppcerts = &ctx->certs;
ctx->ppsinfo = &ctx->msg->signed_infos;
/* Attempt to decode the signature */
ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
- if (ret < 0)
- goto error_decode;
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out;
+ }
+
+ msg = ctx->msg;
+ ctx->msg = NULL;
+out:
while (ctx->certs) {
struct x509_certificate *cert = ctx->certs;
ctx->certs = cert->next;
x509_free_certificate(cert);
}
- mpi_free(ctx->sinfo->sig.mpi[0]);
- kfree(ctx->sinfo->sig.digest);
- kfree(ctx->sinfo);
+ pkcs7_free_signed_info(ctx->sinfo);
+out_no_sinfo:
+ pkcs7_free_message(ctx->msg);
+out_no_msg:
kfree(ctx);
+out_no_ctx:
return msg;
-
-error_decode:
- mpi_free(ctx->sinfo->sig.mpi[0]);
- kfree(ctx->sinfo->sig.digest);
- kfree(ctx->sinfo);
-error_no_sinfo:
- kfree(ctx);
-error_no_ctx:
- pkcs7_free_message(msg);
-error_no_sig:
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(pkcs7_parse_message);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index e26f860e5f2e..eff88a5f5d40 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -37,6 +37,8 @@ static int key_get_type_from_user(char *type,
return ret;
if (ret == 0 || ret >= len)
return -EINVAL;
+ if (type[0] == '.')
+ return -EPERM;
type[len - 1] = '\0';
return 0;
}