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>
This commit is contained in:
parent
bbf178e0a0
commit
c685293aa3
|
@ -124,7 +124,7 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
break;
|
||||
case as_addparty:
|
||||
case as_dropparty:
|
||||
sk->sk_err_soft = msg->reply;
|
||||
sk->sk_err_soft = -msg->reply;
|
||||
/* < 0 failure, otherwise ep_ref */
|
||||
clear_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
break;
|
||||
|
|
|
@ -546,7 +546,7 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
|
|||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
error = xchg(&sk->sk_err_soft, 0);
|
||||
error = -xchg(&sk->sk_err_soft, 0);
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
|
@ -573,7 +573,7 @@ static int svc_dropparty(struct socket *sock, int ep_ref)
|
|||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
error = xchg(&sk->sk_err_soft, 0);
|
||||
error = -xchg(&sk->sk_err_soft, 0);
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
|
|
Loading…
Reference in New Issue
Block a user