[PATCH Hardy CVE-2012-2136] net: sock: validate data_len before allocating skb in sock_alloc_send_pskb()
Colin Ian King
colin.king at canonical.com
Mon Sep 10 08:32:17 UTC 2012
On 07/09/12 19:02, Tim Gardner wrote:
> From: Jason Wang <jasowang at redhat.com>
>
> CVE-2012-2136
>
> BugLink: http://bugs.launchpad.net/bugs/1006622
>
> 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 at redhat.com>
> Signed-off-by: David S. Miller <davem at davemloft.net>
> (cherry picked from commit cc9b17ad29ecaa20bfe426a8d4dbfb94b13ff1cc)
>
Minor quibble, this is also a back-port for the openvz version of sock.c
rather than a clean cherry-pick.
> Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
> ---
> debian/binary-custom.d/openvz/src/net/core/sock.c | 5 +++++
> debian/binary-custom.d/xen/src/net/core/sock.c | 7 +++++--
> net/core/sock.c | 7 +++++--
> 3 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/debian/binary-custom.d/openvz/src/net/core/sock.c b/debian/binary-custom.d/openvz/src/net/core/sock.c
> index b66126b..46f0afc 100644
> --- a/debian/binary-custom.d/openvz/src/net/core/sock.c
> +++ b/debian/binary-custom.d/openvz/src/net/core/sock.c
> @@ -1267,6 +1267,11 @@ struct sk_buff *sock_alloc_send_skb2(struct sock *sk, unsigned long size,
> gfp_t gfp_mask;
> long timeo;
> int err;
> + int npages = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> +
> + err = -EMSGSIZE;
> + if (npages > MAX_SKB_FRAGS)
> + goto failure;
>
> gfp_mask = sk->sk_allocation;
> if (gfp_mask & __GFP_WAIT)
> diff --git a/debian/binary-custom.d/xen/src/net/core/sock.c b/debian/binary-custom.d/xen/src/net/core/sock.c
> index b0e5208..a39b6aa 100644
> --- a/debian/binary-custom.d/xen/src/net/core/sock.c
> +++ b/debian/binary-custom.d/xen/src/net/core/sock.c
> @@ -1233,6 +1233,11 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
> gfp_t gfp_mask;
> long timeo;
> int err;
> + int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> +
> + err = -EMSGSIZE;
> + if (npages > MAX_SKB_FRAGS)
> + goto failure;
>
> gfp_mask = sk->sk_allocation;
> if (gfp_mask & __GFP_WAIT)
> @@ -1251,14 +1256,12 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
> if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
> skb = alloc_skb(header_len, gfp_mask);
> if (skb) {
> - int npages;
> int i;
>
> /* No pages, we're done... */
> if (!data_len)
> break;
>
> - npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> skb->truesize += data_len;
> skb_shinfo(skb)->nr_frags = npages;
> for (i = 0; i < npages; i++) {
> diff --git a/net/core/sock.c b/net/core/sock.c
> index b0e5208..a39b6aa 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1233,6 +1233,11 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
> gfp_t gfp_mask;
> long timeo;
> int err;
> + int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> +
> + err = -EMSGSIZE;
> + if (npages > MAX_SKB_FRAGS)
> + goto failure;
>
> gfp_mask = sk->sk_allocation;
> if (gfp_mask & __GFP_WAIT)
> @@ -1251,14 +1256,12 @@ static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
> if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
> skb = alloc_skb(header_len, gfp_mask);
> if (skb) {
> - int npages;
> int i;
>
> /* No pages, we're done... */
> if (!data_len)
> break;
>
> - npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> skb->truesize += data_len;
> skb_shinfo(skb)->nr_frags = npages;
> for (i = 0; i < npages; i++) {
>
Looks OK to me.
Acked-by: Colin Ian King <colin.king at canonical.com>
More information about the kernel-team
mailing list