Diff below should fix the following panic exposed by syzkaller [0]:

  panic+0x15c sys/kern/subr_prf.c:207
  m_copydata+0x17e m_getptr sys/kern/uipc_mbuf.c:1031 [inline]
  m_copydata+0x17e sys/kern/uipc_mbuf.c:722
  ip6_pullexthdr+0x16f sys/netinet6/ip6_input.c:1149
  ip6_savecontrol+0x373 sys/netinet6/ip6_input.c:1036
  rip6_input+0x7e7 sys/netinet6/raw_ip6.c:225
  ip_deliver+0x353 sys/netinet/ip_input.c:665
  ip6_input_if+0x17cb ip6_ours sys/netinet6/ip6_input.c:518 [inline]
  ip6_input_if+0x17cb sys/netinet6/ip6_input.c:340
  ipv6_input+0x48 sys/netinet6/ip6_input.c:171
  if_input_local+0x121 sys/net/if.c:781
  ip6_output+0xd26
  rip6_output+0x4c0 sys/netinet6/raw_ip6.c:481
  rip6_usrreq+0x5e1 sys/netinet6/raw_ip6.c:670
  sosend+0x645 sys/kern/uipc_socket.c:524

It adds more sanity checks inside ip6_pullexthdr().  The diff itself
comes from NetBSD where the same bug has been also exposed by syzkaller.

I couldn't trigger the issue with the reproducer, so I couldn't test the
effectiveness of the fix.  That said it seems correct to me.

[0] 
https://syzkaller.appspot.com/bug?id=a7a41a7f641844dd94c17c63f0d9ccf68884083a

ok?

Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.225
diff -u -p -r1.225 ip6_input.c
--- netinet6/ip6_input.c        12 Apr 2020 11:56:53 -0000      1.225
+++ netinet6/ip6_input.c        3 May 2020 12:01:59 -0000
@@ -1142,11 +1142,17 @@ ip6_pullexthdr(struct mbuf *m, size_t of
        }
 #endif
 
+       if (off + sizeof(ip6e) > m->m_pkthdr.len)
+               return NULL;
+
        m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
        if (nxt == IPPROTO_AH)
                elen = (ip6e.ip6e_len + 2) << 2;
        else
                elen = (ip6e.ip6e_len + 1) << 3;
+
+       if (off + elen > m->m_pkthdr.len)
+               return NULL
 
        MGET(n, M_DONTWAIT, MT_DATA);
        if (n && elen >= MLEN) {

Reply via email to