ipsec: Validate the protocol identifier in ipsec4_ctlinput()

key_allocsa() expects to handle only IPSec protocols and has an
assertion to this effect.  However, ipsec4_ctlinput() has to handle
messages from ICMP unreachable packets and was not validating the
protocol number.  In practice such a packet would simply fail to match
any SADB entries and would thus be ignored.

Reported by:	syzbot+6a9ef6fcfadb9f3877fe@syzkaller.appspotmail.com
Reviewed by:	ae
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D31890
This commit is contained in:
Mark Johnston 2021-09-10 09:07:59 -04:00
parent b1e6a792d6
commit 10eb2a2bde

View File

@ -276,6 +276,7 @@ ipsec4_ctlinput(int code, struct sockaddr *sa, void *v)
struct icmp *icp;
struct ip *ip = v;
uint32_t pmtu, spi;
uint8_t proto;
if (code != PRC_MSGSIZE || ip == NULL)
return (EINVAL);
@ -289,8 +290,13 @@ ipsec4_ctlinput(int code, struct sockaddr *sa, void *v)
if (pmtu < V_ip4_ipsec_min_pmtu)
return (EINVAL);
proto = ip->ip_p;
if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
proto != IPPROTO_IPCOMP)
return (EINVAL);
memcpy(&spi, (caddr_t)ip + (ip->ip_hl << 2), sizeof(spi));
sav = key_allocsa((union sockaddr_union *)sa, ip->ip_p, spi);
sav = key_allocsa((union sockaddr_union *)sa, proto, spi);
if (sav == NULL)
return (ENOENT);