From c3bba87a7ab57e636a8c96ddd36fdedfefe4848c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 13 Jul 2015 20:20:50 +0100 Subject: [PATCH] greybus: loopback: truncate maximum loop data to link size Get maximum payload by way of gb_operation_get_payload_size_max() and truncate any requested loopback size greater than this value. RX of data from firmware over the specified size will not be accepted. Signed-off-by: Bryan O'Donoghue Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/loopback.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 678690fbbc93..f490648648ce 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -34,6 +34,7 @@ struct gb_loopback { int type; u32 size; + u32 size_max; int ms_wait; struct gb_loopback_stats latency; @@ -46,7 +47,6 @@ struct gb_loopback { }; #define GB_LOOPBACK_MS_WAIT_MAX 1000 -#define GB_LOOPBACK_SIZE_MAX SZ_4K /* Define get_version() routine */ define_get_version(gb_loopback, LOOPBACK); @@ -122,8 +122,8 @@ static void gb_loopback_check_attr(struct gb_loopback *gb) } if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb->size > GB_LOOPBACK_SIZE_MAX) - gb->size = GB_LOOPBACK_SIZE_MAX; + if (gb->size > gb->size_max) + gb->size = gb->size_max; gb->error = 0; gb_loopback_reset_stats(gb); } @@ -182,6 +182,7 @@ static int gb_loopback_sink(struct gb_loopback *gb, do_gettimeofday(&ts); retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK, request, len + sizeof(*request), NULL, 0); + do_gettimeofday(&te); elapsed_nsecs = timeval_to_ns(&te) - timeval_to_ns(&ts); *tping = ns_to_timeval(elapsed_nsecs); @@ -250,6 +251,7 @@ static int gb_loopback_ping(struct gb_loopback *gb, struct timeval *tping) static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) { struct gb_connection *connection = operation->connection; + struct gb_loopback *gb = connection->private; struct gb_loopback_transfer_request *request; struct gb_loopback_transfer_response *response; u32 len; @@ -273,6 +275,13 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } request = operation->request->payload; len = le32_to_cpu(request->len); + if (len > gb->size_max) { + dev_err(&connection->dev, + "transfer request too large (%zu > %zu)\n", + len, gb->size_max); + return -EINVAL; + } + if (len) { if (!gb_operation_response_alloc(operation, len)) { dev_err(&connection->dev, @@ -416,6 +425,14 @@ static int gb_loopback_connection_init(struct gb_connection *connection) if (retval) goto out_get_ver; + /* Calculate maximum payload */ + gb->size_max = gb_operation_get_payload_size_max(connection); + if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { + retval = -EINVAL; + goto out_get_ver; + } + gb->size_max -= sizeof(struct gb_loopback_transfer_request); + gb_loopback_reset_stats(gb); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { -- 2.11.0