fastrpc_get_buff_overlaps() builds end addresses from user ranges.

A wrapped end can understate the payload size.

It can also feed bad ranges into the invoke metadata.

Reject invoke buffers whose pointer plus length overflows.

Signed-off-by: Yousef Alhouseen <[email protected]>
---
 drivers/misc/fastrpc.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index f3a493845..ba4ade874 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
+#include <linux/overflow.h>
 #include <linux/platform_device.h>
 #include <linux/sort.h>
 #include <linux/of_platform.h>
@@ -607,14 +608,17 @@ static int olaps_cmp(const void *a, const void *b)
        return st == 0 ? ed : st;
 }
 
-static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx)
+static int fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx)
 {
        u64 max_end = 0;
        int i;
 
        for (i = 0; i < ctx->nbufs; ++i) {
                ctx->olaps[i].start = ctx->args[i].ptr;
-               ctx->olaps[i].end = ctx->olaps[i].start + ctx->args[i].length;
+               if (check_add_overflow(ctx->olaps[i].start,
+                                      ctx->args[i].length,
+                                      &ctx->olaps[i].end))
+                       return -EOVERFLOW;
                ctx->olaps[i].raix = i;
        }
 
@@ -641,6 +645,8 @@ static void fastrpc_get_buff_overlaps(struct 
fastrpc_invoke_ctx *ctx)
                        max_end = ctx->olaps[i].end;
                }
        }
+
+       return 0;
 }
 
 static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
@@ -675,7 +681,13 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
                        return ERR_PTR(-ENOMEM);
                }
                ctx->args = args;
-               fastrpc_get_buff_overlaps(ctx);
+               ret = fastrpc_get_buff_overlaps(ctx);
+               if (ret) {
+                       kfree(ctx->olaps);
+                       kfree(ctx->maps);
+                       kfree(ctx);
+                       return ERR_PTR(ret);
+               }
        }
 
        /* Released in fastrpc_context_put() */
-- 
2.54.0

Reply via email to