Commit 86d43e2b authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

af_packet: avoid a false positive warning in packet_setsockopt()



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: default avatarsyzbot <syzkaller@googlegroups.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a29689e6
Loading
Loading
Loading
Loading
+14 −12
Original line number Diff line number Diff line
@@ -3800,28 +3800,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
		if (!ret)
			ret = packet_set_ring(sk, &req_u, 0,
					      optname == PACKET_TX_RING);
		}
		release_sock(sk);
		return ret;
	}