From: Al Viro <viro@zeniv.linux.org.uk>
To: Rainer Weikusat <rweikusat@mobileactivedefense.com>,
Jason Baron <jbaron@akamai.com>
Cc: netdev@vger.kernel.org
Subject: Re: [RFC] nasty corner case in unix_dgram_sendmsg()
Date: Tue, 26 Feb 2019 06:38:04 +0000 [thread overview]
Message-ID: <20190226063804.GI2217@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20190226062817.GA17962@ZenIV.linux.org.uk>
On Tue, Feb 26, 2019 at 06:28:17AM +0000, Al Viro wrote:
> 2) the logics in sendmsg is very odd:
> * if we'd detected n:1 send *and* found that we need to
> wait, do so (not using the peer_wake - other's peer_wait is not
> going away). No questions there.
> * if we'd detected n:1 send *and* found that we need to
> wait, but don't have any remaining timeout, we lock both ends
> and check if unix_peer(sk) is (now) not equal to other, either
> because it never had or because we'd been hit by connect(2) while
> we'd been doing the locking. In that case we fail with -EAGAIN.
> Fair enough, but
> * if after relocking we see that unix_peer(sk) now
> is equal to other, we arrange for wakeup forwarding from other's
> peer_wait *and* if that has (likely) succeeded we fail with -EAGAIN.
> Huh? What's the point? The only thing that depends upon that
> wakeup forwarding is poll, and _that_ will set the forwarding up
> on its own.
> * if we'd failed (either because other is dead now or
> because its queue is not full), we go back to restart_locked.
> If it's dead, we'll sod off with ECONNREFUSED, if it's not
> full anymore, we'll send the damn thing.
>
> All of that comes at the cost of considerable headache in
> unix_dgram_sendmsg() - flag-conditional locking, etc. Why do
> we bother? What's wrong with simple "n:1 case detected, queue
> full, no timeout left, return -EAGAIN and be done with that"?
>
> IDGI... Am I missing something subtle going on here?
>
> I understand what peer_wake is for, and the poll side of things
> is fine; it's sendmsg one that looks weird. What's going on
> there?
What I have in mind is something like this (for that part of the
issues):
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 74d1eed7cbd4..85d72ea79924 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1635,7 +1635,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
long timeo;
struct scm_cookie scm;
int data_len = 0;
- int sk_locked;
wait_for_unix_gc();
err = scm_send(sock, msg, &scm, false);
@@ -1713,9 +1712,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out_free;
}
- sk_locked = 0;
unix_state_lock(other);
-restart_locked:
+
err = -EPERM;
if (!unix_may_send(sk, other))
goto out_unlock;
@@ -1728,8 +1726,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
unix_state_unlock(other);
sock_put(other);
- if (!sk_locked)
- unix_state_lock(sk);
+ unix_state_lock(sk);
err = 0;
if (unix_peer(sk) == other) {
@@ -1767,36 +1764,19 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
*/
if (other != sk &&
unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
- if (timeo) {
- timeo = unix_wait_for_peer(other, timeo);
-
- err = sock_intr_errno(timeo);
- if (signal_pending(current))
- goto out_free;
-
- goto restart;
- }
-
- if (!sk_locked) {
- unix_state_unlock(other);
- unix_state_double_lock(sk, other);
- }
-
- if (unix_peer(sk) != other ||
- unix_dgram_peer_wake_me(sk, other)) {
+ if (!timeo) {
err = -EAGAIN;
- sk_locked = 1;
goto out_unlock;
}
- if (!sk_locked) {
- sk_locked = 1;
- goto restart_locked;
- }
- }
+ timeo = unix_wait_for_peer(other, timeo);
- if (unlikely(sk_locked))
- unix_state_unlock(sk);
+ err = sock_intr_errno(timeo);
+ if (signal_pending(current))
+ goto out_free;
+
+ goto restart;
+ }
if (sock_flag(other, SOCK_RCVTSTAMP))
__net_timestamp(skb);
@@ -1809,8 +1789,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
return len;
out_unlock:
- if (sk_locked)
- unix_state_unlock(sk);
unix_state_unlock(other);
out_free:
kfree_skb(skb);
next prev parent reply other threads:[~2019-02-26 6:38 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-25 3:51 [RFC] nasty corner case in unix_dgram_sendmsg() Al Viro
2019-02-26 6:28 ` Al Viro
2019-02-26 6:38 ` Al Viro [this message]
2019-02-26 15:31 ` Rainer Weikusat
2019-02-26 19:03 ` Al Viro
2019-02-26 20:35 ` Jason Baron
2019-02-26 23:59 ` Al Viro
2019-02-27 16:45 ` Jason Baron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190226063804.GI2217@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=jbaron@akamai.com \
--cc=netdev@vger.kernel.org \
--cc=rweikusat@mobileactivedefense.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).