Skip to content

Commit

Permalink
Merge branch 'freebsd/12-stable/master' into hardened/12-stable/master
Browse files Browse the repository at this point in the history
* freebsd/12-stable/master:
  MFC r350645: Correct ICMPv6/MLDv2 out-of-bounds memory access
  MFC r350635: bsnmp: add asn1 message length validation
  • Loading branch information
opntr-auto committed Aug 6, 2019
2 parents 082ea84 + 6d7f541 commit 9f19329
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 25 deletions.
5 changes: 5 additions & 0 deletions contrib/bsnmp/lib/asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ asn_get_header(struct asn_buf *b, u_char *type, asn_len_t *len)
*len = *b->asn_cptr++;
b->asn_len--;
}
if (*len > b->asn_len) {
asn_error(b, "len %u exceeding asn_len %u", *len, b->asn_len);
return (ASN_ERR_EOBUF);
}

return (ASN_ERR_OK);
}

Expand Down
48 changes: 23 additions & 25 deletions sys/netinet6/mld6.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,15 @@ static int mld_v2_enqueue_group_record(struct mbufq *,
struct in6_multi *, const int, const int, const int,
const int);
static int mld_v2_input_query(struct ifnet *, const struct ip6_hdr *,
struct mbuf *, const int, const int);
struct mbuf *, struct mldv2_query *, const int, const int);
static int mld_v2_merge_state_changes(struct in6_multi *,
struct mbufq *);
static void mld_v2_process_group_timers(struct in6_multi_head *,
struct mbufq *, struct mbufq *,
struct in6_multi *, const int);
static int mld_v2_process_group_query(struct in6_multi *,
struct mld_ifsoftc *mli, int, struct mbuf *, const int);
struct mld_ifsoftc *mli, int, struct mbuf *,
struct mldv2_query *, const int);
static int sysctl_mld_gsr(SYSCTL_HANDLER_ARGS);
static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS);

Expand Down Expand Up @@ -803,16 +804,16 @@ mld_v1_update_group(struct in6_multi *inm, const int timer)
* Process a received MLDv2 general, group-specific or
* group-and-source-specific query.
*
* Assumes that the query header has been pulled up to sizeof(mldv2_query).
* Assumes that mld points to a struct mldv2_query which is stored in
* contiguous memory.
*
* Return 0 if successful, otherwise an appropriate error code is returned.
*/
static int
mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
struct mbuf *m, const int off, const int icmp6len)
struct mbuf *m, struct mldv2_query *mld, const int off, const int icmp6len)
{
struct mld_ifsoftc *mli;
struct mldv2_query *mld;
struct in6_multi *inm;
uint32_t maxdelay, nsrc, qqi;
int is_general_query;
Expand Down Expand Up @@ -844,8 +845,6 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,

CTR2(KTR_MLD, "input v2 query on ifp %p(%s)", ifp, if_name(ifp));

mld = (struct mldv2_query *)(mtod(m, uint8_t *) + off);

maxdelay = ntohs(mld->mld_maxdelay); /* in 1/10ths of a second */
if (maxdelay >= 32768) {
maxdelay = (MLD_MRC_MANT(maxdelay) | 0x1000) <<
Expand Down Expand Up @@ -970,7 +969,7 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
* group-specific or group-and-source query.
*/
if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer)
mld_v2_process_group_query(inm, mli, timer, m, off);
mld_v2_process_group_query(inm, mli, timer, m, mld, off);

/* XXX Clear embedded scope ID as userland won't expect it. */
in6_clearscope(&mld->mld_addr);
Expand All @@ -991,17 +990,15 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
*/
static int
mld_v2_process_group_query(struct in6_multi *inm, struct mld_ifsoftc *mli,
int timer, struct mbuf *m0, const int off)
int timer, struct mbuf *m0, struct mldv2_query *mld, const int off)
{
struct mldv2_query *mld;
int retval;
uint16_t nsrc;

IN6_MULTI_LIST_LOCK_ASSERT();
MLD_LOCK_ASSERT();

retval = 0;
mld = (struct mldv2_query *)(mtod(m0, uint8_t *) + off);

switch (inm->in6m_state) {
case MLD_NOT_MEMBER:
Expand All @@ -1021,6 +1018,15 @@ mld_v2_process_group_query(struct in6_multi *inm, struct mld_ifsoftc *mli,

nsrc = ntohs(mld->mld_numsrc);

/* Length should be checked by calling function. */
KASSERT((m0->m_flags & M_PKTHDR) == 0 ||
m0->m_pkthdr.len >= off + sizeof(struct mldv2_query) +
nsrc * sizeof(struct in6_addr),
("mldv2 packet is too short: (%d bytes < %zd bytes, m=%p)",
m0->m_pkthdr.len, off + sizeof(struct mldv2_query) +
nsrc * sizeof(struct in6_addr), m0));


/*
* Deal with group-specific queries upfront.
* If any group query is already pending, purge any recorded
Expand Down Expand Up @@ -1062,28 +1068,20 @@ mld_v2_process_group_query(struct in6_multi *inm, struct mld_ifsoftc *mli,
* report for those sources.
*/
if (inm->in6m_nsrc > 0) {
struct mbuf *m;
uint8_t *sp;
struct in6_addr srcaddr;
int i, nrecorded;
int soff;

m = m0;
soff = off + sizeof(struct mldv2_query);
nrecorded = 0;
for (i = 0; i < nsrc; i++) {
sp = mtod(m, uint8_t *) + soff;
retval = in6m_record_source(inm,
(const struct in6_addr *)sp);
m_copydata(m0, soff, sizeof(struct in6_addr),
(caddr_t)&srcaddr);
retval = in6m_record_source(inm, &srcaddr);
if (retval < 0)
break;
nrecorded += retval;
soff += sizeof(struct in6_addr);
if (soff >= m->m_len) {
soff = soff - m->m_len;
m = m->m_next;
if (m == NULL)
break;
}
}
if (nrecorded > 0) {
CTR1(KTR_MLD,
Expand Down Expand Up @@ -1292,8 +1290,8 @@ mld_input(struct mbuf *m, int off, int icmp6len)
if (mld_v1_input_query(ifp, ip6, mld) != 0)
return (0);
} else if (icmp6len >= sizeof(struct mldv2_query)) {
if (mld_v2_input_query(ifp, ip6, m, off,
icmp6len) != 0)
if (mld_v2_input_query(ifp, ip6, m,
(struct mldv2_query *)mld, off, icmp6len) != 0)
return (0);
}
break;
Expand Down

0 comments on commit 9f19329

Please sign in to comment.