1/* 2 * Copyright (c) 2002, Intel Corporation. All rights reserved. 3 * Copyright (c) 2012, Cyril Hrubis <chrubis@suse.cz> 4 * 5 * This file is licensed under the GPL license. For the full content 6 * of this license, see the COPYING file at the top level of this 7 * source tree. 8 * 9 * The mmap() function shall fail if: 10 * [EOVERFLOW] The file is a regular file and the value of off 11 * plus len exceeds the offset maximum established in the open 12 * file description associated with fildes. 13 * 14 * Note: This error condition came to the standard with large 15 * file extension and cannot be triggered without it. 16 * 17 * So in order to trigger this we need 32 bit architecture 18 * and largefile support turned on. 19 */ 20 21#define _XOPEN_SOURCE 600 22 23/* Turn on large file support, has no effect on 64 bit archs */ 24#define _FILE_OFFSET_BITS 64 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <unistd.h> 29#include <limits.h> 30#include <sys/mman.h> 31#include <sys/types.h> 32#include <sys/stat.h> 33#include <sys/wait.h> 34#include <fcntl.h> 35#include <string.h> 36#include <errno.h> 37#include <sys/utsname.h> 38#include "posixtest.h" 39 40int main(void) 41{ 42 char tmpfname[256]; 43 44 void *pa; 45 size_t len; 46 int fd; 47 off_t off = 0; 48 49 /* check for 64 bit arch */ 50 if (sizeof(void *) == 8) { 51 printf("USUPPORTED: Cannot be tested on 64 bit architecture\n"); 52 return PTS_UNSUPPORTED; 53 } 54 55 /* The overflow does not happen when 32bit binary runs on 64bit kernel */ 56#ifdef __linux__ 57 struct utsname buf; 58 59 if (!uname(&buf) && strstr(buf.machine, "64")) { 60 printf("UNSUPPORTED: Looks like we run on 64bit kernel (%s)\n", 61 buf.machine); 62 return PTS_UNSUPPORTED; 63 } 64 65#endif /* __linux__ */ 66 67 long page_size = sysconf(_SC_PAGE_SIZE); 68 69 snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_mmap_31_1_%d", getpid()); 70 unlink(tmpfname); 71 fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); 72 if (fd == -1) { 73 printf("Error at open(): %s\n", strerror(errno)); 74 return PTS_UNRESOLVED; 75 } 76 unlink(tmpfname); 77 78 /* Set lenght to maximal multiple of page size */ 79 len = ~((size_t) 0) & (~(page_size - 1)); 80 81 /* 82 * Now we need offset that fits into 32 bit 83 * value when divided by page size but is big 84 * enough so that offset + PAGE_ALIGN(len) / page_size 85 * overflows 32 bits. 86 */ 87 off = ((off_t) ~ ((size_t) 0)) * page_size; 88 off &= ~(page_size - 1); 89 90 printf("off: %llx, len: %llx\n", (unsigned long long)off, 91 (unsigned long long)len); 92 93 pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off); 94 if (pa == MAP_FAILED && errno == EOVERFLOW) { 95 printf("Got EOVERFLOW\n"); 96 printf("Test PASSED\n"); 97 return PTS_PASS; 98 } 99 100 if (pa == MAP_FAILED) 101 perror("Test FAILED: expect EOVERFLOW but get other error"); 102 else 103 printf("Test FAILED: Expect EOVERFLOW but got no error\n"); 104 105 close(fd); 106 munmap(pa, len); 107 return PTS_FAIL; 108} 109