public inbox for linux-ext4@vger.kernel.org
 help / color / mirror / Atom feed
From: "PaX Team" <pageexec@freemail.hu>
To: Shawn <citypw@gmail.com>, "Theodore Ts'o" <tytso@mit.edu>
Cc: linux-ext4@vger.kernel.org,
	Brad Spengler <spender@grsecurity.net>,
	Emese Revfy <re.emese@gmail.com>
Subject: Re: PAX: size overflow detected in function ext4_llseek fs/ext4/file.c:670
Date: Fri, 12 May 2017 11:58:54 +0200	[thread overview]
Message-ID: <5915875E.15260.4679D7CA@pageexec.freemail.hu> (raw)
In-Reply-To: <20170512050234.ohjoofele5gugxab@thunk.org>

On 12 May 2017 at 1:02, Theodore Ts'o wrote:

[added Emese to CC and thus kept the whole mail for context even if
i'm responding to some parts of it only]

> On Fri, May 12, 2017 at 12:10:04PM +0800, Shawn wrote:
> > 
> > thanks for the reports, keep them coming . this is an interesting one,
> > here's the code (same at both lines in ext4_seek_hole and ext4_seek_data):
> > 
> > 670 »·······start = offset >> blkbits;
> > 
> > in types this is
> > 
> > u32 = long long >> int;
> > 
> > since the maximum value was exceeded it means that offset (long long,
> > 64 bits even on 32 bit archs) had a value that didn't fit u32 when right
> > shifted. based on some light code reading, blkbits is between 10-16 on
> > ext4 (EXT4_MIN_BLOCK_SIZE-EXT4_MAX_BLOCK_SIZE) so depending on what the
> > actual block size of the underlying filesystem was, offset must have been
> > bigger than 2^42-2^48 (4TB-256TB).
> 
> Yes, this is indeed an interesting one.  I actually suspect that
> offset was *negative*, and since start is a u32, this got translated
> into a large number.

Shawn, can you do the printk instrumentation i suggested to print out
the value of offset (and isize too while at it)?

thing is, IIRC the C standard makes right shifting a negative value
implementation defined (so excluding such values would be good for that
reason alone) and i think gcc simply executes it as an arithmetic shift,
i.e., the sign of the result is preserved and thus the size overflow
checks should have detected a minimum violation, not the maximum one.

to tell for sure what check triggered exactly, i'd like to ask Shawn
to execute

	make fs/ext4/file.o EXTRA_CFLAGS="-fdump-tree-all -fdump-ipa-all"

and send us (Emese in particular) all the resulting files (fs/ext4/file.*)

> It is indeed a bug in ext4, although what we should do is an
> interesting question, especially if I am correct that offset was in
> fact negative.  The man page states:
> 
>        SEEK_DATA
>               Adjust the file offset to the next location in the file
>               greater than or equal to offset containing data.  If
>               offset points to data, then the file offset is set to
>               offset.
> 
> (and SEEK_HOLE is similar).  The man page leaves unspecified what to
> do if offset is negative.  We could say that this is an invalid value,
> and return -EINVAL.  Or we could say that since the next location in
> the file greater to or equal to offset is obviously going to be a
> positive number we could simply set offset to zero if it is negative.
> e.g., should we add to the beginning of ext4_seek_data():
> 
>  if (offset < 0)
>   return -EINVAL;
> 
> or
> 
>  if (offset < 0)
>   offset = 0;
> 
> If offset really were a large number, it should have returned -ENXIO
> due to this check in those functions:
> 
>  isize = i_size_read(inode);
>  if (offset >= isize) {
>   inode_unlock(inode);
>   return -ENXIO;
>  }

is it possible that isize was actually big enough itself to allow a large
enough positive offset pass this test (we'll know for sure if Shawn can
get the data i asked about)? what i'm basically asking is how the blocksize
is tied to the maximum possible file size. say, can one create a >4TB file
with a blocksize of 1024 bytes, etc? by the look of it, ext4_max_bitmap_size
would allow bigger files than that.

> ... and we do have checks in ext4_setattr() which doesn't allow i_size
> to be set to a value larger than sb->s_maxbytes.  (Or
> EXT4_SB(sb)->s_bitmap_maxbytes if the file is mapped using indirect
> blocks.)  But since we do have maxbytes handy, we might as well add a
> safety check:
> 
>  if (offset > maxsize)
>   return -ENXIO;	/* or maybe -EINVAL; one could make an argument either way */
> 
> Still, it's possible for the file system to be corrupted such that the
> on-disk i_size is large enough to allow offset to be insanely large.
> 
> The worse that will happen here is that we will return a bogus
> location instead of returning an error, so the consequences of the
> truncation are minor.  But we should properly reject the call with an
> error if offset is insanely large, and decide what is the proper way
> to respond if SEEK_HOLE or SEEK_DATA is passed a negative offset.
> 
> Cheers,
> 
>      - Ted

  reply	other threads:[~2017-05-12 10:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CABniQZMSW6DiSvJ7Y2TZTwUKX6sGH6-WkQRjL-kPOmdm7PnKHA@mail.gmail.com>
2017-05-12  5:02 ` PAX: size overflow detected in function ext4_llseek fs/ext4/file.c:670 Theodore Ts'o
2017-05-12  9:58   ` PaX Team [this message]
2017-05-13  4:23     ` Shawn C
2017-05-13  6:56       ` PaX Team

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=5915875E.15260.4679D7CA@pageexec.freemail.hu \
    --to=pageexec@freemail.hu \
    --cc=citypw@gmail.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=re.emese@gmail.com \
    --cc=spender@grsecurity.net \
    --cc=tytso@mit.edu \
    /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