diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2016-05-18 20:42:13 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-05-23 16:51:10 -0400 |
| commit | c685293aa379b9d17e44fcc2f96a402b7648e838 (patch) | |
| tree | 7c20c6c980b5df0c3d003eac0f13a0f087d6ecbb /net/atm | |
| parent | bbf178e0a0a323d896611905718db112b1ab1807 (diff) | |
net/atm: sk_err_soft must be positive
The sk_err and sk_err_soft fields are positive errno values and
userspace applications rely on this when using getsockopt(SO_ERROR).
ATM code places an -errno into sk_err_soft in sigd_send() and returns it
from svc_addparty()/svc_dropparty().
Although I am not familiar with ATM code I came to this conclusion
because:
1. sigd_send() msg->type cases as_okay and as_error both have:
sk->sk_err = -msg->reply;
while the as_addparty and as_dropparty cases have:
sk->sk_err_soft = msg->reply;
This is the source of the inconsistency.
2. svc_addparty() returns an -errno and assumes sk_err_soft is also an
-errno:
if (flags & O_NONBLOCK) {
error = -EINPROGRESS;
goto out;
}
...
error = xchg(&sk->sk_err_soft, 0);
out:
release_sock(sk);
return error;
This shows that sk_err_soft is indeed being treated as an -errno.
This patch ensures that sk_err_soft is always a positive errno.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm')
| -rw-r--r-- | net/atm/signaling.c | 2 | ||||
| -rw-r--r-- | net/atm/svc.c | 4 |
2 files changed, 3 insertions, 3 deletions
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 4fd6af47383a..adb6e3d21b1e 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c | |||
| @@ -124,7 +124,7 @@ as_indicate_complete: | |||
| 124 | break; | 124 | break; |
| 125 | case as_addparty: | 125 | case as_addparty: |
| 126 | case as_dropparty: | 126 | case as_dropparty: |
| 127 | sk->sk_err_soft = msg->reply; | 127 | sk->sk_err_soft = -msg->reply; |
| 128 | /* < 0 failure, otherwise ep_ref */ | 128 | /* < 0 failure, otherwise ep_ref */ |
| 129 | clear_bit(ATM_VF_WAITING, &vcc->flags); | 129 | clear_bit(ATM_VF_WAITING, &vcc->flags); |
| 130 | break; | 130 | break; |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 3fa0a9ee98d1..878563a8354d 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
| @@ -546,7 +546,7 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, | |||
| 546 | schedule(); | 546 | schedule(); |
| 547 | } | 547 | } |
| 548 | finish_wait(sk_sleep(sk), &wait); | 548 | finish_wait(sk_sleep(sk), &wait); |
| 549 | error = xchg(&sk->sk_err_soft, 0); | 549 | error = -xchg(&sk->sk_err_soft, 0); |
| 550 | out: | 550 | out: |
| 551 | release_sock(sk); | 551 | release_sock(sk); |
| 552 | return error; | 552 | return error; |
| @@ -573,7 +573,7 @@ static int svc_dropparty(struct socket *sock, int ep_ref) | |||
| 573 | error = -EUNATCH; | 573 | error = -EUNATCH; |
| 574 | goto out; | 574 | goto out; |
| 575 | } | 575 | } |
| 576 | error = xchg(&sk->sk_err_soft, 0); | 576 | error = -xchg(&sk->sk_err_soft, 0); |
| 577 | out: | 577 | out: |
| 578 | release_sock(sk); | 578 | release_sock(sk); |
| 579 | return error; | 579 | return error; |
