lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 10 Feb 2015 10:39:37 +0200
From:	Tomas Winkler <tomas.winkler@...el.com>
To:	gregkh@...uxfoundation.org
Cc:	arnd@...db.de, linux-kernel@...r.kernel.org,
	Tomas Winkler <tomas.winkler@...el.com>
Subject: [char-misc-next 08/18] mei: iamthif: fix device reset on mei_amthif_irq_read_msg

On failure mei_amthif_irq_read_msg returns an error
that will cause device reset but the issue is software one
so instead we should propagate error to caller and just
clean the read queues.
As a side effect also removes useless BUG_ONs

Signed-off-by: Tomas Winkler <tomas.winkler@...el.com>
---
 drivers/misc/mei/amthif.c    | 76 ++++++++++++++++++++++++++++----------------
 drivers/misc/mei/interrupt.c |  7 ++--
 drivers/misc/mei/mei_dev.h   |  2 +-
 3 files changed, 51 insertions(+), 34 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index c4cb9a984a5f..2ad2f94678c8 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -195,23 +195,26 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		dev_dbg(dev->dev, "woke up from sleep\n");
 	}
 
+	if (cb->status) {
+		rets = cb->status;
+		dev_dbg(dev->dev, "read operation failed %d\n", rets);
+		goto free;
+	}
 
 	dev_dbg(dev->dev, "Got amthif data\n");
 	dev->iamthif_timer = 0;
 
-	if (cb) {
-		timeout = cb->read_time +
-			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
-		dev_dbg(dev->dev, "amthif timeout = %lud\n",
-				timeout);
-
-		if  (time_after(jiffies, timeout)) {
-			dev_dbg(dev->dev, "amthif Time out\n");
-			/* 15 sec for the message has expired */
-			list_del(&cb->list);
-			rets = -ETIME;
-			goto free;
-		}
+	timeout = cb->read_time +
+		mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
+	dev_dbg(dev->dev, "amthif timeout = %lud\n",
+			timeout);
+
+	if  (time_after(jiffies, timeout)) {
+		dev_dbg(dev->dev, "amthif Time out\n");
+		/* 15 sec for the message has expired */
+		list_del(&cb->list);
+		rets = -ETIME;
+		goto free;
 	}
 	/* if the whole message will fit remove it from the list */
 	if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
@@ -501,25 +504,42 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
  * mei_amthif_irq_read_msg - read routine after ISR to
  *			handle the read amthif message
  *
- * @dev: the device structure
+ * @cl: mei client
  * @mei_hdr: header of amthif message
- * @complete_list: An instance of our list structure
+ * @complete_list: completed callbacks list
  *
- * Return: 0 on success, <0 on failure.
+ * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
  */
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
 			    struct mei_msg_hdr *mei_hdr,
 			    struct mei_cl_cb *complete_list)
 {
+	struct mei_device *dev;
 	struct mei_cl_cb *cb;
 	unsigned char *buffer;
+	int ret = 0;
 
-	BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
-	BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
+	dev = cl->dev;
 
-	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
-	BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
+	if (cl->state != MEI_FILE_CONNECTED)
+		goto err;
+
+	if (dev->iamthif_state != MEI_IAMTHIF_READING)
+		goto err;
+
+	cb = dev->iamthif_current_cb;
 
+	if (!cb) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	if (dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length) {
+		cb->status = -ERANGE;
+		goto err;
+	}
+
+	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
 	mei_read_slots(dev, buffer, mei_hdr->length);
 
 	dev->iamthif_msg_buf_index += mei_hdr->length;
@@ -527,14 +547,8 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	if (!mei_hdr->msg_complete)
 		return 0;
 
-	dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
-			mei_hdr->length);
-
 	dev_dbg(dev->dev, "completed amthif read.\n ");
-	if (!dev->iamthif_current_cb)
-		return -ENODEV;
 
-	cb = dev->iamthif_current_cb;
 	dev->iamthif_current_cb = NULL;
 
 	dev->iamthif_stall_timer = 0;
@@ -543,10 +557,16 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	if (dev->iamthif_ioctl) {
 		/* found the iamthif cb */
 		dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-		dev_dbg(dev->dev, "add the amthif read cb to complete.\n ");
 		list_add_tail(&cb->list, &complete_list->list);
 	}
+
 	return 0;
+
+err:
+	mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
+	dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
+				MEI_HDR_PRM(mei_hdr));
+	return ret;
 }
 
 /**
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 587cb04a3cf5..151f0c84a65e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -384,11 +384,8 @@ int mei_irq_read_handler(struct mei_device *dev,
 		goto end;
 	}
 
-	if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
-	    MEI_FILE_CONNECTED == dev->iamthif_cl.state &&
-	    dev->iamthif_state == MEI_IAMTHIF_READING) {
-
-		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
+	if (cl == &dev->iamthif_cl) {
+		ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
 		if (ret) {
 			dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
 					ret);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 195e426b08f0..b74d156ed600 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -685,7 +685,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 			struct mei_cl_cb *cmpl_list);
 
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
 			    struct mei_msg_hdr *mei_hdr,
 			    struct mei_cl_cb *complete_list);
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ