diff options
author | Kuniyuki Iwashima <kuniyu@amazon.com> | 2024-12-13 14:08:42 +0300 |
---|---|---|
committer | Paolo Abeni <pabeni@redhat.com> | 2024-12-17 14:08:27 +0300 |
commit | d460b04bc452cf15810b79c15381fffd9d201915 (patch) | |
tree | 7a7eca7aa1c855fb2e6f07b76591988948dbfe6e /net/unix/af_unix.c | |
parent | 6c444255b193b5b9c5a18c3784d960e10e1833a2 (diff) | |
download | linux-d460b04bc452cf15810b79c15381fffd9d201915.tar.xz |
af_unix: Clean up error paths in unix_stream_sendmsg().
If we move send_sig() to the SEND_SHUTDOWN check before
the while loop, then we can reuse the same kfree_skb()
after the pipe_err_free label.
Let's gather the scattered kfree_skb()s in error paths.
While at it, some style issues are fixed, and the pipe_err_free
label is renamed to out_pipe to match other label names.
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 660d8b8130ca..d30bcd50527e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2275,8 +2275,13 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, } } - if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) - goto pipe_err; + if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) { + if (!(msg->msg_flags & MSG_NOSIGNAL)) + send_sig(SIGPIPE, current, 0); + + err = -EPIPE; + goto out_err; + } while (sent < len) { size = len - sent; @@ -2305,20 +2310,18 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, /* Only send the fds in the first buffer */ err = unix_scm_to_skb(&scm, skb, !fds_sent); - if (err < 0) { - kfree_skb(skb); - goto out_err; - } + if (err < 0) + goto out_free; + fds_sent = true; if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) { skb->ip_summed = CHECKSUM_UNNECESSARY; err = skb_splice_from_iter(skb, &msg->msg_iter, size, sk->sk_allocation); - if (err < 0) { - kfree_skb(skb); - goto out_err; - } + if (err < 0) + goto out_free; + size = err; refcount_add(size, &sk->sk_wmem_alloc); } else { @@ -2326,17 +2329,15 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, skb->data_len = data_len; skb->len = size; err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size); - if (err) { - kfree_skb(skb); - goto out_err; - } + if (err) + goto out_free; } unix_state_lock(other); if (sock_flag(other, SOCK_DEAD) || (other->sk_shutdown & RCV_SHUTDOWN)) - goto pipe_err_free; + goto out_pipe; maybe_add_creds(skb, sock, other); scm_stat_add(other, skb); @@ -2359,13 +2360,13 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, return sent; -pipe_err_free: +out_pipe: unix_state_unlock(other); - kfree_skb(skb); -pipe_err: - if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) + if (!sent && !(msg->msg_flags & MSG_NOSIGNAL)) send_sig(SIGPIPE, current, 0); err = -EPIPE; +out_free: + kfree_skb(skb); out_err: scm_destroy(&scm); return sent ? : err; |