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
This commit is contained in:
cem 2016-04-26 23:02:18 +00:00
parent 8bb71df062
commit 2ec16edcab

View File

@ -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 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
return (error);
}
#undef INP_WLOCK_RECHECK
#undef INP_WLOCK_RECHECK_CLEANUP
/*
* Attach TCP protocol to socket, allocating