aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2012-05-30 17:18:10 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 11:47:36 -0400
commit325b4161bab9ba01b345c4483bbb0e36cb571943 (patch)
treeb8584bb3b7cd29f3c82793ce68b1cc4cdb41d26c
parentd1877392b4dce5d4c74d329777980d2a3ccede99 (diff)
net: sock: validate data_len before allocating skb in sock_alloc_send_pskb()
[ Upstream commit cc9b17ad29ecaa20bfe426a8d4dbfb94b13ff1cc ] We need to validate the number of pages consumed by data_len, otherwise frags array could be overflowed by userspace. So this patch validate data_len and return -EMSGSIZE when data_len may occupies more frags than MAX_SKB_FRAGS. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/core/sock.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index aebb419519b..b4bb59a9245 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1501,6 +1501,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
1501 gfp_t gfp_mask; 1501 gfp_t gfp_mask;
1502 long timeo; 1502 long timeo;
1503 int err; 1503 int err;
1504 int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
1505
1506 err = -EMSGSIZE;
1507 if (npages > MAX_SKB_FRAGS)
1508 goto failure;
1504 1509
1505 gfp_mask = sk->sk_allocation; 1510 gfp_mask = sk->sk_allocation;
1506 if (gfp_mask & __GFP_WAIT) 1511 if (gfp_mask & __GFP_WAIT)
@@ -1519,14 +1524,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
1519 if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { 1524 if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
1520 skb = alloc_skb(header_len, gfp_mask); 1525 skb = alloc_skb(header_len, gfp_mask);
1521 if (skb) { 1526 if (skb) {
1522 int npages;
1523 int i; 1527 int i;
1524 1528
1525 /* No pages, we're done... */ 1529 /* No pages, we're done... */
1526 if (!data_len) 1530 if (!data_len)
1527 break; 1531 break;
1528 1532
1529 npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
1530 skb->truesize += data_len; 1533 skb->truesize += data_len;
1531 skb_shinfo(skb)->nr_frags = npages; 1534 skb_shinfo(skb)->nr_frags = npages;
1532 for (i = 0; i < npages; i++) { 1535 for (i = 0; i < npages; i++) {