The following program maps page 0x7fffffffe000 then use recv (translated into recvfrom in glibc) to receive 4096 bytes. according to strace's result, recvfrom returns -EFAULT. If change 0x7fffffffe000 to 0x7fffffffd000, recvfrom returns successfully. My kernel version is 2.6.36-gentoo-r5. #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <sys/mman.h> #include <sys/socket.h> #include <assert.h> #define PAGE_SIZE (4096) #define LAST_PAGE ((void*)(0x7fffffffe000)) int main() { void * ptr = mmap(LAST_PAGE, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); assert(ptr == LAST_PAGE); memset(ptr, '\0', PAGE_SIZE); void * data = malloc(PAGE_SIZE); assert(data != NULL); memset(data, '1', PAGE_SIZE); int fds[2]; int err = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds); assert(err == 0); err = send(fds[0], data, PAGE_SIZE, 0); assert(err == PAGE_SIZE); err = recv(fds[1], ptr, PAGE_SIZE, MSG_WAITALL); perror("recv returns"); return 0; } // vim:ts=4:sw=4 Reproducible: Always Steps to Reproduce: 1. compile the program; 2. run the generated executable; Actual Results: recv returns: Bad address Expected Results: recv returns: Success
fixed by following commit: x86, 64-bit: Fix copy_[to/from]_user() checks for the userspace address limit commit 26afb7c661080ae3f1f13ddf7f0c58c4f931c22b Date: Thu May 12 16:30:30 2011 +0200