summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-02-21 17:22:06 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-02-21 17:22:06 +0000
commitf2132ef3d7e0cc16e2af76cc163c11d21fd04d1f (patch)
tree7473e24e896192d0430a0c6668f33357b409f533
parent81e2483802b2414cb711b9ce30adf852ea76e70f (diff)
make validation code more strict for ND6/dest6 variable length headers.
check duplicated nd6_ifinfo table initialization in a better way. sync with kame
-rw-r--r--sys/netinet6/dest6.c19
-rw-r--r--sys/netinet6/nd6.c32
2 files changed, 33 insertions, 18 deletions
diff --git a/sys/netinet6/dest6.c b/sys/netinet6/dest6.c
index cca97912931..63328823a57 100644
--- a/sys/netinet6/dest6.c
+++ b/sys/netinet6/dest6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: dest6.c,v 1.6 2001/02/16 15:57:58 itojun Exp $ */
-/* $KAME: dest6.c,v 1.23 2001/01/23 13:32:26 itojun Exp $ */
+/* $OpenBSD: dest6.c,v 1.7 2001/02/21 17:22:05 itojun Exp $ */
+/* $KAME: dest6.c,v 1.24 2001/02/21 16:12:35 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -88,22 +88,19 @@ dest6_input(mp, offp, proto)
/* search header for all options. */
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
- switch(*opt) {
+ if (*opt != IP6OPT_PAD1 && dstoptlen < IP6OPT_MINLEN) {
+ ip6stat.ip6s_toosmall++;
+ goto bad;
+ }
+
+ switch (*opt) {
case IP6OPT_PAD1:
optlen = 1;
break;
case IP6OPT_PADN:
- if (dstoptlen < IP6OPT_MINLEN) {
- ip6stat.ip6s_toosmall++;
- goto bad;
- }
optlen = *(opt + 1) + 2;
break;
default: /* unknown option */
- if (dstoptlen < IP6OPT_MINLEN) {
- ip6stat.ip6s_toosmall++;
- goto bad;
- }
if ((optlen = ip6_unknown_opt(opt, m,
opt-mtod(m, u_int8_t *))) == -1)
return(IPPROTO_DONE);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index c7f72da2688..5f069b783c0 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nd6.c,v 1.26 2001/02/16 16:00:00 itojun Exp $ */
-/* $KAME: nd6.c,v 1.126 2001/02/16 12:49:45 itojun Exp $ */
+/* $OpenBSD: nd6.c,v 1.27 2001/02/21 17:22:05 itojun Exp $ */
+/* $KAME: nd6.c,v 1.131 2001/02/21 16:28:18 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -169,8 +169,14 @@ nd6_ifattach(ifp)
#define ND nd_ifinfo[ifp->if_index]
- /* don't initialize if called twice */
- if (ND.linkmtu)
+ /*
+ * Don't initialize if called twice.
+ * XXX: to detect this, we should choose a member that is never set
+ * before initialization of the ND structure itself. We formaly used
+ * the linkmtu member, which was not suitable because it could be
+ * initialized via "ifconfig mtu".
+ */
+ if (ND.basereachable)
return;
ND.linkmtu = ifindex2ifnet[ifp->if_index]->if_mtu;
@@ -275,6 +281,12 @@ nd6_option(ndopts)
nd_opt = ndopts->nd_opts_search;
+ /* make sure nd_opt_len is inside the buffer */
+ if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
+ bzero(ndopts, sizeof(*ndopts));
+ return NULL;
+ }
+
olen = nd_opt->nd_opt_len << 3;
if (olen == 0) {
/*
@@ -286,7 +298,12 @@ nd6_option(ndopts)
}
ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
- if (!(ndopts->nd_opts_search < ndopts->nd_opts_last)) {
+ if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
+ /* option overruns the end of buffer, invalid */
+ bzero(ndopts, sizeof(*ndopts));
+ return NULL;
+ } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
+ /* reached the end of options chain */
ndopts->nd_opts_done = 1;
ndopts->nd_opts_search = NULL;
}
@@ -333,8 +350,9 @@ nd6_options(ndopts)
case ND_OPT_MTU:
case ND_OPT_REDIRECTED_HEADER:
if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
- printf("duplicated ND6 option found "
- "(type=%d)\n", nd_opt->nd_opt_type);
+ nd6log((LOG_INFO,
+ "duplicated ND6 option found (type=%d)\n",
+ nd_opt->nd_opt_type));
/* XXX bark? */
} else {
ndopts->nd_opt_array[nd_opt->nd_opt_type]