lkml.org 
[lkml]   [2019]   [Oct]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 106/114] vfs: Fix EOVERFLOW testing in put_compat_statfs64
    Date
    From: Eric Sandeen <sandeen@redhat.com>

    commit cc3a7bfe62b947b423fcb2cfe89fcba92bf48fa3 upstream.

    Today, put_compat_statfs64() disallows nearly any field value over
    2^32 if f_bsize is only 32 bits, but that makes no sense.
    compat_statfs64 is there for the explicit purpose of providing 64-bit
    fields for f_files, f_ffree, etc. And f_bsize is always only 32 bits.

    As a result, 32-bit userspace gets -EOVERFLOW for i.e. large file
    counts even with -D_FILE_OFFSET_BITS=64 set.

    In reality, only f_bsize and f_frsize can legitimately overflow
    (fields like f_type and f_namelen should never be large), so test
    only those fields.

    This bug was discussed at length some time ago, and this is the proposal
    Al suggested at https://lkml.org/lkml/2018/8/6/640. It seemed to get
    dropped amid the discussion of other related changes, but this
    part seems obviously correct on its own, so I've picked it up and
    sent it, for expediency.

    Fixes: 64d2ab32efe3 ("vfs: fix put_compat_statfs64() does not handle errors")
    Signed-off-by: Eric Sandeen <sandeen@redhat.com>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/statfs.c | 17 ++++-------------
    1 file changed, 4 insertions(+), 13 deletions(-)

    --- a/fs/statfs.c
    +++ b/fs/statfs.c
    @@ -304,19 +304,10 @@ COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned
    static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
    {
    struct compat_statfs64 buf;
    - if (sizeof(ubuf->f_bsize) == 4) {
    - if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
    - kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
    - return -EOVERFLOW;
    - /* f_files and f_ffree may be -1; it's okay
    - * to stuff that into 32 bits */
    - if (kbuf->f_files != 0xffffffffffffffffULL
    - && (kbuf->f_files & 0xffffffff00000000ULL))
    - return -EOVERFLOW;
    - if (kbuf->f_ffree != 0xffffffffffffffffULL
    - && (kbuf->f_ffree & 0xffffffff00000000ULL))
    - return -EOVERFLOW;
    - }
    +
    + if ((kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
    + return -EOVERFLOW;
    +
    memset(&buf, 0, sizeof(struct compat_statfs64));
    buf.f_type = kbuf->f_type;
    buf.f_bsize = kbuf->f_bsize;

    \
     
     \ /
      Last update: 2019-10-10 10:49    [W:2.229 / U:0.344 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site