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

Commit 4fbeba43 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files
Herbert writes:
  "Crypto Fixes for 4.19

   This push fixes the following issues:
   - Out-of-bound stack access in qat.
   - Illegal schedule in mxs-dcp.
   - Memory corruption in chelsio.
   - Incorrect pointer computation in caam."

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: qat - Fix KASAN stack-out-of-bounds bug in adf_probe()
  crypto: mxs-dcp - Fix wait logic on chan threads
  crypto: chelsio - Fix memory corruption in DMA Mapped buffers.
  crypto: caam/jr - fix ablkcipher_edesc pointer arithmetic
parents 087f759a ba439a6c
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1553,8 +1553,8 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
	edesc->src_nents = src_nents;
	edesc->dst_nents = dst_nents;
	edesc->sec4_sg_bytes = sec4_sg_bytes;
	edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
			 desc_bytes;
	edesc->sec4_sg = (struct sec4_sg_entry *)((u8 *)edesc->hw_desc +
						  desc_bytes);
	edesc->iv_dir = DMA_TO_DEVICE;

	/* Make sure IV is located in a DMAable area */
@@ -1757,8 +1757,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
	edesc->src_nents = src_nents;
	edesc->dst_nents = dst_nents;
	edesc->sec4_sg_bytes = sec4_sg_bytes;
	edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
			 desc_bytes;
	edesc->sec4_sg = (struct sec4_sg_entry *)((u8 *)edesc->hw_desc +
						  desc_bytes);
	edesc->iv_dir = DMA_FROM_DEVICE;

	/* Make sure IV is located in a DMAable area */
+22 −10
Original line number Diff line number Diff line
@@ -367,7 +367,8 @@ static inline void dsgl_walk_init(struct dsgl_walk *walk,
	walk->to = (struct phys_sge_pairs *)(dsgl + 1);
}

static inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid)
static inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid,
				 int pci_chan_id)
{
	struct cpl_rx_phys_dsgl *phys_cpl;

@@ -385,6 +386,7 @@ static inline void dsgl_walk_end(struct dsgl_walk *walk, unsigned short qid)
	phys_cpl->rss_hdr_int.opcode = CPL_RX_PHYS_ADDR;
	phys_cpl->rss_hdr_int.qid = htons(qid);
	phys_cpl->rss_hdr_int.hash_val = 0;
	phys_cpl->rss_hdr_int.channel = pci_chan_id;
}

static inline void dsgl_walk_add_page(struct dsgl_walk *walk,
@@ -718,7 +720,7 @@ static inline void create_wreq(struct chcr_context *ctx,
		FILL_WR_RX_Q_ID(ctx->dev->rx_channel_id, qid,
				!!lcb, ctx->tx_qidx);

	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(ctx->dev->tx_channel_id,
	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(ctx->tx_chan_id,
						       qid);
	chcr_req->ulptx.len = htonl((DIV_ROUND_UP(len16, 16) -
				     ((sizeof(chcr_req->wreq)) >> 4)));
@@ -1339,16 +1341,23 @@ static int chcr_device_init(struct chcr_context *ctx)
				    adap->vres.ncrypto_fc);
		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
		txq_perchan = ntxq / u_ctx->lldi.nchan;
		rxq_idx = ctx->dev->tx_channel_id * rxq_perchan;
		rxq_idx += id % rxq_perchan;
		txq_idx = ctx->dev->tx_channel_id * txq_perchan;
		txq_idx += id % txq_perchan;
		spin_lock(&ctx->dev->lock_chcr_dev);
		ctx->rx_qidx = rxq_idx;
		ctx->tx_qidx = txq_idx;
		ctx->tx_chan_id = ctx->dev->tx_channel_id;
		ctx->dev->tx_channel_id = !ctx->dev->tx_channel_id;
		ctx->dev->rx_channel_id = 0;
		spin_unlock(&ctx->dev->lock_chcr_dev);
		rxq_idx = ctx->tx_chan_id * rxq_perchan;
		rxq_idx += id % rxq_perchan;
		txq_idx = ctx->tx_chan_id * txq_perchan;
		txq_idx += id % txq_perchan;
		ctx->rx_qidx = rxq_idx;
		ctx->tx_qidx = txq_idx;
		/* Channel Id used by SGE to forward packet to Host.
		 * Same value should be used in cpl_fw6_pld RSS_CH field
		 * by FW. Driver programs PCI channel ID to be used in fw
		 * at the time of queue allocation with value "pi->tx_chan"
		 */
		ctx->pci_chan_id = txq_idx / txq_perchan;
	}
out:
	return err;
@@ -2503,6 +2512,7 @@ void chcr_add_aead_dst_ent(struct aead_request *req,
	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
	struct dsgl_walk dsgl_walk;
	unsigned int authsize = crypto_aead_authsize(tfm);
	struct chcr_context *ctx = a_ctx(tfm);
	u32 temp;

	dsgl_walk_init(&dsgl_walk, phys_cpl);
@@ -2512,7 +2522,7 @@ void chcr_add_aead_dst_ent(struct aead_request *req,
	dsgl_walk_add_page(&dsgl_walk, IV, &reqctx->iv_dma);
	temp = req->cryptlen + (reqctx->op ? -authsize : authsize);
	dsgl_walk_add_sg(&dsgl_walk, req->dst, temp, req->assoclen);
	dsgl_walk_end(&dsgl_walk, qid);
	dsgl_walk_end(&dsgl_walk, qid, ctx->pci_chan_id);
}

void chcr_add_cipher_src_ent(struct ablkcipher_request *req,
@@ -2544,6 +2554,8 @@ void chcr_add_cipher_dst_ent(struct ablkcipher_request *req,
			     unsigned short qid)
{
	struct chcr_blkcipher_req_ctx *reqctx = ablkcipher_request_ctx(req);
	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(wrparam->req);
	struct chcr_context *ctx = c_ctx(tfm);
	struct dsgl_walk dsgl_walk;

	dsgl_walk_init(&dsgl_walk, phys_cpl);
@@ -2552,7 +2564,7 @@ void chcr_add_cipher_dst_ent(struct ablkcipher_request *req,
	reqctx->dstsg = dsgl_walk.last_sg;
	reqctx->dst_ofst = dsgl_walk.last_sg_len;

	dsgl_walk_end(&dsgl_walk, qid);
	dsgl_walk_end(&dsgl_walk, qid, ctx->pci_chan_id);
}

void chcr_add_hash_src_ent(struct ahash_request *req,
+2 −0
Original line number Diff line number Diff line
@@ -255,6 +255,8 @@ struct chcr_context {
	struct chcr_dev *dev;
	unsigned char tx_qidx;
	unsigned char rx_qidx;
	unsigned char tx_chan_id;
	unsigned char pci_chan_id;
	struct __crypto_ctx crypto_ctx[0];
};

+30 −23
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ struct dcp {
	struct dcp_coherent_block	*coh;

	struct completion		completion[DCP_MAX_CHANS];
	struct mutex			mutex[DCP_MAX_CHANS];
	spinlock_t			lock[DCP_MAX_CHANS];
	struct task_struct		*thread[DCP_MAX_CHANS];
	struct crypto_queue		queue[DCP_MAX_CHANS];
};
@@ -349,13 +349,20 @@ static int dcp_chan_thread_aes(void *data)

	int ret;

	do {
		__set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		set_current_state(TASK_INTERRUPTIBLE);

		mutex_lock(&sdcp->mutex[chan]);
		spin_lock(&sdcp->lock[chan]);
		backlog = crypto_get_backlog(&sdcp->queue[chan]);
		arq = crypto_dequeue_request(&sdcp->queue[chan]);
		mutex_unlock(&sdcp->mutex[chan]);
		spin_unlock(&sdcp->lock[chan]);

		if (!backlog && !arq) {
			schedule();
			continue;
		}

		set_current_state(TASK_RUNNING);

		if (backlog)
			backlog->complete(backlog, -EINPROGRESS);
@@ -363,11 +370,8 @@ static int dcp_chan_thread_aes(void *data)
		if (arq) {
			ret = mxs_dcp_aes_block_crypt(arq);
			arq->complete(arq, ret);
			continue;
		}

		schedule();
	} while (!kthread_should_stop());
	}

	return 0;
}
@@ -409,9 +413,9 @@ static int mxs_dcp_aes_enqueue(struct ablkcipher_request *req, int enc, int ecb)
	rctx->ecb = ecb;
	actx->chan = DCP_CHAN_CRYPTO;

	mutex_lock(&sdcp->mutex[actx->chan]);
	spin_lock(&sdcp->lock[actx->chan]);
	ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
	mutex_unlock(&sdcp->mutex[actx->chan]);
	spin_unlock(&sdcp->lock[actx->chan]);

	wake_up_process(sdcp->thread[actx->chan]);

@@ -640,13 +644,20 @@ static int dcp_chan_thread_sha(void *data)
	struct ahash_request *req;
	int ret, fini;

	do {
		__set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		set_current_state(TASK_INTERRUPTIBLE);

		mutex_lock(&sdcp->mutex[chan]);
		spin_lock(&sdcp->lock[chan]);
		backlog = crypto_get_backlog(&sdcp->queue[chan]);
		arq = crypto_dequeue_request(&sdcp->queue[chan]);
		mutex_unlock(&sdcp->mutex[chan]);
		spin_unlock(&sdcp->lock[chan]);

		if (!backlog && !arq) {
			schedule();
			continue;
		}

		set_current_state(TASK_RUNNING);

		if (backlog)
			backlog->complete(backlog, -EINPROGRESS);
@@ -658,12 +669,8 @@ static int dcp_chan_thread_sha(void *data)
			ret = dcp_sha_req_to_buf(arq);
			fini = rctx->fini;
			arq->complete(arq, ret);
			if (!fini)
				continue;
		}

		schedule();
	} while (!kthread_should_stop());
	}

	return 0;
}
@@ -721,9 +728,9 @@ static int dcp_sha_update_fx(struct ahash_request *req, int fini)
		rctx->init = 1;
	}

	mutex_lock(&sdcp->mutex[actx->chan]);
	spin_lock(&sdcp->lock[actx->chan]);
	ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
	mutex_unlock(&sdcp->mutex[actx->chan]);
	spin_unlock(&sdcp->lock[actx->chan]);

	wake_up_process(sdcp->thread[actx->chan]);
	mutex_unlock(&actx->mutex);
@@ -997,7 +1004,7 @@ static int mxs_dcp_probe(struct platform_device *pdev)
	platform_set_drvdata(pdev, sdcp);

	for (i = 0; i < DCP_MAX_CHANS; i++) {
		mutex_init(&sdcp->mutex[i]);
		spin_lock_init(&sdcp->lock[i]);
		init_completion(&sdcp->completion[i]);
		crypto_init_queue(&sdcp->queue[i], 50);
	}
+3 −3
Original line number Diff line number Diff line
@@ -123,7 +123,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	struct adf_hw_device_data *hw_data;
	char name[ADF_DEVICE_NAME_LENGTH];
	unsigned int i, bar_nr;
	int ret, bar_mask;
	unsigned long bar_mask;
	int ret;

	switch (ent->device) {
	case ADF_C3XXX_PCI_DEVICE_ID:
@@ -235,8 +236,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	/* Find and map all the device's BARS */
	i = 0;
	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
	for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
			 ADF_PCI_MAX_BARS * 2) {
	for_each_set_bit(bar_nr, &bar_mask, ADF_PCI_MAX_BARS * 2) {
		struct adf_bar *bar = &accel_pci_dev->pci_bars[i++];

		bar->base_addr = pci_resource_start(pdev, bar_nr);
Loading