summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2015-06-15 11:25:34 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2015-06-17 23:16:01 +0200
commit7185795a62589292015484985635b4a38029a2b9 (patch)
tree1cd29f85bcd557626219d2c400c8d97fc67ac5aa
parentpowerpc/powernv: Increase opal-irqchip initcall priority (diff)
downloadlinux-7185795a62589292015484985635b4a38029a2b9.tar.xz
linux-7185795a62589292015484985635b4a38029a2b9.zip
powerpc/powernv: fix construction of opal PRD messages
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> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/platforms/powernv/opal-prd.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c
index d9e72bde79f5..46cb3feb0a13 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);