[Bug libc/24699] New: mmap64 with very large offset broken on MIPS64 n32

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] New: mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

            Bug ID: 24699
           Summary: mmap64 with very large offset broken on MIPS64 n32
           Product: glibc
           Version: 2.26
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: patrickdepinguin at gmail dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

Corresponding mail discussion:
https://www.sourceware.org/ml/libc-alpha/2019-06/msg00280.html

Bug opened as this is a user-visible problem, as discussed with Florian Weimer.

---

In glibc 2.26, a change was made to the behavior of mmap64, as a fix
for bug #21270 (mmap64 silently truncates large offset values), via
commit 158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.
Practically, with the new behavior, doing mmap64 with an offset larger
than 1<<44 now fails with errno=EINVAL. The reasoning in this bug is
that offsets greater than 1<<44  are silently truncated, and so better
to fail early.

However, I have several cases in embedded applications where such
mmap64 with large offset values is performed, and it worked correctly
(< 2.26). In these applications, a physical memory region is mapped
into the virtual address space, by performing an mmap64 on /dev/mem.
The offset is very large because this is accessing devices high up in
the memory range.

This is on MIPS64 with the n32 ABI.

Example code is:

#define _GNU_SOURCE
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdint.h>
#include <fcntl.h>
#include <inttypes.h>

int main(void)
{
    off_t physical_base = 0x100001a000000ull;
    size_t length = 0x1000;
    volatile uint32_t* virtual_base;

    int fd = open("/dev/mem",O_RDWR);
    if (fd < 0) {
        perror("cannot open /dev/mem");
        return 1;
    }

    errno = 0;
    virtual_base = (volatile uint32_t*) mmap64(0, length,
PROT_READ|PROT_WRITE, MAP_SHARED, fd, physical_base);
    if (virtual_base == (volatile uint32_t *)-1) {
        printf("Mapping failed, errno=%d\n", errno);
        return 1;
    }
    printf("Virtual address: %p\n", virtual_base);
    return 0;
}



On a toolchain using gcc 4.7, glibc 2.16, the above gives a valid
virtual address.
On a toolchain using gcc 7.3, glibc 2.27, the mapping fails with
errno=22 (EINVAL) and virtual_base=-1 (0xffffffff).

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

--- Comment #1 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a008c76b56e4f958cf5a0d6f67d29fade89421b7

commit a008c76b56e4f958cf5a0d6f67d29fade89421b7
Author: Adhemerval Zanella <[hidden email]>
Date:   Tue Jun 18 14:09:09 2019 -0300

    posix: Fix large mmap64 offset for mips64n32 (BZ#24699)

    The fix for BZ#21270 (commit 158d5fa0e19) added a mask to avoid offset
larger
    than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
    as mips64n64, but still defines off_t as old non-LFS type (other ILP32,
such
    x32, defines off_t being equal to off64_t).  This leads to use the same
    mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the
maximum
    offset it can use with mmap64.

    This patch fixes by setting the high mask only for __NR_mmap2 usage. The
    posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
    patch also change the test to check for an arch-specific header that
defines
    the maximum supported offset.

    Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests
tst-mmap-offset
    on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu
and
    mips64-n32-linux-gnu.

        [BZ #24699]
        * posix/tst-mmap-offset.c: Mention BZ #24699.
        (do_test_bz21270): Rename to do_test_large_offset and use
        mmap64_maximum_offset to check for maximum expected offset value.
        * sysdeps/generic/mmap_info.h: New file.
        * sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
        * sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
        __NR_mmap2 is used.

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
In reply to this post by Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

Adhemerval Zanella <adhemerval.zanella at linaro dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |adhemerval.zanella at linaro dot o
                   |                            |rg
         Resolution|---                         |FIXED
           Assignee|unassigned at sourceware dot org   |adhemerval.zanella at linaro dot o
                   |                            |rg
   Target Milestone|---                         |2.30

--- Comment #2 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
Fixed on 2.30.

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
In reply to this post by Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

--- Comment #3 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.26/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=54194d8b4d097fd3a9cb9528a0ad686622d6c182

commit 54194d8b4d097fd3a9cb9528a0ad686622d6c182
Author: Adhemerval Zanella <[hidden email]>
Date:   Tue Jun 18 14:09:09 2019 -0300

    posix: Fix large mmap64 offset for mips64n32 (BZ#24699)

    The fix for BZ#21270 (commit 158d5fa0e19) added a mask to avoid offset
larger
    than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
    as mips64n64, but still defines off_t as old non-LFS type (other ILP32,
such
    x32, defines off_t being equal to off64_t).  This leads to use the same
    mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the
maximum
    offset it can use with mmap64.

    This patch fixes by setting the high mask only for __NR_mmap2 usage. The
    posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
    patch also change the test to check for an arch-specific header that
defines
    the maximum supported offset.

    Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests
tst-mmap-offset
    on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu
and
    mips64-n32-linux-gnu.

        [BZ #24699]
        * posix/tst-mmap-offset.c: Mention BZ #24699.
        (do_test_bz21270): Rename to do_test_large_offset and use
        mmap64_maximum_offset to check for maximum expected offset value.
        * sysdeps/generic/mmap_info.h: New file.
        * sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
        * sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
        __NR_mmap2 is used.

    (cherry picked from commit a008c76b56e4f958cf5a0d6f67d29fade89421b7)

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
In reply to this post by Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

--- Comment #4 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.27/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=22bd3ab40e83ec0049bfb3bdba3b9ebdb1a6ab20

commit 22bd3ab40e83ec0049bfb3bdba3b9ebdb1a6ab20
Author: Adhemerval Zanella <[hidden email]>
Date:   Tue Jun 18 14:09:09 2019 -0300

    posix: Fix large mmap64 offset for mips64n32 (BZ#24699)

    The fix for BZ#21270 (commit 158d5fa0e19) added a mask to avoid offset
larger
    than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
    as mips64n64, but still defines off_t as old non-LFS type (other ILP32,
such
    x32, defines off_t being equal to off64_t).  This leads to use the same
    mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the
maximum
    offset it can use with mmap64.

    This patch fixes by setting the high mask only for __NR_mmap2 usage. The
    posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
    patch also change the test to check for an arch-specific header that
defines
    the maximum supported offset.

    Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests
tst-mmap-offset
    on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu
and
    mips64-n32-linux-gnu.

        [BZ #24699]
        * posix/tst-mmap-offset.c: Mention BZ #24699.
        (do_test_bz21270): Rename to do_test_large_offset and use
        mmap64_maximum_offset to check for maximum expected offset value.
        * sysdeps/generic/mmap_info.h: New file.
        * sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
        * sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
        __NR_mmap2 is used.

    (cherry picked from commit a008c76b56e4f958cf5a0d6f67d29fade89421b7)

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
In reply to this post by Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

--- Comment #5 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.28/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=57922433fa038faa6e37798b9655f85a94978d89

commit 57922433fa038faa6e37798b9655f85a94978d89
Author: Adhemerval Zanella <[hidden email]>
Date:   Tue Jun 18 14:09:09 2019 -0300

    posix: Fix large mmap64 offset for mips64n32 (BZ#24699)

    The fix for BZ#21270 (commit 158d5fa0e19) added a mask to avoid offset
larger
    than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
    as mips64n64, but still defines off_t as old non-LFS type (other ILP32,
such
    x32, defines off_t being equal to off64_t).  This leads to use the same
    mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the
maximum
    offset it can use with mmap64.

    This patch fixes by setting the high mask only for __NR_mmap2 usage. The
    posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
    patch also change the test to check for an arch-specific header that
defines
    the maximum supported offset.

    Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests
tst-mmap-offset
    on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu
and
    mips64-n32-linux-gnu.

        [BZ #24699]
        * posix/tst-mmap-offset.c: Mention BZ #24699.
        (do_test_bz21270): Rename to do_test_large_offset and use
        mmap64_maximum_offset to check for maximum expected offset value.
        * sysdeps/generic/mmap_info.h: New file.
        * sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
        * sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
        __NR_mmap2 is used.

    (cherry picked from commit a008c76b56e4f958cf5a0d6f67d29fade89421b7)

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/24699] mmap64 with very large offset broken on MIPS64 n32

Martin.Jansa at gmail dot com
In reply to this post by Martin.Jansa at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=24699

--- Comment #6 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.29/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=2d3fefd7ce64ac1015701c96916fffacc073a877

commit 2d3fefd7ce64ac1015701c96916fffacc073a877
Author: Adhemerval Zanella <[hidden email]>
Date:   Tue Jun 18 14:09:09 2019 -0300

    posix: Fix large mmap64 offset for mips64n32 (BZ#24699)

    The fix for BZ#21270 (commit 158d5fa0e19) added a mask to avoid offset
larger
    than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
    as mips64n64, but still defines off_t as old non-LFS type (other ILP32,
such
    x32, defines off_t being equal to off64_t).  This leads to use the same
    mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the
maximum
    offset it can use with mmap64.

    This patch fixes by setting the high mask only for __NR_mmap2 usage. The
    posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
    patch also change the test to check for an arch-specific header that
defines
    the maximum supported offset.

    Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests
tst-mmap-offset
    on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu
and
    mips64-n32-linux-gnu.

        [BZ #24699]
        * posix/tst-mmap-offset.c: Mention BZ #24699.
        (do_test_bz21270): Rename to do_test_large_offset and use
        mmap64_maximum_offset to check for maximum expected offset value.
        * sysdeps/generic/mmap_info.h: New file.
        * sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
        * sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
        __NR_mmap2 is used.

    (cherry picked from commit a008c76b56e4f958cf5a0d6f67d29fade89421b7)

--
You are receiving this mail because:
You are on the CC list for the bug.