hartkopp/can-isotp

MSG_CMSG_COMPAT set by the kernel for `recvmsg`

Closed this issue · 7 comments

Hi, not sure if this is the right place for this issue, but I've encountered a problem with more recent kernels > 5.10 on ARM64 machines.

On any recvmsg call from the kernel, the flag MSG_CMSG_COMPAT is set on my machine, which results in EINVAL on this line:

if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))

The issue can be reproduced on any Raspberry PI 4 with the latest kernel.

One remark, isotprecv is not affected by this issue, since it uses read and not recvmsg.

I propose to add this flag to this line:

if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))

For reference, I guess the issue comes from this line:
https://elixir.bootlin.com/linux/latest/source/net/compat.c#L507

@marckleinebudde @olerem : Using MSG_CMSG_COMPAT in recvmsg flags seems to be a common pattern, e.g. in af_packet.c or bluetooth/hci_sock.c .

I don't see any 'special' handlings in cmsg's in isotp.c but some special created cmsg's in j1939/socket.c (search for put_cmsg()).

Do you see any problems with adding the MSG_CMSG_COMPAT flag in recvmsg flags ?

diff --git a/net/can/isotp.c b/net/can/isotp.c
index 9bc344851704..fd0e297a8584 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1099,11 +1099,11 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
        struct sock *sk = sock->sk;
        struct sk_buff *skb;
        struct isotp_sock *so = isotp_sk(sk);
        int ret = 0;
 
-       if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))
+       if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK | MSG_CMSG_COMPAT))
                return -EINVAL;
 
        if (!so->bound)
                return -EADDRNOTAVAIL;
 
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 7e90f9e61d9b..1790469b2580 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -796,11 +796,11 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg,
        struct sock *sk = sock->sk;
        struct sk_buff *skb;
        struct j1939_sk_buff_cb *skcb;
        int ret = 0;
 
-       if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE))
+       if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE | MSG_CMSG_COMPAT))
                return -EINVAL;
 
        if (flags & MSG_ERRQUEUE)
                return sock_recv_errqueue(sock->sk, msg, size, SOL_CAN_J1939,
                                          SCM_J1939_ERRQUEUE);

Hi, not sure if this is the right place for this issue, but I've encountered a problem with more recent kernels > 5.10 on ARM64 machines.

On any recvmsg call from the kernel, the flag MSG_CMSG_COMPAT is set on my machine, which results in EINVAL on this line:

Are you using a 32 bit userspace?

Yes, I‘m using a 32bit userspace.

This is where the MSG_CMSG_COMPAT comes from.

@marckleinebudde @olerem : Using MSG_CMSG_COMPAT in recvmsg flags seems to be a common pattern, e.g. in af_packet.c or bluetooth/hci_sock.c .

I don't see any 'special' handlings in cmsg's in isotp.c but some special created cmsg's in j1939/socket.c (search for put_cmsg()).

Looks good send a patch.

Has been fixed in mainline Linux and stable kernels.