diff options
author | Eric Dumazet <edumazet@google.com> | 2024-04-05 14:49:39 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-06-27 14:52:13 +0300 |
commit | 82116ea1cc615fcbd568271fa4d9b31fa04eab8a (patch) | |
tree | c501f1e5e286bbcebc9903f9567eafd0c837da6e /net | |
parent | ceba8dbabdaf490d6fff4d131a57dd687a906d1d (diff) | |
download | linux-82116ea1cc615fcbd568271fa4d9b31fa04eab8a.tar.xz |
af_packet: avoid a false positive warning in packet_setsockopt()
[ Upstream commit 86d43e2bf93ccac88ef71cee36a23282ebd9e427 ]
Although the code is correct, the following line
copy_from_sockptr(&req_u.req, optval, len));
triggers this warning :
memcpy: detected field-spanning write (size 28) of single field "dst" at include/linux/sockptr.h:49 (size 16)
Refactor the code to be more explicit.
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/packet/af_packet.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 150451ddd755..ea3ebc160e25 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3799,28 +3799,30 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, case PACKET_TX_RING: { union tpacket_req_u req_u; - int len; + ret = -EINVAL; lock_sock(sk); switch (po->tp_version) { case TPACKET_V1: case TPACKET_V2: - len = sizeof(req_u.req); + if (optlen < sizeof(req_u.req)) + break; + ret = copy_from_sockptr(&req_u.req, optval, + sizeof(req_u.req)) ? + -EINVAL : 0; break; case TPACKET_V3: default: - len = sizeof(req_u.req3); + if (optlen < sizeof(req_u.req3)) + break; + ret = copy_from_sockptr(&req_u.req3, optval, + sizeof(req_u.req3)) ? + -EINVAL : 0; break; } - if (optlen < len) { - ret = -EINVAL; - } else { - if (copy_from_sockptr(&req_u.req, optval, len)) - ret = -EFAULT; - else - ret = packet_set_ring(sk, &req_u, 0, - optname == PACKET_TX_RING); - } + if (!ret) + ret = packet_set_ring(sk, &req_u, 0, + optname == PACKET_TX_RING); release_sock(sk); return ret; } |