When delivering an ICMP packet to the ctlinput function, ensure that

the outer IP header, the ICMP header, the inner IP header and the
first n bytes are stored in contgous memory. The ctlinput functions
currently rely on this for n = 8. This fixes a bug in case the inner IP
header had options.
While there, remove the options from the outer header and provide a
way to increase n to allow improved ICMP handling for SCTP. This will
be added in another commit.

MFC after:	1 week
This commit is contained in:
Michael Tuexen 2016-04-14 19:51:29 +00:00
parent 9b8f7eaf6a
commit f77b842746
2 changed files with 23 additions and 0 deletions

View File

@ -475,6 +475,23 @@ icmp_input(struct mbuf **mp, int *offp, int proto)
* XXX if the packet contains [IPv4 AH TCP], we can't make a * XXX if the packet contains [IPv4 AH TCP], we can't make a
* notification to TCP layer. * notification to TCP layer.
*/ */
i = sizeof(struct ip) + min(icmplen, ICMP_ADVLENPREF(icp));
ip_stripoptions(m);
if (m->m_len < i && (m = m_pullup(m, i)) == NULL) {
/* This should actually not happen */
ICMPSTAT_INC(icps_tooshort);
return (IPPROTO_DONE);
}
ip = mtod(m, struct ip *);
icp = (struct icmp *)(ip + 1);
/*
* The upper layer handler can rely on:
* - The outer IP header has no options.
* - The outer IP header, the ICMP header, the inner IP header,
* and the first n bytes of the inner payload are contiguous.
* n is at least 8, but might be larger based on
* ICMP_ADVLENPREF. See its definition in ip_icmp.h.
*/
ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
if (ctlfunc) if (ctlfunc)
(*ctlfunc)(code, (struct sockaddr *)&icmpsrc, (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,

View File

@ -136,6 +136,12 @@ struct icmp {
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
/* N.B.: must separately check that ip_hl >= 5 */ /* N.B.: must separately check that ip_hl >= 5 */
/* This is the minimum length required by RFC 792. */
/*
* ICMP_ADVLENPREF is the preferred number of bytes which should be contiguous.
* It currently reflects the required minimum.
*/
#define ICMP_ADVLENPREF(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
/* /*
* Definition of type and code field values. * Definition of type and code field values.