diff mbox

powerpc/powernv: fix construction of opal PRD messages

Message ID 1434360334.29351.605847485345.1.gpush@pablo (mailing list archive)
State Accepted
Commit 7185795a62589292015484985635b4a38029a2b9
Delegated to: Michael Ellerman
Headers show

Commit Message

Jeremy Kerr June 15, 2015, 9:25 a.m. UTC
We currently have a bug in the PRD code, where the contents of an
incoming message (beyond the header) will be overwritten by the list
item manipulations when adding to to the prd_msg_queue.

This change reorders struct opal_prd_msg_queue_item, so that the
message body doesn't overlap the list_head.

We also clarify the memcpy of the message, as we're copying unnecessary
bytes at the end of the message data.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
 arch/powerpc/platforms/powernv/opal-prd.c |   19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

Comments

Stewart Smith June 16, 2015, 1:25 a.m. UTC | #1
Jeremy Kerr <jk@ozlabs.org> writes:
> We currently have a bug in the PRD code, where the contents of an
> incoming message (beyond the header) will be overwritten by the list
> item manipulations when adding to to the prd_msg_queue.
>
> This change reorders struct opal_prd_msg_queue_item, so that the
> message body doesn't overlap the list_head.
>
> We also clarify the memcpy of the message, as we're copying unnecessary
> bytes at the end of the message data.
>
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

Acked-by: Stewart Smith <stewart@linux.vnet.ibm.com>
diff mbox

Patch

diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c
index 64694dd..ba2e388 100644
--- a/arch/powerpc/platforms/powernv/opal-prd.c
+++ b/arch/powerpc/platforms/powernv/opal-prd.c
@@ -32,9 +32,13 @@ 
 #include <asm/uaccess.h>
 
 
+/**
+ * The msg member must be at the end of the struct, as it's followed by the
+ * message data.
+ */
 struct opal_prd_msg_queue_item {
-	struct opal_prd_msg_header	msg;
 	struct list_head		list;
+	struct opal_prd_msg_header	msg;
 };
 
 static struct device_node *prd_node;
@@ -351,22 +355,23 @@  static int opal_prd_msg_notifier(struct notifier_block *nb,
 	struct opal_prd_msg_queue_item *item;
 	struct opal_prd_msg_header *hdr;
 	struct opal_msg *msg = _msg;
+	int msg_size, item_size;
 	unsigned long flags;
-	int size;
 
 	if (msg_type != OPAL_MSG_PRD)
 		return 0;
 
-	/* Calculate total size of the item we need to store. The 'size' field
-	 * in the header includes the header itself. */
+	/* Calculate total size of the message and item we need to store. The
+	 * 'size' field in the header includes the header itself. */
 	hdr = (void *)msg->params;
-	size = (sizeof(*item) - sizeof(item->msg)) + be16_to_cpu(hdr->size);
+	msg_size = be16_to_cpu(hdr->size);
+	item_size = msg_size + sizeof(*item) - sizeof(item->msg);
 
-	item = kzalloc(size, GFP_ATOMIC);
+	item = kzalloc(item_size, GFP_ATOMIC);
 	if (!item)
 		return -ENOMEM;
 
-	memcpy(&item->msg, msg->params, size);
+	memcpy(&item->msg, msg->params, msg_size);
 
 	spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
 	list_add_tail(&item->list, &opal_prd_msg_queue);