Before accessing various fields in IPV4 network header
and TCP header, make sure the packet :
- Has IP version 4 (ip->version == 4)
- Has not a silly network length (ip->ihl >= 5)
- Is big enough to hold network and transport headers
- Has not a silly TCP header size (th->doff >= sizeof(struct tcphdr) / 4)
syzbot reported :
BUG: KMSAN: uninit-value in slhc_compress+0x5b9/0x2e60 drivers/net/slip/slhc.c:270
CPU: 0 PID: 11728 Comm: syz-executor231 Not tainted 5.6.0-rc2-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1c9/0x220 lib/dump_stack.c:118
kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118
__msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215
slhc_compress+0x5b9/0x2e60 drivers/net/slip/slhc.c:270
ppp_send_frame drivers/net/ppp/ppp_generic.c:1637 [inline]
__ppp_xmit_process+0x1902/0x2970 drivers/net/ppp/ppp_generic.c:1495
ppp_xmit_process+0x147/0x2f0 drivers/net/ppp/ppp_generic.c:1516
ppp_write+0x6bb/0x790 drivers/net/ppp/ppp_generic.c:512
do_loop_readv_writev fs/read_write.c:717 [inline]
do_iter_write+0x812/0xdc0 fs/read_write.c:1000
compat_writev+0x2df/0x5a0 fs/read_write.c:1351
do_compat_pwritev64 fs/read_write.c:1400 [inline]
__do_compat_sys_pwritev fs/read_write.c:1420 [inline]
__se_compat_sys_pwritev fs/read_write.c:1414 [inline]
__ia32_compat_sys_pwritev+0x349/0x3f0 fs/read_write.c:1414
do_syscall_32_irqs_on arch/x86/entry/common.c:339 [inline]
do_fast_syscall_32+0x3c7/0x6e0 arch/x86/entry/common.c:410
entry_SYSENTER_compat+0x68/0x77 arch/x86/entry/entry_64_compat.S:139
RIP: 0023:0xf7f7cd99
Code: 90 e8 0b 00 00 00 f3 90 0f ae e8 eb f9 8d 74 26 00 89 3c 24 c3 90 90 90 90 90 90 90 90 90 90 90 90 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90 90 90 eb 0d 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 002b:
00000000ffdb84ac EFLAGS:
00000217 ORIG_RAX:
000000000000014e
RAX:
ffffffffffffffda RBX:
0000000000000003 RCX:
00000000200001c0
RDX:
0000000000000001 RSI:
0000000000000000 RDI:
0000000000000003
RBP:
0000000040047459 R08:
0000000000000000 R09:
0000000000000000
R10:
0000000000000000 R11:
0000000000000000 R12:
0000000000000000
R13:
0000000000000000 R14:
0000000000000000 R15:
0000000000000000
Uninit was created at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline]
kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127
kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82
slab_alloc_node mm/slub.c:2793 [inline]
__kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4401
__kmalloc_reserve net/core/skbuff.c:142 [inline]
__alloc_skb+0x2fd/0xac0 net/core/skbuff.c:210
alloc_skb include/linux/skbuff.h:1051 [inline]
ppp_write+0x115/0x790 drivers/net/ppp/ppp_generic.c:500
do_loop_readv_writev fs/read_write.c:717 [inline]
do_iter_write+0x812/0xdc0 fs/read_write.c:1000
compat_writev+0x2df/0x5a0 fs/read_write.c:1351
do_compat_pwritev64 fs/read_write.c:1400 [inline]
__do_compat_sys_pwritev fs/read_write.c:1420 [inline]
__se_compat_sys_pwritev fs/read_write.c:1414 [inline]
__ia32_compat_sys_pwritev+0x349/0x3f0 fs/read_write.c:1414
do_syscall_32_irqs_on arch/x86/entry/common.c:339 [inline]
do_fast_syscall_32+0x3c7/0x6e0 arch/x86/entry/common.c:410
entry_SYSENTER_compat+0x68/0x77 arch/x86/entry/entry_64_compat.S:139
Fixes: 9863b480ae77 ("slip: Move the SLIP drivers")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
struct cstate *cs = lcs->next;
unsigned long deltaS, deltaA;
short changes = 0;
- int hlen;
+ int nlen, hlen;
unsigned char new_seq[16];
unsigned char *cp = new_seq;
struct iphdr *ip;
return isize;
ip = (struct iphdr *) icp;
+ if (ip->version != 4 || ip->ihl < 5)
+ return isize;
/* Bail if this packet isn't TCP, or is an IP fragment */
if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
comp->sls_o_tcp++;
return isize;
}
- /* Extract TCP header */
+ nlen = ip->ihl * 4;
+ if (isize < nlen + sizeof(*th))
+ return isize;
- th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
- hlen = ip->ihl*4 + th->doff*4;
+ th = (struct tcphdr *)(icp + nlen);
+ if (th->doff < sizeof(struct tcphdr) / 4)
+ return isize;
+ hlen = nlen + th->doff * 4;
/* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
* some other control bit is set). Also uncompressible if