diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e61f7cd65d08..5fdcb8d108d4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1182,13 +1182,13 @@ out: | |||
1182 | * @sk: socket | 1182 | * @sk: socket |
1183 | * | 1183 | * |
1184 | * Drops all bad checksum frames, until a valid one is found. | 1184 | * Drops all bad checksum frames, until a valid one is found. |
1185 | * Returns the length of found skb, or 0 if none is found. | 1185 | * Returns the length of found skb, or -1 if none is found. |
1186 | */ | 1186 | */ |
1187 | static unsigned int first_packet_length(struct sock *sk) | 1187 | static int first_packet_length(struct sock *sk) |
1188 | { | 1188 | { |
1189 | struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue; | 1189 | struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue; |
1190 | struct sk_buff *skb; | 1190 | struct sk_buff *skb; |
1191 | unsigned int res; | 1191 | int res; |
1192 | 1192 | ||
1193 | __skb_queue_head_init(&list_kill); | 1193 | __skb_queue_head_init(&list_kill); |
1194 | 1194 | ||
@@ -1203,7 +1203,7 @@ static unsigned int first_packet_length(struct sock *sk) | |||
1203 | __skb_unlink(skb, rcvq); | 1203 | __skb_unlink(skb, rcvq); |
1204 | __skb_queue_tail(&list_kill, skb); | 1204 | __skb_queue_tail(&list_kill, skb); |
1205 | } | 1205 | } |
1206 | res = skb ? skb->len : 0; | 1206 | res = skb ? skb->len : -1; |
1207 | spin_unlock_bh(&rcvq->lock); | 1207 | spin_unlock_bh(&rcvq->lock); |
1208 | 1208 | ||
1209 | if (!skb_queue_empty(&list_kill)) { | 1209 | if (!skb_queue_empty(&list_kill)) { |
@@ -1232,7 +1232,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1232 | 1232 | ||
1233 | case SIOCINQ: | 1233 | case SIOCINQ: |
1234 | { | 1234 | { |
1235 | unsigned int amount = first_packet_length(sk); | 1235 | int amount = max_t(int, 0, first_packet_length(sk)); |
1236 | 1236 | ||
1237 | return put_user(amount, (int __user *)arg); | 1237 | return put_user(amount, (int __user *)arg); |
1238 | } | 1238 | } |
@@ -2184,7 +2184,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
2184 | 2184 | ||
2185 | /* Check for false positives due to checksum errors */ | 2185 | /* Check for false positives due to checksum errors */ |
2186 | if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && | 2186 | if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && |
2187 | !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk)) | 2187 | !(sk->sk_shutdown & RCV_SHUTDOWN) && first_packet_length(sk) == -1) |
2188 | mask &= ~(POLLIN | POLLRDNORM); | 2188 | mask &= ~(POLLIN | POLLRDNORM); |
2189 | 2189 | ||
2190 | return mask; | 2190 | return mask; |
@@ -2216,7 +2216,6 @@ struct proto udp_prot = { | |||
2216 | .sysctl_wmem = &sysctl_udp_wmem_min, | 2216 | .sysctl_wmem = &sysctl_udp_wmem_min, |
2217 | .sysctl_rmem = &sysctl_udp_rmem_min, | 2217 | .sysctl_rmem = &sysctl_udp_rmem_min, |
2218 | .obj_size = sizeof(struct udp_sock), | 2218 | .obj_size = sizeof(struct udp_sock), |
2219 | .slab_flags = SLAB_DESTROY_BY_RCU, | ||
2220 | .h.udp_table = &udp_table, | 2219 | .h.udp_table = &udp_table, |
2221 | #ifdef CONFIG_COMPAT | 2220 | #ifdef CONFIG_COMPAT |
2222 | .compat_setsockopt = compat_udp_setsockopt, | 2221 | .compat_setsockopt = compat_udp_setsockopt, |