Commit 7185795a authored by Jeremy Kerr's avatar Jeremy Kerr Committed by Michael Ellerman

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: default avatarJeremy Kerr <jk@ozlabs.org>
Acked-by: default avatarStewart Smith <stewart@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 02b6505c
...@@ -32,9 +32,13 @@ ...@@ -32,9 +32,13 @@
#include <asm/uaccess.h> #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_queue_item {
struct opal_prd_msg_header msg;
struct list_head list; struct list_head list;
struct opal_prd_msg_header msg;
}; };
static struct device_node *prd_node; static struct device_node *prd_node;
...@@ -351,22 +355,23 @@ static int opal_prd_msg_notifier(struct notifier_block *nb, ...@@ -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_queue_item *item;
struct opal_prd_msg_header *hdr; struct opal_prd_msg_header *hdr;
struct opal_msg *msg = _msg; struct opal_msg *msg = _msg;
int msg_size, item_size;
unsigned long flags; unsigned long flags;
int size;
if (msg_type != OPAL_MSG_PRD) if (msg_type != OPAL_MSG_PRD)
return 0; return 0;
/* Calculate total size of the item we need to store. The 'size' field /* Calculate total size of the message and item we need to store. The
* in the header includes the header itself. */ * 'size' field in the header includes the header itself. */
hdr = (void *)msg->params; 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) if (!item)
return -ENOMEM; return -ENOMEM;
memcpy(&item->msg, msg->params, size); memcpy(&item->msg, msg->params, msg_size);
spin_lock_irqsave(&opal_prd_msg_queue_lock, flags); spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
list_add_tail(&item->list, &opal_prd_msg_queue); list_add_tail(&item->list, &opal_prd_msg_queue);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment