diff options
author | 2015-11-09 12:15:29 +0000 | |
---|---|---|
committer | 2015-11-09 12:15:29 +0000 | |
commit | c1a024aae2ea3047586478afb6b390660a3cc388 (patch) | |
tree | 7da518c2d490ee3e607ce70531a54d6d84b135d0 | |
parent | use strncasecmp() (diff) | |
download | wireguard-openbsd-c1a024aae2ea3047586478afb6b390660a3cc388.tar.xz wireguard-openbsd-c1a024aae2ea3047586478afb6b390660a3cc388.zip |
Do not leave dangling pointers in the ART tree in case of memory
exhaustion.
Reported by benno@ and found thanks to his bgpd(8) test setup.
-rw-r--r-- | sys/net/rtable.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/sys/net/rtable.c b/sys/net/rtable.c index 150588304cb..9f7dcf08496 100644 --- a/sys/net/rtable.c +++ b/sys/net/rtable.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtable.c,v 1.22 2015/11/06 17:55:55 mpi Exp $ */ +/* $OpenBSD: rtable.c,v 1.23 2015/11/09 12:15:29 mpi Exp $ */ /* * Copyright (c) 2014-2015 Martin Pieuchot @@ -623,6 +623,23 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst, } #endif + /* + * XXX Allocating a sockaddr for the mask per node wastes a lot + * of memory, thankfully we'll get rid of that when rt_mask() + * will be no more. + */ + if (mask != NULL) { + struct sockaddr *msk; + + msk = malloc(dst->sa_len, M_RTABLE, M_NOWAIT | M_ZERO); + if (msk == NULL) { + error = ENOMEM; + goto out; + } + memcpy(msk, mask, dst->sa_len); + rt->rt_mask = msk; + } + an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO); if (an == NULL) { error = ENOBUFS; @@ -634,6 +651,8 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst, prev = art_insert(ar, an, addr, plen); if (prev == NULL) { + free(rt->rt_mask, M_RTABLE, 0); + rt->rt_mask = NULL; pool_put(&an_pool, an); error = ESRCH; goto out; @@ -675,25 +694,6 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst, rt->rt_node = an; rt->rt_dest = dst; - - /* - * XXX Allocating a sockaddr for the mask per node wastes a lot - * of memory, thankfully we'll get rid of that when rt_mask() - * will be no more. - */ - if (mask != NULL) { - struct sockaddr *msk; - - msk = malloc(dst->sa_len, M_RTABLE, M_NOWAIT | M_ZERO); - if (msk == NULL) { - pool_put(&an_pool, an); - error = ENOMEM; - goto out; - } - memcpy(msk, mask, dst->sa_len); - rt->rt_mask = msk; - } - rtref(rt); SLIST_INSERT_HEAD(&an->an_rtlist, rt, rt_next); |