diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2015-06-15 12:25:34 +0300 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-06-18 00:16:01 +0300 |
commit | 7185795a62589292015484985635b4a38029a2b9 (patch) | |
tree | 1cd29f85bcd557626219d2c400c8d97fc67ac5aa | |
parent | 02b6505c8f84cbb4be459c9bf8ebbb7b0754e764 (diff) | |
download | linux-7185795a62589292015484985635b4a38029a2b9.tar.xz |
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.c | 19 |
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); |