]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/rds/rdma.c
net: fix rds_iovec page count overflow
[karo-tx-linux.git] / net / rds / rdma.c
index eaeeb91e11196a07405ee9cbfc417c7da3793ea3..f7d8c08bd6b2d97d5f74b9345c2a9054c8dc23a7 100644 (file)
@@ -150,12 +150,9 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
 {
        int ret;
 
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(current, current->mm, user_addr,
-                            nr_pages, write, 0, pages, NULL);
-       up_read(&current->mm->mmap_sem);
+       ret = get_user_pages_fast(user_addr, nr_pages, write, pages);
 
-       if (0 <= ret && (unsigned) ret < nr_pages) {
+       if (ret >= 0 && ret < nr_pages) {
                while (ret--)
                        put_page(pages[ret]);
                ret = -EFAULT;
@@ -450,7 +447,7 @@ static struct rds_rdma_op *rds_rdma_prepare(struct rds_sock *rs,
                goto out;
        }
 
-       if (args->nr_local > (u64)UINT_MAX) {
+       if (args->nr_local > UIO_MAXIOV) {
                ret = -EMSGSIZE;
                goto out;
        }
@@ -476,6 +473,14 @@ static struct rds_rdma_op *rds_rdma_prepare(struct rds_sock *rs,
 
                max_pages = max(nr, max_pages);
                nr_pages += nr;
+
+               /*
+                * nr_pages for one entry is limited to (UINT_MAX>>PAGE_SHIFT)+1,
+                * so tot_pages cannot overflow without first going negative.
+                */
+               if ((int)nr_pages < 0)
+                       ret = -EINVAL;
+                       goto out;
        }
 
        pages = kcalloc(max_pages, sizeof(struct page *), GFP_KERNEL);