2021-06-17 02:17:37

by Kees Cook

[permalink] [raw]
Subject: [PATCH] s390: iucv: Avoid field over-reading memcpy()

In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memcpy(), memmove(), and memset(), avoid
intentionally reading across neighboring array fields.

Add a wrapping struct to serve as the memcpy() source so the compiler
can perform appropriate bounds checking, avoiding this future warning:

In function '__fortify_memcpy',
inlined from 'iucv_message_pending' at net/iucv/iucv.c:1663:4:
./include/linux/fortify-string.h:246:4: error: call to '__read_overflow2_field' declared with attribute error: detected read beyond size of field (2nd parameter)

Signed-off-by: Kees Cook <[email protected]>
---
net/iucv/iucv.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 349c6ac3313f..e6795d5a546a 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -1635,14 +1635,16 @@ struct iucv_message_pending {
u8 iptype;
u32 ipmsgid;
u32 iptrgcls;
- union {
- u32 iprmmsg1_u32;
- u8 iprmmsg1[4];
- } ln1msg1;
- union {
- u32 ipbfln1f;
- u8 iprmmsg2[4];
- } ln1msg2;
+ struct {
+ union {
+ u32 iprmmsg1_u32;
+ u8 iprmmsg1[4];
+ } ln1msg1;
+ union {
+ u32 ipbfln1f;
+ u8 iprmmsg2[4];
+ } ln1msg2;
+ } rmmsg;
u32 res1[3];
u32 ipbfln2f;
u8 ippollfg;
@@ -1660,10 +1662,10 @@ static void iucv_message_pending(struct iucv_irq_data *data)
msg.id = imp->ipmsgid;
msg.class = imp->iptrgcls;
if (imp->ipflags1 & IUCV_IPRMDATA) {
- memcpy(msg.rmmsg, imp->ln1msg1.iprmmsg1, 8);
+ memcpy(msg.rmmsg, &imp->rmmsg, 8);
msg.length = 8;
} else
- msg.length = imp->ln1msg2.ipbfln1f;
+ msg.length = imp->rmmsg.ln1msg2.ipbfln1f;
msg.reply_size = imp->ipbfln2f;
path->handler->message_pending(path, &msg);
}
--
2.25.1


2021-06-29 14:28:39

by Heiko Carstens

[permalink] [raw]
Subject: Re: [PATCH] s390: iucv: Avoid field over-reading memcpy()

On Wed, Jun 16, 2021 at 01:19:42PM -0700, Kees Cook wrote:
> In preparation for FORTIFY_SOURCE performing compile-time and run-time
> field bounds checking for memcpy(), memmove(), and memset(), avoid
> intentionally reading across neighboring array fields.
>
> Add a wrapping struct to serve as the memcpy() source so the compiler
> can perform appropriate bounds checking, avoiding this future warning:
>
> In function '__fortify_memcpy',
> inlined from 'iucv_message_pending' at net/iucv/iucv.c:1663:4:
> ./include/linux/fortify-string.h:246:4: error: call to '__read_overflow2_field' declared with attribute error: detected read beyond size of field (2nd parameter)
>
> Signed-off-by: Kees Cook <[email protected]>
> ---
> net/iucv/iucv.c | 22 ++++++++++++----------
> 1 file changed, 12 insertions(+), 10 deletions(-)

This one is for Julian Wiedmann and Karsten Graul.

2021-06-29 15:42:29

by Karsten Graul

[permalink] [raw]
Subject: Re: [PATCH] s390: iucv: Avoid field over-reading memcpy()

On 16/06/2021 22:19, Kees Cook wrote:
> In preparation for FORTIFY_SOURCE performing compile-time and run-time
> field bounds checking for memcpy(), memmove(), and memset(), avoid
> intentionally reading across neighboring array fields.
>
> Add a wrapping struct to serve as the memcpy() source so the compiler
> can perform appropriate bounds checking, avoiding this future warning:
>
> In function '__fortify_memcpy',
> inlined from 'iucv_message_pending' at net/iucv/iucv.c:1663:4:
> ./include/linux/fortify-string.h:246:4: error: call to '__read_overflow2_field' declared with attribute error: detected read beyond size of field (2nd parameter)
>
> Signed-off-by: Kees Cook <[email protected]>

Looks good, thanks for taking care of that change.

Acked-by: Karsten Graul <[email protected]>

> ---
> net/iucv/iucv.c | 22 ++++++++++++----------
> 1 file changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
> index 349c6ac3313f..e6795d5a546a 100644
> --- a/net/iucv/iucv.c
> +++ b/net/iucv/iucv.c
> @@ -1635,14 +1635,16 @@ struct iucv_message_pending {
> u8 iptype;
> u32 ipmsgid;
> u32 iptrgcls;
> - union {
> - u32 iprmmsg1_u32;
> - u8 iprmmsg1[4];
> - } ln1msg1;
> - union {
> - u32 ipbfln1f;
> - u8 iprmmsg2[4];
> - } ln1msg2;
> + struct {
> + union {
> + u32 iprmmsg1_u32;
> + u8 iprmmsg1[4];
> + } ln1msg1;
> + union {
> + u32 ipbfln1f;
> + u8 iprmmsg2[4];
> + } ln1msg2;
> + } rmmsg;
> u32 res1[3];
> u32 ipbfln2f;
> u8 ippollfg;
> @@ -1660,10 +1662,10 @@ static void iucv_message_pending(struct iucv_irq_data *data)
> msg.id = imp->ipmsgid;
> msg.class = imp->iptrgcls;
> if (imp->ipflags1 & IUCV_IPRMDATA) {
> - memcpy(msg.rmmsg, imp->ln1msg1.iprmmsg1, 8);
> + memcpy(msg.rmmsg, &imp->rmmsg, 8);
> msg.length = 8;
> } else
> - msg.length = imp->ln1msg2.ipbfln1f;
> + msg.length = imp->rmmsg.ln1msg2.ipbfln1f;
> msg.reply_size = imp->ipbfln2f;
> path->handler->message_pending(path, &msg);
> }
>

--
Karsten

(I'm a dude)