Merge "Move the ILP32 mmap() hackery into legacy_32_bit_support.cpp." into main am: cbc07d4d31 am: 0031c5a935

Original change: https://android-review.googlesource.com/c/platform/bionic/+/3118911

Change-Id: I9aef6205371070efa9ce76a7cce0796c6c47eceb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Elliott Hughes 2024-06-07 11:12:04 +00:00 committed by Automerger Merge Worker
commit 19e49a1c09
4 changed files with 46 additions and 75 deletions

View file

@ -1224,9 +1224,6 @@ cc_library_static {
// off64_t/time64_t support on LP32. // off64_t/time64_t support on LP32.
"bionic/legacy_32_bit_support.cpp", "bionic/legacy_32_bit_support.cpp",
"bionic/time64.c", "bionic/time64.c",
// TODO: move to libc/bionic/legacy_32_bit_support.cpp or #if __LP64__ instead.
"bionic/mmap.cpp",
], ],
}, },
}, },

View file

@ -174,20 +174,21 @@ int utimensat(int, const char*, const struct timespec times[2], int) all
off_t lseek(int, off_t, int) lp32 off_t lseek(int, off_t, int) lp32
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) lp32 int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) lp32
off_t lseek|lseek64(int, off_t, int) lp64 off_t lseek|lseek64(int, off_t, int) lp64
int ftruncate64(int, off64_t) lp32
int ftruncate|ftruncate64(int, off_t) lp64
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) lp32 ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) lp32
ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) lp32 ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) lp32
ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) lp64 ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) lp64
int truncate(const char*, off_t) lp32 int truncate(const char*, off_t) lp32
int truncate64(const char*, off64_t) lp32 int truncate64(const char*, off64_t) lp32
int truncate|truncate64(const char*, off_t) lp64 int truncate|truncate64(const char*, off_t) lp64
# (mmap only gets two lines because we only used the 64-bit variant on 32-bit systems.)
void* __mmap2:mmap2(void*, size_t, int, int, int, long) lp32
void* mmap|mmap64(void*, size_t, int, int, int, off_t) lp64
# (fallocate only gets two lines because there is no 32-bit variant.) # (fallocate only gets two lines because there is no 32-bit variant.)
int fallocate64:fallocate(int, int, off64_t, off64_t) lp32 int fallocate64:fallocate(int, int, off64_t, off64_t) lp32
int fallocate|fallocate64(int, int, off_t, off_t) lp64 int fallocate|fallocate64(int, int, off_t, off_t) lp64
# (ftruncate only gets two lines because 32-bit bionic only uses the 64-bit call.)
int ftruncate64(int, off64_t) lp32
int ftruncate|ftruncate64(int, off_t) lp64
# (mmap only gets two lines because 32-bit bionic only uses the 64-bit call.)
void* __mmap2:mmap2(void*, size_t, int, int, int, long) lp32
void* mmap|mmap64(void*, size_t, int, int, int, off_t) lp64
# posix_fadvise64 is awkward: arm has shuffled arguments, # posix_fadvise64 is awkward: arm has shuffled arguments,
# the POSIX functions don't set errno, and no architecture has posix_fadvise. # the POSIX functions don't set errno, and no architecture has posix_fadvise.

View file

@ -30,24 +30,28 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdint.h>
#include <sys/mman.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h>
#include <sys/vfs.h>
#include <unistd.h> #include <unistd.h>
#include "platform/bionic/macros.h"
#include "platform/bionic/page.h"
#include "private/ErrnoRestorer.h"
#include "private/bionic_fdtrack.h" #include "private/bionic_fdtrack.h"
#if defined(__LP64__) #if defined(__LP64__)
#error This code is only needed on 32-bit systems! #error This code is only needed on 32-bit systems!
#endif #endif
// System calls we need. // To implement lseek64() on ILP32, we need to use the _llseek() system call
// which splits the off64_t into two 32-bit arguments and returns the off64_t
// result via a pointer because 32-bit kernels can't accept 64-bit arguments
// or return 64-bit results. (Our symbol is __llseek with two underscores for
// historical reasons, but it's exposed as ABI so we can't fix it.)
extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int); extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int);
// For lseek64 we need to use the llseek system call which splits the off64_t in two and
// returns the off64_t result via a pointer because 32-bit kernels can't return 64-bit results.
off64_t lseek64(int fd, off64_t off, int whence) { off64_t lseek64(int fd, off64_t off, int whence) {
off64_t result; off64_t result;
unsigned long off_hi = static_cast<unsigned long>(off >> 32); unsigned long off_hi = static_cast<unsigned long>(off >> 32);
@ -101,3 +105,33 @@ int prlimit(pid_t pid, int resource, const rlimit* n32, rlimit* o32) {
} }
return result; return result;
} }
// mmap2(2) is like mmap(2), but the offset is in 4096-byte blocks (regardless
// of page size), not bytes, to enable mapping parts of large files past the
// 4GiB limit but without the inconvenience of dealing with 64-bit values, with
// no down side since mappings need to be page aligned anyway, and the 32-bit
// architectures that support this system call all have 4KiB pages.
extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
static constexpr size_t MMAP2_SHIFT = 12;
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT) - 1)) != 0) {
errno = EINVAL;
return MAP_FAILED;
}
// Prevent allocations large enough for `end - start` to overflow,
// to avoid security bugs.
size_t rounded = __BIONIC_ALIGN(size, page_size());
if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
}
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
return mmap64(addr, size, prot, flags, fd, static_cast<off64_t>(offset));
}

View file

@ -1,61 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <errno.h>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
#include "platform/bionic/macros.h"
#include "platform/bionic/page.h"
#include "private/ErrnoRestorer.h"
// mmap2(2) is like mmap(2), but the offset is in 4096-byte blocks, not bytes.
extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
#define MMAP2_SHIFT 12 // 2**12 == 4096
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
errno = EINVAL;
return MAP_FAILED;
}
// Prevent allocations large enough for `end - start` to overflow.
size_t rounded = __BIONIC_ALIGN(size, page_size());
if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
}
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
return mmap64(addr, size, prot, flags, fd, static_cast<off64_t>(offset));
}