This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

mmap64 with very large offset broken since glibc 2.26 (MIPS64 n32)


Hello,

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) [1], 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).

Regardless of the question whether an application should be doing such
physical memory access at all, I would like to understand whether it
is intentional that the mmap64 behavior change breaks this scenario.
It seems that in this case, there was no silent truncation of the
offset to begin with, so I would say that the mmap64 should succeed
even with glibc 2.26+.

Thanks,
Thomas

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=21270


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]