netinet*: update *mp to pass the proper value back
In ip6_[direct_]input() we are looping over the extension headers to deal with the next header. We pass a pointer to an mbuf pointer to the handling functions. In certain cases the mbuf can be updated there and we need to pass the new one back. That missing in dest6_input() and route6_input(). In tcp6_input() we should also update it before we call tcp_input(). In addition to that mark the mbuf NULL all the times when we return that we are done with handling the packet and no next header should be checked (IPPROTO_DONE). This will eventually allow us to assert proper behaviour and catch the above kind of errors more easily, expecting *mp to always be set. This change is extracted from a larger patch and not an exhaustive change across the entire stack yet. PR: 240135 Reported by: prabhakar.lakhera gmail.com MFC after: 3 weeks Sponsored by: Netflix
This commit is contained in:
parent
4df8c94283
commit
a8fe77d877
@ -530,11 +530,13 @@ tcp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
ifa_free(&ia6->ia_ifa);
|
ifa_free(&ia6->ia_ifa);
|
||||||
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR,
|
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR,
|
||||||
(caddr_t)&ip6->ip6_dst - (caddr_t)ip6);
|
(caddr_t)&ip6->ip6_dst - (caddr_t)ip6);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
if (ia6)
|
if (ia6)
|
||||||
ifa_free(&ia6->ia_ifa);
|
ifa_free(&ia6->ia_ifa);
|
||||||
|
|
||||||
|
*mp = m;
|
||||||
return (tcp_input(mp, offp, proto));
|
return (tcp_input(mp, offp, proto));
|
||||||
}
|
}
|
||||||
#endif /* INET6 */
|
#endif /* INET6 */
|
||||||
|
@ -113,17 +113,21 @@ dest6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
default: /* unknown option */
|
default: /* unknown option */
|
||||||
optlen = ip6_unknown_opt(opt, m,
|
optlen = ip6_unknown_opt(opt, m,
|
||||||
opt - mtod(m, u_int8_t *));
|
opt - mtod(m, u_int8_t *));
|
||||||
if (optlen == -1)
|
if (optlen == -1) {
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
|
}
|
||||||
optlen += 2;
|
optlen += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*offp = off;
|
*offp = off;
|
||||||
|
*mp = m;
|
||||||
return (dstopts->ip6d_nxt);
|
return (dstopts->ip6d_nxt);
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
@ -419,6 +419,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
if (ip6->ip6_plen == 0) {
|
if (ip6->ip6_plen == 0) {
|
||||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
|
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
|
||||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,6 +434,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||||
offsetof(struct ip6_hdr, ip6_plen));
|
offsetof(struct ip6_hdr, ip6_plen));
|
||||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,6 +478,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
offsetof(struct ip6_hdr, ip6_plen));
|
offsetof(struct ip6_hdr, ip6_plen));
|
||||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||||
IP6STAT_INC(ip6s_fragdropped);
|
IP6STAT_INC(ip6s_fragdropped);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,6 +614,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||||
offset - sizeof(struct ip6_frag) +
|
offset - sizeof(struct ip6_frag) +
|
||||||
offsetof(struct ip6_frag, ip6f_offlg));
|
offsetof(struct ip6_frag, ip6f_offlg));
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
|
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
|
||||||
@ -627,6 +631,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||||
offset - sizeof(struct ip6_frag) +
|
offset - sizeof(struct ip6_frag) +
|
||||||
offsetof(struct ip6_frag, ip6f_offlg));
|
offsetof(struct ip6_frag, ip6f_offlg));
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,6 +782,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
frag6_freef(q6, bucket);
|
frag6_freef(q6, bucket);
|
||||||
}
|
}
|
||||||
IP6QB_UNLOCK(bucket);
|
IP6QB_UNLOCK(bucket);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
plen += af6->ip6af_frglen;
|
plen += af6->ip6af_frglen;
|
||||||
@ -788,6 +794,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
frag6_freef(q6, bucket);
|
frag6_freef(q6, bucket);
|
||||||
}
|
}
|
||||||
IP6QB_UNLOCK(bucket);
|
IP6QB_UNLOCK(bucket);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,6 +884,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
#ifdef RSS
|
#ifdef RSS
|
||||||
/* Queue/dispatch for reprocessing. */
|
/* Queue/dispatch for reprocessing. */
|
||||||
netisr_dispatch(NETISR_IPV6_DIRECT, m);
|
netisr_dispatch(NETISR_IPV6_DIRECT, m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -892,6 +900,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
in6_ifstat_inc(dstifp, ifs6_reass_fail);
|
||||||
IP6STAT_INC(ip6s_fragdropped);
|
IP6STAT_INC(ip6s_fragdropped);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,8 +617,10 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
*/
|
*/
|
||||||
if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0)
|
if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0)
|
||||||
goto freeit;
|
goto freeit;
|
||||||
if (mld_input(m, off, icmp6len) != 0)
|
if (mld_input(m, off, icmp6len) != 0) {
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
|
}
|
||||||
/* m stays. */
|
/* m stays. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -853,6 +855,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
deliver:
|
deliver:
|
||||||
if (icmp6_notify_error(&m, off, icmp6len, code) != 0) {
|
if (icmp6_notify_error(&m, off, icmp6len, code) != 0) {
|
||||||
/* In this case, m should've been freed. */
|
/* In this case, m should've been freed. */
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -869,11 +872,13 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
/* deliver the packet to appropriate sockets */
|
/* deliver the packet to appropriate sockets */
|
||||||
icmp6_rip6_input(&m, *offp);
|
icmp6_rip6_input(&m, *offp);
|
||||||
|
|
||||||
return IPPROTO_DONE;
|
*mp = m;
|
||||||
|
return (IPPROTO_DONE);
|
||||||
|
|
||||||
freeit:
|
freeit:
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return IPPROTO_DONE;
|
*mp = NULL;
|
||||||
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1106,6 +1111,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
|
|||||||
|
|
||||||
freeit:
|
freeit:
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1918,6 +1924,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
|
|||||||
fromsa.sin6_addr = ip6->ip6_src;
|
fromsa.sin6_addr = ip6->ip6_src;
|
||||||
if (sa6_recoverscope(&fromsa)) {
|
if (sa6_recoverscope(&fromsa)) {
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2041,7 +2048,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
|
|||||||
m_freem(m);
|
m_freem(m);
|
||||||
IP6STAT_DEC(ip6s_delivered);
|
IP6STAT_DEC(ip6s_delivered);
|
||||||
}
|
}
|
||||||
return IPPROTO_DONE;
|
*mp = NULL;
|
||||||
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1010,8 +1010,10 @@ ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
|
|||||||
off += hbhlen;
|
off += hbhlen;
|
||||||
hbhlen -= sizeof(struct ip6_hbh);
|
hbhlen -= sizeof(struct ip6_hbh);
|
||||||
if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
|
if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
|
||||||
hbhlen, rtalertp, plenp) < 0)
|
hbhlen, rtalertp, plenp) < 0) {
|
||||||
|
*mp = NULL;
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
*offp = off;
|
*offp = off;
|
||||||
*mp = m;
|
*mp = m;
|
||||||
|
@ -110,9 +110,11 @@ route6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
IP6STAT_INC(ip6s_badoptions);
|
IP6STAT_INC(ip6s_badoptions);
|
||||||
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
|
||||||
(caddr_t)&rh->ip6r_type - (caddr_t)ip6);
|
(caddr_t)&rh->ip6r_type - (caddr_t)ip6);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
*offp += rhlen;
|
*offp += rhlen;
|
||||||
|
*mp = m;
|
||||||
return (rh->ip6r_nxt);
|
return (rh->ip6r_nxt);
|
||||||
}
|
}
|
||||||
|
@ -394,8 +394,11 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
else
|
else
|
||||||
UDP_PROBE(receive, NULL, last,
|
UDP_PROBE(receive, NULL, last,
|
||||||
ip6, last, uh);
|
ip6, last, uh);
|
||||||
if (udp6_append(last, n, off, fromsa))
|
if (udp6_append(last, n, off, fromsa)) {
|
||||||
|
/* XXX-BZ do we leak m here? */
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
INP_RUNLOCK(last);
|
INP_RUNLOCK(last);
|
||||||
}
|
}
|
||||||
@ -434,6 +437,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
INP_RUNLOCK(last);
|
INP_RUNLOCK(last);
|
||||||
} else
|
} else
|
||||||
INP_RUNLOCK(last);
|
INP_RUNLOCK(last);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -501,6 +505,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
if (V_udp_blackhole)
|
if (V_udp_blackhole)
|
||||||
goto badunlocked;
|
goto badunlocked;
|
||||||
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
|
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
INP_RLOCK_ASSERT(inp);
|
INP_RLOCK_ASSERT(inp);
|
||||||
@ -509,6 +514,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
if (up->u_rxcslen == 0 || up->u_rxcslen > ulen) {
|
if (up->u_rxcslen == 0 || up->u_rxcslen > ulen) {
|
||||||
INP_RUNLOCK(inp);
|
INP_RUNLOCK(inp);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,11 +524,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
|
|||||||
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
|
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
|
||||||
if (udp6_append(inp, m, off, fromsa) == 0)
|
if (udp6_append(inp, m, off, fromsa) == 0)
|
||||||
INP_RUNLOCK(inp);
|
INP_RUNLOCK(inp);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
|
|
||||||
badunlocked:
|
badunlocked:
|
||||||
if (m)
|
if (m)
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
*mp = NULL;
|
||||||
return (IPPROTO_DONE);
|
return (IPPROTO_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user