Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32e2524a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull crypto fixes from Herbert Xu:
 "This fixes the following issues:

   - Potential memory overwrite in simd

   - Kernel info leaks in crypto_user

   - NULL dereference and use-after-free in hisilicon"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: user - Zeroize whole structure given to user space
  crypto: user - fix leaking uninitialized memory to userspace
  crypto: simd - correctly take reqsize of wrapped skcipher into account
  crypto: hisilicon - Fix reference after free of memories on error path
  crypto: hisilicon - Fix NULL dereference for same dst and src
parents 4efd3460 9f4debe3
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_cipher rcipher;

	strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));
	strncpy(rcipher.type, "cipher", sizeof(rcipher.type));

	rcipher.blocksize = alg->cra_blocksize;
	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
@@ -103,7 +103,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_comp rcomp;

	strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
	strncpy(rcomp.type, "compression", sizeof(rcomp.type));
	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
		    sizeof(struct crypto_report_comp), &rcomp))
		goto nla_put_failure;
@@ -117,7 +117,7 @@ static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_acomp racomp;

	strlcpy(racomp.type, "acomp", sizeof(racomp.type));
	strncpy(racomp.type, "acomp", sizeof(racomp.type));

	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
		    sizeof(struct crypto_report_acomp), &racomp))
@@ -132,7 +132,7 @@ static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_akcipher rakcipher;

	strlcpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
	strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));

	if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
		    sizeof(struct crypto_report_akcipher), &rakcipher))
@@ -147,7 +147,7 @@ static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
{
	struct crypto_report_kpp rkpp;

	strlcpy(rkpp.type, "kpp", sizeof(rkpp.type));
	strncpy(rkpp.type, "kpp", sizeof(rkpp.type));

	if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
		    sizeof(struct crypto_report_kpp), &rkpp))
@@ -161,10 +161,10 @@ static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
static int crypto_report_one(struct crypto_alg *alg,
			     struct crypto_user_alg *ualg, struct sk_buff *skb)
{
	strlcpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
	strlcpy(ualg->cru_driver_name, alg->cra_driver_name,
	strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
	strncpy(ualg->cru_driver_name, alg->cra_driver_name,
		sizeof(ualg->cru_driver_name));
	strlcpy(ualg->cru_module_name, module_name(alg->cra_module),
	strncpy(ualg->cru_module_name, module_name(alg->cra_module),
		sizeof(ualg->cru_module_name));

	ualg->cru_type = 0;
@@ -177,7 +177,7 @@ static int crypto_report_one(struct crypto_alg *alg,
	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
		struct crypto_report_larval rl;

		strlcpy(rl.type, "larval", sizeof(rl.type));
		strncpy(rl.type, "larval", sizeof(rl.type));
		if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
			    sizeof(struct crypto_report_larval), &rl))
			goto nla_put_failure;
+21 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ static int crypto_report_aead(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&raead, 0, sizeof(raead));

	strncpy(raead.type, "aead", sizeof(raead.type));

	v32 = atomic_read(&alg->encrypt_cnt);
@@ -65,6 +67,8 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rcipher, 0, sizeof(rcipher));

	strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));

	v32 = atomic_read(&alg->encrypt_cnt);
@@ -93,6 +97,8 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rcomp, 0, sizeof(rcomp));

	strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
	v32 = atomic_read(&alg->compress_cnt);
	rcomp.stat_compress_cnt = v32;
@@ -120,6 +126,8 @@ static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&racomp, 0, sizeof(racomp));

	strlcpy(racomp.type, "acomp", sizeof(racomp.type));
	v32 = atomic_read(&alg->compress_cnt);
	racomp.stat_compress_cnt = v32;
@@ -147,6 +155,8 @@ static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rakcipher, 0, sizeof(rakcipher));

	strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
	v32 = atomic_read(&alg->encrypt_cnt);
	rakcipher.stat_encrypt_cnt = v32;
@@ -177,6 +187,8 @@ static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
	struct crypto_stat rkpp;
	u32 v;

	memset(&rkpp, 0, sizeof(rkpp));

	strlcpy(rkpp.type, "kpp", sizeof(rkpp.type));

	v = atomic_read(&alg->setsecret_cnt);
@@ -203,6 +215,8 @@ static int crypto_report_ahash(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rhash, 0, sizeof(rhash));

	strncpy(rhash.type, "ahash", sizeof(rhash.type));

	v32 = atomic_read(&alg->hash_cnt);
@@ -227,6 +241,8 @@ static int crypto_report_shash(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rhash, 0, sizeof(rhash));

	strncpy(rhash.type, "shash", sizeof(rhash.type));

	v32 = atomic_read(&alg->hash_cnt);
@@ -251,6 +267,8 @@ static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
	u64 v64;
	u32 v32;

	memset(&rrng, 0, sizeof(rrng));

	strncpy(rrng.type, "rng", sizeof(rrng.type));

	v32 = atomic_read(&alg->generate_cnt);
@@ -275,6 +293,8 @@ static int crypto_reportstat_one(struct crypto_alg *alg,
				 struct crypto_user_alg *ualg,
				 struct sk_buff *skb)
{
	memset(ualg, 0, sizeof(*ualg));

	strlcpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
	strlcpy(ualg->cru_driver_name, alg->cra_driver_name,
		sizeof(ualg->cru_driver_name));
@@ -291,6 +311,7 @@ static int crypto_reportstat_one(struct crypto_alg *alg,
	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
		struct crypto_stat rl;

		memset(&rl, 0, sizeof(rl));
		strlcpy(rl.type, "larval", sizeof(rl.type));
		if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL,
			    sizeof(struct crypto_stat), &rl))
+3 −2
Original line number Diff line number Diff line
@@ -124,8 +124,9 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)

	ctx->cryptd_tfm = cryptd_tfm;

	reqsize = sizeof(struct skcipher_request);
	reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base);
	reqsize = crypto_skcipher_reqsize(cryptd_skcipher_child(cryptd_tfm));
	reqsize = max(reqsize, crypto_skcipher_reqsize(&cryptd_tfm->base));
	reqsize += sizeof(struct skcipher_request);

	crypto_skcipher_set_reqsize(tfm, reqsize);

+17 −14
Original line number Diff line number Diff line
@@ -732,6 +732,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
	int *splits_in_nents;
	int *splits_out_nents = NULL;
	struct sec_request_el *el, *temp;
	bool split = skreq->src != skreq->dst;

	mutex_init(&sec_req->lock);
	sec_req->req_base = &skreq->base;
@@ -750,7 +751,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
	if (ret)
		goto err_free_split_sizes;

	if (skreq->src != skreq->dst) {
	if (split) {
		sec_req->len_out = sg_nents(skreq->dst);
		ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,
					   &splits_out, &splits_out_nents,
@@ -785,8 +786,9 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
					       split_sizes[i],
					       skreq->src != skreq->dst,
					       splits_in[i], splits_in_nents[i],
					       splits_out[i],
					       splits_out_nents[i], info);
					       split ? splits_out[i] : NULL,
					       split ? splits_out_nents[i] : 0,
					       info);
		if (IS_ERR(el)) {
			ret = PTR_ERR(el);
			goto err_free_elements;
@@ -806,13 +808,6 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
	 * more refined but this is unlikely to happen so no need.
	 */

	/* Cleanup - all elements in pointer arrays have been coppied */
	kfree(splits_in_nents);
	kfree(splits_in);
	kfree(splits_out_nents);
	kfree(splits_out);
	kfree(split_sizes);

	/* Grab a big lock for a long time to avoid concurrency issues */
	mutex_lock(&queue->queuelock);

@@ -827,13 +822,13 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
	     (!queue->havesoftqueue ||
	      kfifo_avail(&queue->softqueue) > steps)) ||
	    !list_empty(&ctx->backlog)) {
		ret = -EBUSY;
		if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
			list_add_tail(&sec_req->backlog_head, &ctx->backlog);
			mutex_unlock(&queue->queuelock);
			return -EBUSY;
			goto out;
		}

		ret = -EBUSY;
		mutex_unlock(&queue->queuelock);
		goto err_free_elements;
	}
@@ -842,7 +837,15 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
	if (ret)
		goto err_free_elements;

	return -EINPROGRESS;
	ret = -EINPROGRESS;
out:
	/* Cleanup - all elements in pointer arrays have been copied */
	kfree(splits_in_nents);
	kfree(splits_in);
	kfree(splits_out_nents);
	kfree(splits_out);
	kfree(split_sizes);
	return ret;

err_free_elements:
	list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
@@ -854,7 +857,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
				 crypto_skcipher_ivsize(atfm),
				 DMA_BIDIRECTIONAL);
err_unmap_out_sg:
	if (skreq->src != skreq->dst)
	if (split)
		sec_unmap_sg_on_err(skreq->dst, steps, splits_out,
				    splits_out_nents, sec_req->len_out,
				    info->dev);