[SSI-devel] Possible sock leak?
Brought to you by:
brucewalker,
rogertsang
From: John S. <joh...@gm...> - 2006-07-14 13:48:35
|
For some reason this didn't get posted. ---------- Forwarded message ---------- From: John Steinman <joh...@gm...> Date: Jul 13, 2006 3:06 PM Subject: Possible sock leak? To: ssi...@li... The call to unix_peer_get calls ssi_unix_sock_hold to reference the sock and I would expect a caller of unix_peer_get would call ssi_unix_sock_put at some at some point to de-referrence the sock. There appears to be some inconsistent logic here and a potential risk of a sock leak? Can someone explain which should be called sock_put or ssi_unix_sock_put? static struct sock *unix_peer_get(struct sock *s) { struct sock *peer; unix_state_rlock(s); peer = unix_peer(s); if (peer) ssi_unix_sock_hold(peer); unix_state_runlock(s); return peer; } static inline void ssi_unix_sock_hold(unix_socket *s) { if (!rmtunix_ismagic(s)) sock_hold(s); } static inline void ssi_unix_sock_put(unix_socket *s, int freeinfo) { if (!rmtunix_ismagic(s)) { sock_put(s); } else if (freeinfo && !rmtunix_iscached(s)) { rmtunix_clrmagic(s); kfree(s); } } The callers are: net/unix/af_unix.c In unix_getname calls unix_peer_get but if peer is true we go to "out" without calling ssi_unix_sock_put possible leak here: if (peer) { sk = unix_peer_get(sk); err = -ENOTCONN; if (!sk) goto out; if (ssi_unix_ismagic(sk)) { err = ssi_unix_getpeername(sk, uaddr, uaddr_len); goto out; } err = 0; } else { sock_hold(sk); } out: return err; In unix_dgram_sendmsg calls unix_peer_get but in the "out" code sock_put is called not ssi_unix_sock_put: if (msg->msg_namelen) { err = unix_mkname(sunaddr, msg->msg_namelen, &hash); if (err < 0) goto out; namelen = err; } else { sunaddr = NULL; err = -ENOTCONN; other = unix_peer_get(sk); if (!other) goto out; } out: if (other) sock_put(other); scm_destroy(siocb->scm); return err; In unix_stream_sendmsg calls unix_peer_get but I believe calls correctly ssi_unix_sock_put for the out_err condition but call sock_put for the non out_err: if (msg->msg_namelen) { err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; goto out_err; } else { sunaddr = NULL; err = -ENOTCONN; other = unix_peer_get(sk); if (!other) goto out_err; } sock_put(other); scm_destroy(siocb->scm); siocb->scm = NULL; return sent; pipe_err_free: unix_state_runlock(other); kfree_skb(skb); pipe_err: if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL)) ssi_unix_send_sig(SIGPIPE,current,0); err = -EPIPE; out_err: if (other) ssi_unix_sock_put(other, 0); scm_destroy(siocb->scm); siocb->scm = NULL; return sent ? : err; } -- John F. Steinman -- John F. Steinman |