Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libc/src/__support/OSUtil/linux/auxv.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <linux/auxvec.h> // For AT_ macros
#include <linux/mman.h> // For mmap flags
#include <linux/param.h> // For EXEC_PAGESIZE
#include <linux/prctl.h> // For prctl
#include <sys/syscall.h> // For syscall numbers

Expand Down Expand Up @@ -90,7 +91,7 @@ LIBC_INLINE void Vector::fallback_initialize_unsync() {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// We do not proceed if mmap fails.
if (mmap_ret <= 0)
if (!linux_utils::is_valid_mmap(mmap_ret))
return;

// Initialize the auxv array with AT_NULL entries.
Expand Down
14 changes: 14 additions & 0 deletions libc/src/__support/OSUtil/linux/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/architectures.h"

#ifdef LIBC_TARGET_ARCH_IS_X86_32
Expand All @@ -34,6 +35,19 @@ LIBC_INLINE R syscall_impl(long __number, Ts... ts) {
return cpp::bit_or_static_cast<R>(syscall_impl(__number, (long)ts...));
}

// Linux-specific function for checking
namespace linux_utils {
LIBC_INLINE_VAR constexpr unsigned long MAX_ERRNO = 4095;
// Ideally, this should be defined using PAGE_OFFSET
// However, that is a configurable parameter. We mimic kernel's behavior
// by checking against MAX_ERRNO.
template <typename PointerLike>
LIBC_INLINE constexpr bool is_valid_mmap(PointerLike ptr) {
long addr = cpp::bit_cast<long>(ptr);
return LIBC_LIKELY(addr > 0 || addr < -static_cast<long>(MAX_ERRNO));
}
} // namespace linux_utils

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_SYSCALL_H
2 changes: 1 addition & 1 deletion libc/src/__support/threads/linux/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ LIBC_INLINE ErrorOr<void *> alloc_stack(size_t stacksize, size_t guardsize) {
-1, // Not backed by any file
0 // No offset
);
if (mmap_result < 0 && (uintptr_t(mmap_result) >= UINTPTR_MAX - size))
if (!linux_utils::is_valid_mmap(mmap_result))
return Error{int(-mmap_result)};

if (guardsize) {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/mman/linux/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ LLVM_LIBC_FUNCTION(void *, mmap,
// However, since a valid return address cannot be within the last page, a
// return value corresponding to a location in the last page is an error
// value.
if (ret < 0 && ret > -EXEC_PAGESIZE) {
if (!linux_utils::is_valid_mmap(ret)) {
libc_errno = static_cast<int>(-ret);
return MAP_FAILED;
}
Expand Down
2 changes: 1 addition & 1 deletion libc/startup/linux/aarch64/tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
if (mmap_ret_val < 0 && static_cast<uintptr_t>(mmap_ret_val) > -app.page_size)
if (!linux_utils::is_valid_mmap(mmap_ret_val))
syscall_impl<long>(SYS_exit, 1);
uintptr_t thread_ptr = uintptr_t(reinterpret_cast<uintptr_t *>(mmap_ret_val));
uintptr_t tls_addr = thread_ptr + size_of_pointers + padding;
Expand Down
2 changes: 1 addition & 1 deletion libc/startup/linux/riscv/tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
if (mmap_ret_val < 0 && static_cast<uintptr_t>(mmap_ret_val) > -app.page_size)
if (!linux_utils::is_valid_mmap(mmap_ret_val))
syscall_impl<long>(SYS_exit, 1);
uintptr_t thread_ptr = uintptr_t(reinterpret_cast<uintptr_t *>(mmap_ret_val));
uintptr_t tls_addr = thread_ptr + size_of_pointers + padding;
Expand Down
2 changes: 1 addition & 1 deletion libc/startup/linux/x86_64/tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void init_tls(TLSDescriptor &tls_descriptor) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// We cannot check the return value with MAP_FAILED as that is the return
// of the mmap function and not the mmap syscall.
if (mmap_retval < 0 && static_cast<uintptr_t>(mmap_retval) > -app.page_size)
if (!linux_utils::is_valid_mmap(mmap_retval))
syscall_impl<long>(SYS_exit, 1);
uintptr_t *tls_addr = reinterpret_cast<uintptr_t *>(mmap_retval);

Expand Down
Loading