aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix
diff options
context:
space:
mode:
authorRainer Weikusat <rweikusat@mobileactivedefense.com>2016-02-08 13:47:19 -0500
committerDavid S. Miller <davem@davemloft.net>2016-02-16 12:48:04 -0500
commit1b92ee3d03af6643df395300ba7748f19ecdb0c5 (patch)
tree174da5394bc86b1f6a66a69ce9da19a688dae40a /net/unix
parentdb92ea5d4df00271b57d79c2d03dae5a5d60fcc1 (diff)
af_unix: Don't set err in unix_stream_read_generic unless there was an error
The present unix_stream_read_generic contains various code sequences of the form err = -EDISASTER; if (<test>) goto out; This has the unfortunate side effect of possibly causing the error code to bleed through to the final out: return copied ? : err; and then to be wrongly returned if no data was copied because the caller didn't supply a data buffer, as demonstrated by the program available at http://pad.lv/1540731 Change it such that err is only set if an error condition was detected. Fixes: 3822b5c2fc62 ("af_unix: Revert 'lock_interruptible' in stream receive code") Reported-by: Joseph Salisbury <joseph.salisbury@canonical.com> Signed-off-by: Rainer Weikusat <rweikusat@mobileactivedefense.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 29be035f9c65..df923caa8389 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2277,13 +2277,15 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
2277 size_t size = state->size; 2277 size_t size = state->size;
2278 unsigned int last_len; 2278 unsigned int last_len;
2279 2279
2280 err = -EINVAL; 2280 if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
2281 if (sk->sk_state != TCP_ESTABLISHED) 2281 err = -EINVAL;
2282 goto out; 2282 goto out;
2283 }
2283 2284
2284 err = -EOPNOTSUPP; 2285 if (unlikely(flags & MSG_OOB)) {
2285 if (flags & MSG_OOB) 2286 err = -EOPNOTSUPP;
2286 goto out; 2287 goto out;
2288 }
2287 2289
2288 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); 2290 target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
2289 timeo = sock_rcvtimeo(sk, noblock); 2291 timeo = sock_rcvtimeo(sk, noblock);
@@ -2329,9 +2331,11 @@ again:
2329 goto unlock; 2331 goto unlock;
2330 2332
2331 unix_state_unlock(sk); 2333 unix_state_unlock(sk);
2332 err = -EAGAIN; 2334 if (!timeo) {
2333 if (!timeo) 2335 err = -EAGAIN;
2334 break; 2336 break;
2337 }
2338
2335 mutex_unlock(&u->readlock); 2339 mutex_unlock(&u->readlock);
2336 2340
2337 timeo = unix_stream_data_wait(sk, timeo, last, 2341 timeo = unix_stream_data_wait(sk, timeo, last,