]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tcp: fix MSG_PEEK race check
authorIlpo Jarvinen <ilpo.jarvinen@helsinki.fi>
Sun, 10 May 2009 20:32:34 +0000 (20:32 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 15 Jun 2009 16:39:50 +0000 (09:39 -0700)
[ Upstream commit 775273131810caa41dfc7f9e552ea5d8508caf40 ]

Commit 518a09ef11 (tcp: Fix recvmsg MSG_PEEK influence of
blocking behavior) lets the loop run longer than the race check
did previously expect, so we need to be more careful with this
check and consider the work we have been doing.

I tried my best to deal with urg hole madness too which happens
here:
if (!sock_flag(sk, SOCK_URGINLINE)) {
++*seq;
...
by using additional offset by one but I certainly have very
little interest in testing that part.

Signed-off-by: Ilpo Jarvinen <ilpo.jarvinen@helsinki.fi>
Tested-by: Frans Pop <elendil@planet.nl>
Tested-by: Ian Zimmermann <itz@buug.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/ipv4/tcp.c

index 76b148bcb0dcb9ffcb333aa2b3ab3a2ed68fad33..b16dc847637b598e683525b867e3ff87f6ab0abd 100644 (file)
@@ -1286,6 +1286,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct task_struct *user_recv = NULL;
        int copied_early = 0;
        struct sk_buff *skb;
+       u32 urg_hole = 0;
 
        lock_sock(sk);
 
@@ -1497,7 +1498,8 @@ do_prequeue:
                                }
                        }
                }
-               if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {
+               if ((flags & MSG_PEEK) &&
+                   (peek_seq - copied - urg_hole != tp->copied_seq)) {
                        if (net_ratelimit())
                                printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n",
                                       current->comm, task_pid_nr(current));
@@ -1518,6 +1520,7 @@ do_prequeue:
                                if (!urg_offset) {
                                        if (!sock_flag(sk, SOCK_URGINLINE)) {
                                                ++*seq;
+                                               urg_hole++;
                                                offset++;
                                                used--;
                                                if (!used)