Patchwork [Karmic,CVE-2010-4175,01/01] rds: Integer overflow in RDS cmsg handling, CVE-2010-4175

login
register
mail settings
Submitter Brad Figg
Date Feb. 23, 2011, 4:55 p.m.
Message ID <1298480107-15119-1-git-send-email-brad.figg@canonical.com>
Download mbox | patch
Permalink /patch/84210/
State Accepted
Commit df663fa5d0ba5cbb5722a3b2e3b771fbcfc0cd9b
Headers show

Comments

Brad Figg - Feb. 23, 2011, 4:55 p.m.
From: Dan Rosenberg <drosenberg@vsecurity.com>

CVE-2010-4175

BugLink: http://bugs.launchpad.net/bugs/721455

In rds_cmsg_rdma_args(), the user-provided args->nr_local value is
restricted to less than UINT_MAX.  This seems to need a tighter upper
bound, since the calculation of total iov_size can overflow, resulting
in a small sock_kmalloc() allocation.  This would probably just result
in walking off the heap and crashing when calling rds_rdma_pages() with
a high count value.  If it somehow doesn't crash here, then memory
corruption could occur soon after.

Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

(backport of upstream commit 218854af84038d828a32f061858b1902ed2beec6)
Signed-off-by: Brad Figg <brad.figg@canonical.com>
---
 net/rds/rdma.c |   24 +++++++++++++++++++-----
 1 files changed, 19 insertions(+), 5 deletions(-)
Tim Gardner - Feb. 23, 2011, 5:45 p.m.
On 02/23/2011 09:55 AM, Brad Figg wrote:
> From: Dan Rosenberg<drosenberg@vsecurity.com>
>
> CVE-2010-4175
>
> BugLink: http://bugs.launchpad.net/bugs/721455
>
> In rds_cmsg_rdma_args(), the user-provided args->nr_local value is
> restricted to less than UINT_MAX.  This seems to need a tighter upper
> bound, since the calculation of total iov_size can overflow, resulting
> in a small sock_kmalloc() allocation.  This would probably just result
> in walking off the heap and crashing when calling rds_rdma_pages() with
> a high count value.  If it somehow doesn't crash here, then memory
> corruption could occur soon after.
>
> Signed-off-by: Dan Rosenberg<drosenberg@vsecurity.com>
> Signed-off-by: David S. Miller<davem@davemloft.net>
>
> (backport of upstream commit 218854af84038d828a32f061858b1902ed2beec6)
> Signed-off-by: Brad Figg<brad.figg@canonical.com>
> ---
>   net/rds/rdma.c |   24 +++++++++++++++++++-----
>   1 files changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/net/rds/rdma.c b/net/rds/rdma.c
> index aa3befb..fa2ab42 100644
> --- a/net/rds/rdma.c
> +++ b/net/rds/rdma.c
> @@ -616,18 +616,32 @@ out:
>   int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
>   			  struct cmsghdr *cmsg)
>   {
> +	struct rds_rdma_args *args;
>   	struct rds_rdma_op *op;
> +        int ret = 0;
>
>   	if (cmsg->cmsg_len<  CMSG_LEN(sizeof(struct rds_rdma_args))
> -	 || rm->m_rdma_op != NULL)
> -		return -EINVAL;
> +	 || rm->m_rdma_op != NULL) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	args = CMSG_DATA(cmsg);
> +
> +	if (args->nr_local>  UIO_MAXIOV) {
> +		ret = -EMSGSIZE;
> +		goto out;
> +	}
>
>   	op = rds_rdma_prepare(rs, CMSG_DATA(cmsg));
> -	if (IS_ERR(op))
> -		return PTR_ERR(op);
> +	if (IS_ERR(op)) {
> +		ret = PTR_ERR(op);
> +		goto out;
> +	}
>   	rds_stats_inc(s_send_rdma);
>   	rm->m_rdma_op = op;
> -	return 0;
> +out:
> +	return ret;
>   }
>
>   /*

Acked-by: Tim Gardner <tim.gardner@canonical.com>
John Johansen - Feb. 23, 2011, 8:17 p.m.
On 02/23/2011 08:55 AM, Brad Figg wrote:
> From: Dan Rosenberg <drosenberg@vsecurity.com>
> 
> CVE-2010-4175
> 
> BugLink: http://bugs.launchpad.net/bugs/721455
> 
> In rds_cmsg_rdma_args(), the user-provided args->nr_local value is
> restricted to less than UINT_MAX.  This seems to need a tighter upper
> bound, since the calculation of total iov_size can overflow, resulting
> in a small sock_kmalloc() allocation.  This would probably just result
> in walking off the heap and crashing when calling rds_rdma_pages() with
> a high count value.  If it somehow doesn't crash here, then memory
> corruption could occur soon after.
> 
> Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> 
> (backport of upstream commit 218854af84038d828a32f061858b1902ed2beec6)
> Signed-off-by: Brad Figg <brad.figg@canonical.com>
> ---
>  net/rds/rdma.c |   24 +++++++++++++++++++-----
>  1 files changed, 19 insertions(+), 5 deletions(-)
> 
> diff --git a/net/rds/rdma.c b/net/rds/rdma.c
> index aa3befb..fa2ab42 100644
> --- a/net/rds/rdma.c
> +++ b/net/rds/rdma.c
> @@ -616,18 +616,32 @@ out:
>  int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
>  			  struct cmsghdr *cmsg)
>  {
> +	struct rds_rdma_args *args;
>  	struct rds_rdma_op *op;
> +        int ret = 0;
>  
>  	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args))
> -	 || rm->m_rdma_op != NULL)
> -		return -EINVAL;
> +	 || rm->m_rdma_op != NULL) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	args = CMSG_DATA(cmsg);
> +
> +	if (args->nr_local > UIO_MAXIOV) {
> +		ret = -EMSGSIZE;
> +		goto out;
> +	}
>  
>  	op = rds_rdma_prepare(rs, CMSG_DATA(cmsg));
> -	if (IS_ERR(op))
> -		return PTR_ERR(op);
> +	if (IS_ERR(op)) {
> +		ret = PTR_ERR(op);
> +		goto out;
> +	}
>  	rds_stats_inc(s_send_rdma);
>  	rm->m_rdma_op = op;
> -	return 0;
> +out:
> +	return ret;
>  }
>  
>  /*
Acked-by: John Johansen <john.johansen@canonical.com>
Tim Gardner - Feb. 23, 2011, 9:41 p.m.
applied

Patch

diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index aa3befb..fa2ab42 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -616,18 +616,32 @@  out:
 int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
 			  struct cmsghdr *cmsg)
 {
+	struct rds_rdma_args *args;
 	struct rds_rdma_op *op;
+        int ret = 0;
 
 	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args))
-	 || rm->m_rdma_op != NULL)
-		return -EINVAL;
+	 || rm->m_rdma_op != NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	args = CMSG_DATA(cmsg);
+
+	if (args->nr_local > UIO_MAXIOV) {
+		ret = -EMSGSIZE;
+		goto out;
+	}
 
 	op = rds_rdma_prepare(rs, CMSG_DATA(cmsg));
-	if (IS_ERR(op))
-		return PTR_ERR(op);
+	if (IS_ERR(op)) {
+		ret = PTR_ERR(op);
+		goto out;
+	}
 	rds_stats_inc(s_send_rdma);
 	rm->m_rdma_op = op;
-	return 0;
+out:
+	return ret;
 }
 
 /*