diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-11-09 12:15:30 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-11-09 12:15:30 +0000 |
commit | f14a9ba0ac2b5f84f20415bae9199fd48b0ab259 (patch) | |
tree | 8afa0092ea50b3e6def5234ebfc3d0fe55c50da6 /sys | |
parent | 45be7ac5ce7032c92c1d7217d61126eec9c2f7ae (diff) |
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.
Diffstat (limited to 'sys')
-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); |