diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2451aeb5ac23..7a0f0b27bf1f 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1081,8 +1081,7 @@ out_err: | |||
1081 | * this, no blocking and very strange errors 8) | 1081 | * this, no blocking and very strange errors 8) |
1082 | */ | 1082 | */ |
1083 | 1083 | ||
1084 | static int tcp_recv_urg(struct sock *sk, long timeo, | 1084 | static int tcp_recv_urg(struct sock *sk, struct msghdr *msg, int len, int flags) |
1085 | struct msghdr *msg, int len, int flags) | ||
1086 | { | 1085 | { |
1087 | struct tcp_sock *tp = tcp_sk(sk); | 1086 | struct tcp_sock *tp = tcp_sk(sk); |
1088 | 1087 | ||
@@ -1322,6 +1321,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1322 | struct task_struct *user_recv = NULL; | 1321 | struct task_struct *user_recv = NULL; |
1323 | int copied_early = 0; | 1322 | int copied_early = 0; |
1324 | struct sk_buff *skb; | 1323 | struct sk_buff *skb; |
1324 | u32 urg_hole = 0; | ||
1325 | 1325 | ||
1326 | lock_sock(sk); | 1326 | lock_sock(sk); |
1327 | 1327 | ||
@@ -1533,7 +1533,8 @@ do_prequeue: | |||
1533 | } | 1533 | } |
1534 | } | 1534 | } |
1535 | } | 1535 | } |
1536 | if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) { | 1536 | if ((flags & MSG_PEEK) && |
1537 | (peek_seq - copied - urg_hole != tp->copied_seq)) { | ||
1537 | if (net_ratelimit()) | 1538 | if (net_ratelimit()) |
1538 | printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n", | 1539 | printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n", |
1539 | current->comm, task_pid_nr(current)); | 1540 | current->comm, task_pid_nr(current)); |
@@ -1554,6 +1555,7 @@ do_prequeue: | |||
1554 | if (!urg_offset) { | 1555 | if (!urg_offset) { |
1555 | if (!sock_flag(sk, SOCK_URGINLINE)) { | 1556 | if (!sock_flag(sk, SOCK_URGINLINE)) { |
1556 | ++*seq; | 1557 | ++*seq; |
1558 | urg_hole++; | ||
1557 | offset++; | 1559 | offset++; |
1558 | used--; | 1560 | used--; |
1559 | if (!used) | 1561 | if (!used) |
@@ -1697,7 +1699,7 @@ out: | |||
1697 | return err; | 1699 | return err; |
1698 | 1700 | ||
1699 | recv_urg: | 1701 | recv_urg: |
1700 | err = tcp_recv_urg(sk, timeo, msg, len, flags); | 1702 | err = tcp_recv_urg(sk, msg, len, flags); |
1701 | goto out; | 1703 | goto out; |
1702 | } | 1704 | } |
1703 | 1705 | ||
@@ -2512,6 +2514,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2512 | struct sk_buff *p; | 2514 | struct sk_buff *p; |
2513 | struct tcphdr *th; | 2515 | struct tcphdr *th; |
2514 | struct tcphdr *th2; | 2516 | struct tcphdr *th2; |
2517 | unsigned int len; | ||
2515 | unsigned int thlen; | 2518 | unsigned int thlen; |
2516 | unsigned int flags; | 2519 | unsigned int flags; |
2517 | unsigned int mss = 1; | 2520 | unsigned int mss = 1; |
@@ -2532,6 +2535,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2532 | 2535 | ||
2533 | skb_gro_pull(skb, thlen); | 2536 | skb_gro_pull(skb, thlen); |
2534 | 2537 | ||
2538 | len = skb_gro_len(skb); | ||
2535 | flags = tcp_flag_word(th); | 2539 | flags = tcp_flag_word(th); |
2536 | 2540 | ||
2537 | for (; (p = *head); head = &p->next) { | 2541 | for (; (p = *head); head = &p->next) { |
@@ -2562,7 +2566,7 @@ found: | |||
2562 | 2566 | ||
2563 | mss = skb_shinfo(p)->gso_size; | 2567 | mss = skb_shinfo(p)->gso_size; |
2564 | 2568 | ||
2565 | flush |= (skb_gro_len(skb) > mss) | !skb_gro_len(skb); | 2569 | flush |= (len > mss) | !len; |
2566 | flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); | 2570 | flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); |
2567 | 2571 | ||
2568 | if (flush || skb_gro_receive(head, skb)) { | 2572 | if (flush || skb_gro_receive(head, skb)) { |
@@ -2575,7 +2579,7 @@ found: | |||
2575 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); | 2579 | tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); |
2576 | 2580 | ||
2577 | out_check_final: | 2581 | out_check_final: |
2578 | flush = skb_gro_len(skb) < mss; | 2582 | flush = len < mss; |
2579 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2583 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | |
2580 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2584 | TCP_FLAG_SYN | TCP_FLAG_FIN); |
2581 | 2585 | ||