Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55ca7b1d authored by Eric Dumazet's avatar Eric Dumazet Committed by Greg Kroah-Hartman
Browse files

net: af_packet: fix race in PACKET_{R|T}X_RING




[ Upstream commit 5171b37d959641bbc619781caf62e61f7b940871 ]

In order to remove the race caught by syzbot [1], we need
to lock the socket before using po->tp_version as this could
change under us otherwise.

This means lock_sock() and release_sock() must be done by
packet_set_ring() callers.

[1] :
BUG: KMSAN: uninit-value in packet_set_ring+0x1254/0x3870 net/packet/af_packet.c:4249
CPU: 0 PID: 20195 Comm: syzkaller707632 Not tainted 4.16.0+ #83
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:17 [inline]
 dump_stack+0x185/0x1d0 lib/dump_stack.c:53
 kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067
 __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676
 packet_set_ring+0x1254/0x3870 net/packet/af_packet.c:4249
 packet_setsockopt+0x12c6/0x5a90 net/packet/af_packet.c:3662
 SYSC_setsockopt+0x4b8/0x570 net/socket.c:1849
 SyS_setsockopt+0x76/0xa0 net/socket.c:1828
 do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287
 entry_SYSCALL_64_after_hwframe+0x3d/0xa2
RIP: 0033:0x449099
RSP: 002b:00007f42b5307ce8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036
RAX: ffffffffffffffda RBX: 000000000070003c RCX: 0000000000449099
RDX: 0000000000000005 RSI: 0000000000000107 RDI: 0000000000000003
RBP: 0000000000700038 R08: 000000000000001c R09: 0000000000000000
R10: 00000000200000c0 R11: 0000000000000246 R12: 0000000000000000
R13: 000000000080eecf R14: 00007f42b53089c0 R15: 0000000000000001

Local variable description: ----req_u@packet_setsockopt
Variable was created at:
 packet_setsockopt+0x13f/0x5a90 net/packet/af_packet.c:3612
 SYSC_setsockopt+0x4b8/0x570 net/socket.c:1849

Fixes: f6fb8f10 ("af-packet: TPACKET_V3 flexible buffer implementation.")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 228ce13c
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -3024,6 +3024,7 @@ static int packet_release(struct socket *sock)

	packet_flush_mclist(sk);

	lock_sock(sk);
	if (po->rx_ring.pg_vec) {
		memset(&req_u, 0, sizeof(req_u));
		packet_set_ring(sk, &req_u, 1, 0);
@@ -3033,6 +3034,7 @@ static int packet_release(struct socket *sock)
		memset(&req_u, 0, sizeof(req_u));
		packet_set_ring(sk, &req_u, 1, 1);
	}
	release_sock(sk);

	f = fanout_release(sk);

@@ -3661,6 +3663,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
		union tpacket_req_u req_u;
		int len;

		lock_sock(sk);
		switch (po->tp_version) {
		case TPACKET_V1:
		case TPACKET_V2:
@@ -3671,13 +3674,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
			len = sizeof(req_u.req3);
			break;
		}
		if (optlen < len)
			return -EINVAL;
		if (optlen < len) {
			ret = -EINVAL;
		} else {
			if (copy_from_user(&req_u.req, optval, len))
			return -EFAULT;
		return packet_set_ring(sk, &req_u, 0,
				ret = -EFAULT;
			else
				ret = packet_set_ring(sk, &req_u, 0,
						    optname == PACKET_TX_RING);
		}
		release_sock(sk);
		return ret;
	}
	case PACKET_COPY_THRESH:
	{
		int val;
@@ -4247,7 +4255,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
	/* Added to avoid minimal code churn */
	struct tpacket_req *req = &req_u->req;

	lock_sock(sk);
	/* Opening a Tx-ring is NOT supported in TPACKET_V3 */
	if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
		net_warn_ratelimited("Tx-ring is not supported.\n");
@@ -4383,7 +4390,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
	if (pg_vec)
		free_pg_vec(pg_vec, order, req->tp_block_nr);
out:
	release_sock(sk);
	return err;
}