netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Stern <stern@rowland.harvard.edu>
To: Hans Petter Selasky <hps@selasky.org>
Cc: "Bjørn Mork" <bjorn@mork.no>, "Oliver Neukum" <oneukum@suse.com>,
	linux-usb@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [RFC] CDC-NCM: avoid overflow in sanity checking
Date: Thu, 10 Feb 2022 20:54:19 -0500	[thread overview]
Message-ID: <YgXByzVayvl3KJTS@rowland.harvard.edu> (raw)
In-Reply-To: <3624a7e7-3568-bee1-77e5-67d5b7d48aa6@selasky.org>

On Thu, Feb 10, 2022 at 11:50:20PM +0100, Hans Petter Selasky wrote:
> On 2/10/22 18:27, Bjørn Mork wrote:
> > Hans Petter Selasky <hps@selasky.org> writes:
> > 
> > > "int" variables are 32-bit, so 0xFFF0 won't overflow.
> > > 
> > > The initial driver code written by me did only support 16-bit lengths
> > > and offset. Then integer overflow is not possible.
> > > 
> > > It looks like somebody else introduced this integer overflow :-(
> > > 
> > > commit 0fa81b304a7973a499f844176ca031109487dd31
> > > Author: Alexander Bersenev <bay@hackerdom.ru>
> > > Date:   Fri Mar 6 01:33:16 2020 +0500
> > > 
> > >      cdc_ncm: Implement the 32-bit version of NCM Transfer Block
> > > 
> > >      The NCM specification defines two formats of transfer blocks: with
> > >      16-bit
> > >      fields (NTB-16) and with 32-bit fields (NTB-32). Currently only
> > >      NTB-16 is
> > >      implemented.
> > > 
> > > ....
> > > 
> > > With NCM 32, both "len" and "offset" must be checked, because these
> > > are now 32-bit and stored into regular "int".
> > > 
> > > The fix you propose is not fully correct!
> > 
> > Yes, there is still an issue if len > skb_in->len since
> > (skb_in->len - len) then ends up as a very large unsigned int.
> > 
> > I must admit that I have some problems tweaking my mind around these
> > subtle unsigned overflow thingies.  Which is why I suggest just
> > simplifying the whole thing with an additional test for the 32bit case
> > (which never will be used for any sane device):
> > 
> > 		} else {
> > 			offset = le32_to_cpu(dpe.dpe32->dwDatagramIndex);
> > 			len = le32_to_cpu(dpe.dpe32->dwDatagramLength);
> >                          if (offset < 0 || len < 0)
> >                                  goto err_ndp;
> > 		}
> 
> Hi,
> 
> I think something like this would do the trick:
> 
> if (offset < 0 || offset > sbk_in->len ||
>     len < 0 || len > sbk_in->len)

Speaking as someone who is entirely unfamiliar with this code, a few
things seem clear.

First, since offset and len are initialized by converting 16- or 32-bit 
unsigned values from little-endian to cpu-endian, they should be 
unsigned themselves.

Second, once they are unsigned there is obviously no point in testing 
whether they are < 0.

Third, if you want to make sure that skb_in's buffer contains the entire 
interval from offset to offset + len, the proper tests are:

	if (offset <= skb_in->len && len <= skb_in->len - offset) ...

The first test demonstrates that the start of the interval is in range 
and the second test demonstrates that the end of the interval is in 
range.  Furthermore, success of the first test proves that the 
computation in the second test can't overflow to a negative value.

IMO, working with unsigned values is simpler than working with 
signed values.  But it does require some discipline to ensure that 
intermediate computations don't overflow or yield negative values.

Alan Stern

  reply	other threads:[~2022-02-11  2:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-10 15:54 [RFC] CDC-NCM: avoid overflow in sanity checking Oliver Neukum
2022-02-10 16:38 ` Hans Petter Selasky
2022-02-10 17:27   ` Bjørn Mork
2022-02-10 22:50     ` Hans Petter Selasky
2022-02-11  1:54       ` Alan Stern [this message]
2022-02-11  7:17         ` Bjørn Mork
2022-02-14 19:30           ` Oliver Neukum
2022-02-14 19:41             ` Bjørn Mork

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=YgXByzVayvl3KJTS@rowland.harvard.edu \
    --to=stern@rowland.harvard.edu \
    --cc=bjorn@mork.no \
    --cc=hps@selasky.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oneukum@suse.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).