diff options
author | cem <cem@FreeBSD.org> | 2016-04-26 23:02:18 +0000 |
---|---|---|
committer | cem <cem@FreeBSD.org> | 2016-04-26 23:02:18 +0000 |
commit | 2ec16edcab38f68b4bff79343cb860259c3c25ef (patch) | |
tree | 8b77d883157160020c04d445229b712876dd36a1 | |
parent | 8bb71df062a605b270c567a55b0a11e1556a6fe2 (diff) | |
download | FreeBSD-src-2ec16edcab38f68b4bff79343cb860259c3c25ef.zip FreeBSD-src-2ec16edcab38f68b4bff79343cb860259c3c25ef.tar.gz |
tcp_usrreq: Free allocated buffer in relock case
The disgusting macro INP_WLOCK_RECHECK may early-return. In
tcp_default_ctloutput() the TCP_CCALGOOPT case allocates memory before invoking
this macro, which may leak memory.
Add a _CLEANUP variant that takes a code argument to perform variable cleanup
in the early return path. Use it to free the 'pbuf' allocated in
tcp_default_ctloutput().
I am not especially happy with this macro, but I reckon it's not any worse than
INP_WLOCK_RECHECK already was.
Reported by: Coverity
CID: 1350286
Sponsored by: EMC / Isilon Storage Division
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 6a3cde6..204c354 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1361,14 +1361,16 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti) * has to revalidate that the connection is still valid for the socket * option. */ -#define INP_WLOCK_RECHECK(inp) do { \ +#define INP_WLOCK_RECHECK_CLEANUP(inp, cleanup) do { \ INP_WLOCK(inp); \ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { \ INP_WUNLOCK(inp); \ + cleanup; \ return (ECONNRESET); \ } \ tp = intotcpcb(inp); \ } while(0) +#define INP_WLOCK_RECHECK(inp) INP_WLOCK_RECHECK_CLEANUP((inp), /* noop */) int tcp_ctloutput(struct socket *so, struct sockopt *sopt) @@ -1497,7 +1499,7 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp free(pbuf, M_TEMP); return (error); } - INP_WLOCK_RECHECK(inp); + INP_WLOCK_RECHECK_CLEANUP(inp, free(pbuf, M_TEMP)); if (CC_ALGO(tp)->ctl_output != NULL) error = CC_ALGO(tp)->ctl_output(tp->ccv, sopt, pbuf); else @@ -1838,6 +1840,7 @@ unlock_and_done: return (error); } #undef INP_WLOCK_RECHECK +#undef INP_WLOCK_RECHECK_CLEANUP /* * Attach TCP protocol to socket, allocating |