All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Ian Abbott <abbotti@mev.co.uk>
Cc: linux-spi <linux-spi@vger.kernel.org>,
	Mark Brown <broonie@kernel.org>,
	Dan Carpenter <dan.carpenter@oracle.com>,
	lkml <linux-kernel@vger.kernel.org>,
	"3.8+" <stable@vger.kernel.org>
Subject: Re: [PATCH] spi: spidev: fix possible arithmetic overflow for multi-transfer message
Date: Mon, 23 May 2016 10:04:34 -0700	[thread overview]
Message-ID: <20160523170434.GD20465@dtor-ws> (raw)
In-Reply-To: <5742D973.80104@mev.co.uk>

On Mon, May 23, 2016 at 11:20:35AM +0100, Ian Abbott wrote:
> On 21/05/16 17:50, Dmitry Torokhov wrote:
> >On Mon, Mar 23, 2015 at 10:50 AM, Ian Abbott <abbotti@mev.co.uk> wrote:
> >>`spidev_message()` sums the lengths of the individual SPI transfers to
> >>determine the overall SPI message length.  It restricts the total
> >>length, returning an error if too long, but it does not check for
> >>arithmetic overflow.  For example, if the SPI message consisted of two
> >>transfers and the first has a length of 10 and the second has a length
> >>of (__u32)(-1), the total length would be seen as 9, even though the
> >>second transfer is actually very long.  If the second transfer specifies
> >>a null `rx_buf` and a non-null `tx_buf`, the `copy_from_user()` could
> >>overrun the spidev's pre-allocated tx buffer before it reaches an
> >>invalid user memory address.  Fix it by checking that neither the total
> >>nor the individual transfer lengths exceed the maximum allowed value.
> >>
> >>Thanks to Dan Carpenter for reporting the potential integer overflow.
> >>
> >>Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
> >>Cc: <stable@vger.kernel.org> # 4.0+
> >>---
> >>This could be backported to kernels prior to 4.0, but the total and
> >>individual lengths would need to be checked against `bufsiz` instead of
> >>`INT_MAX`.
> >>---
> >>  drivers/spi/spidev.c | 5 +++--
> >>  1 file changed, 3 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
> >>index bb6b3ab..23ad978 100644
> >>--- a/drivers/spi/spidev.c
> >>+++ b/drivers/spi/spidev.c
> >>@@ -249,9 +249,10 @@ static int spidev_message(struct spidev_data *spidev,
> >>                 total += k_tmp->len;
> >>                 /* Since the function returns the total length of transfers
> >>                  * on success, restrict the total to positive int values to
> >>-                * avoid the return value looking like an error.
> >>+                * avoid the return value looking like an error.  Also check
> >>+                * each transfer length to avoid arithmetic overflow.
> >>                  */
> >>-               if (total > INT_MAX) {
> >>+               if (total > INT_MAX || k_tmp->len > INT_MAX) {
> >
> >What if total is INT_MAX - 2 and k_tmp->len is 3? What about total is
> >INT_MAX and k_tmp->len is INT_MAX as well? I think the proper check
> 
> In your questions, I assume you are referring to the values of
> 'total' before the addition.  I'll call the values 'old_total' and

Sorry, yes, for some reason I was thinking we are checking before
performing addition. Ignore me.

> 'new_total' (with the same type as 'total', i.e. 'unsigned int').
> Note that total (and old_total, and new_total) and 'k_tmp->len' have
> range UINT_MAX, or 2*INT_MAX+1.
> 
> Before the addition, we know that old_total <= INT_MAX (otherwise
> the loop would have errored out already), but k_tmp->len can have
> any value from 0 to UINT_MAX.  After the addition, new_total can
> have any value from 0 to UINT_MAX, and might be less than old_total.
> new_total can only be less than old_total if old_total + k_tmp->len
> > UINT_MAX, and here I am referring to proper addition, not addition
> modulo UINT_MAX+1.  Rearranging, new_total will be less than
> old_total if k_tmp->len > UINT_MAX - old_total.  Since the maximum
> value of old_total is INT_MAX, the lowest possible value of
> k_tmp->len that could cause new_total to be less than old_total is
> UINT_MAX - INT_MAX, or INT_MAX+1.  That is what the second part of
> the 'if' test is detecting.
> 
> >should be:
> >
> >if (total < k_tmp->len || total > INT_MAX) {
> >         ...
> >}
> >
> 
> That also works.
> 
> -- 
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbotti@mev.co.uk> )=-
> -=(                          Web: http://www.mev.co.uk/  )=-

-- 
Dmitry

  reply	other threads:[~2016-05-23 17:04 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-23 17:50 [PATCH] spi: spidev: fix possible arithmetic overflow for multi-transfer message Ian Abbott
2015-03-23 17:50 ` Ian Abbott
2015-03-23 18:50 ` Mark Brown
     [not found]   ` <20150323185042.GL14954-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2015-03-23 19:29     ` Ian Abbott
2015-03-23 19:29       ` Ian Abbott
     [not found]       ` <5510698B.3040000-GUHe90Wt2aFaa/9Udqfwiw@public.gmane.org>
2015-03-23 21:01         ` Mark Brown
2015-03-23 21:01           ` Mark Brown
     [not found] ` <1427133027-8134-1-git-send-email-abbotti-GUHe90Wt2aFaa/9Udqfwiw@public.gmane.org>
2016-05-21 16:50   ` Dmitry Torokhov
2016-05-21 16:50     ` Dmitry Torokhov
2016-05-23 10:20     ` Ian Abbott
2016-05-23 17:04       ` Dmitry Torokhov [this message]
2016-05-23 11:15     ` Mark Brown
2016-05-23 11:23       ` Ian Abbott

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160523170434.GD20465@dtor-ws \
    --to=dmitry.torokhov@gmail.com \
    --cc=abbotti@mev.co.uk \
    --cc=broonie@kernel.org \
    --cc=dan.carpenter@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.