diff mbox series

[1/2] powerpc/powernv: Fix fortify source warnings in opal-prd.c

Message ID 20230821142820.497107-1-mpe@ellerman.id.au (mailing list archive)
State Accepted
Commit feea65a338e52297b68ceb688eaf0ffc50310a83
Headers show
Series [1/2] powerpc/powernv: Fix fortify source warnings in opal-prd.c | expand

Commit Message

Michael Ellerman Aug. 21, 2023, 2:28 p.m. UTC
As reported by Mahesh & Aneesh, opal_prd_msg_notifier() triggers a
FORTIFY_SOURCE warning:

  memcpy: detected field-spanning write (size 32) of single field "&item->msg" at arch/powerpc/platforms/powernv/opal-prd.c:355 (size 4)
  WARNING: CPU: 9 PID: 660 at arch/powerpc/platforms/powernv/opal-prd.c:355 opal_prd_msg_notifier+0x174/0x188 [opal_prd]
  NIP opal_prd_msg_notifier+0x174/0x188 [opal_prd]
  LR  opal_prd_msg_notifier+0x170/0x188 [opal_prd]
  Call Trace:
    opal_prd_msg_notifier+0x170/0x188 [opal_prd] (unreliable)
    notifier_call_chain+0xc0/0x1b0
    atomic_notifier_call_chain+0x2c/0x40
    opal_message_notify+0xf4/0x2c0

This happens because the copy is targetting item->msg, which is only 4
bytes in size, even though the enclosing item was allocated with extra
space following the msg.

To fix the warning define struct opal_prd_msg with a union of the header
and a flex array, and have the memcpy target the flex array.

Reported-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Reported-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/platforms/powernv/opal-prd.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

Comments

Mahesh J Salgaonkar Aug. 23, 2023, 2:58 a.m. UTC | #1
On 2023-08-22 00:28:19 Tue, Michael Ellerman wrote:
> As reported by Mahesh & Aneesh, opal_prd_msg_notifier() triggers a
> FORTIFY_SOURCE warning:
> 
>   memcpy: detected field-spanning write (size 32) of single field "&item->msg" at arch/powerpc/platforms/powernv/opal-prd.c:355 (size 4)
>   WARNING: CPU: 9 PID: 660 at arch/powerpc/platforms/powernv/opal-prd.c:355 opal_prd_msg_notifier+0x174/0x188 [opal_prd]
>   NIP opal_prd_msg_notifier+0x174/0x188 [opal_prd]
>   LR  opal_prd_msg_notifier+0x170/0x188 [opal_prd]
>   Call Trace:
>     opal_prd_msg_notifier+0x170/0x188 [opal_prd] (unreliable)
>     notifier_call_chain+0xc0/0x1b0
>     atomic_notifier_call_chain+0x2c/0x40
>     opal_message_notify+0xf4/0x2c0
> 
> This happens because the copy is targetting item->msg, which is only 4
> bytes in size, even though the enclosing item was allocated with extra
> space following the msg.
> 
> To fix the warning define struct opal_prd_msg with a union of the header
> and a flex array, and have the memcpy target the flex array.
> 
> Reported-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Reported-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Tested-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Reviewed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>

Thanks,
-Mahesh

> ---
>  arch/powerpc/platforms/powernv/opal-prd.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c
> index 113bdb151f68..40e26e9f318f 100644
> --- a/arch/powerpc/platforms/powernv/opal-prd.c
> +++ b/arch/powerpc/platforms/powernv/opal-prd.c
> @@ -24,13 +24,20 @@
>  #include <linux/uaccess.h>
>  
>  
> +struct opal_prd_msg {
> +	union {
> +		struct opal_prd_msg_header header;
> +		DECLARE_FLEX_ARRAY(u8, data);
> +	};
> +};
> +
>  /*
>   * 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 list_head		list;
> -	struct opal_prd_msg_header	msg;
> +	struct list_head	list;
> +	struct opal_prd_msg	msg;
>  };
>  
>  static struct device_node *prd_node;
> @@ -156,7 +163,7 @@ static ssize_t opal_prd_read(struct file *file, char __user *buf,
>  	int rc;
>  
>  	/* we need at least a header's worth of data */
> -	if (count < sizeof(item->msg))
> +	if (count < sizeof(item->msg.header))
>  		return -EINVAL;
>  
>  	if (*ppos)
> @@ -186,7 +193,7 @@ static ssize_t opal_prd_read(struct file *file, char __user *buf,
>  			return -EINTR;
>  	}
>  
> -	size = be16_to_cpu(item->msg.size);
> +	size = be16_to_cpu(item->msg.header.size);
>  	if (size > count) {
>  		err = -EINVAL;
>  		goto err_requeue;
> @@ -352,7 +359,7 @@ static int opal_prd_msg_notifier(struct notifier_block *nb,
>  	if (!item)
>  		return -ENOMEM;
>  
> -	memcpy(&item->msg, msg->params, msg_size);
> +	memcpy(&item->msg.data, msg->params, msg_size);
>  
>  	spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
>  	list_add_tail(&item->list, &opal_prd_msg_queue);
> -- 
> 2.41.0
>
Michael Ellerman Aug. 31, 2023, 4:02 a.m. UTC | #2
On Tue, 22 Aug 2023 00:28:19 +1000, Michael Ellerman wrote:
> As reported by Mahesh & Aneesh, opal_prd_msg_notifier() triggers a
> FORTIFY_SOURCE warning:
> 
>   memcpy: detected field-spanning write (size 32) of single field "&item->msg" at arch/powerpc/platforms/powernv/opal-prd.c:355 (size 4)
>   WARNING: CPU: 9 PID: 660 at arch/powerpc/platforms/powernv/opal-prd.c:355 opal_prd_msg_notifier+0x174/0x188 [opal_prd]
>   NIP opal_prd_msg_notifier+0x174/0x188 [opal_prd]
>   LR  opal_prd_msg_notifier+0x170/0x188 [opal_prd]
>   Call Trace:
>     opal_prd_msg_notifier+0x170/0x188 [opal_prd] (unreliable)
>     notifier_call_chain+0xc0/0x1b0
>     atomic_notifier_call_chain+0x2c/0x40
>     opal_message_notify+0xf4/0x2c0
> 
> [...]

Applied to powerpc/next.

[1/2] powerpc/powernv: Fix fortify source warnings in opal-prd.c
      https://git.kernel.org/powerpc/c/feea65a338e52297b68ceb688eaf0ffc50310a83
[2/2] powerpc/powernv: Use struct opal_prd_msg in more places
      https://git.kernel.org/powerpc/c/22b165617b779418166319a19fd926a9c6feb9a3

cheers
diff mbox series

Patch

diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c
index 113bdb151f68..40e26e9f318f 100644
--- a/arch/powerpc/platforms/powernv/opal-prd.c
+++ b/arch/powerpc/platforms/powernv/opal-prd.c
@@ -24,13 +24,20 @@ 
 #include <linux/uaccess.h>
 
 
+struct opal_prd_msg {
+	union {
+		struct opal_prd_msg_header header;
+		DECLARE_FLEX_ARRAY(u8, data);
+	};
+};
+
 /*
  * 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 list_head		list;
-	struct opal_prd_msg_header	msg;
+	struct list_head	list;
+	struct opal_prd_msg	msg;
 };
 
 static struct device_node *prd_node;
@@ -156,7 +163,7 @@  static ssize_t opal_prd_read(struct file *file, char __user *buf,
 	int rc;
 
 	/* we need at least a header's worth of data */
-	if (count < sizeof(item->msg))
+	if (count < sizeof(item->msg.header))
 		return -EINVAL;
 
 	if (*ppos)
@@ -186,7 +193,7 @@  static ssize_t opal_prd_read(struct file *file, char __user *buf,
 			return -EINTR;
 	}
 
-	size = be16_to_cpu(item->msg.size);
+	size = be16_to_cpu(item->msg.header.size);
 	if (size > count) {
 		err = -EINVAL;
 		goto err_requeue;
@@ -352,7 +359,7 @@  static int opal_prd_msg_notifier(struct notifier_block *nb,
 	if (!item)
 		return -ENOMEM;
 
-	memcpy(&item->msg, msg->params, msg_size);
+	memcpy(&item->msg.data, msg->params, msg_size);
 
 	spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
 	list_add_tail(&item->list, &opal_prd_msg_queue);