Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] uml: physical memory map file fixes

UML really wants shared memory semantics form its physical memory map file,
and the place for that is /dev/shm. So move the default, and fix the error
messages to recognize that this value can be overridden.

Signed-off-by: Rob Landley <rob@landley.net>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Rob Landley and committed by
Linus Torvalds
966a082f f983c45e

+118 -24
+117 -1
arch/um/os-Linux/mem.c
··· 8 8 #include <fcntl.h> 9 9 #include <sys/types.h> 10 10 #include <sys/mman.h> 11 + #include <sys/statfs.h> 11 12 #include "kern_util.h" 12 13 #include "user.h" 13 14 #include "user_util.h" ··· 20 19 21 20 #include <sys/param.h> 22 21 22 + static char *default_tmpdir = "/tmp"; 23 23 static char *tempdir = NULL; 24 24 25 25 static void __init find_tempdir(void) ··· 36 34 break; 37 35 } 38 36 if((dir == NULL) || (*dir == '\0')) 39 - dir = "/tmp"; 37 + dir = default_tmpdir; 40 38 41 39 tempdir = malloc(strlen(dir) + 2); 42 40 if(tempdir == NULL){ ··· 46 44 } 47 45 strcpy(tempdir, dir); 48 46 strcat(tempdir, "/"); 47 + } 48 + 49 + /* This will return 1, with the first character in buf being the 50 + * character following the next instance of c in the file. This will 51 + * read the file as needed. If there's an error, -errno is returned; 52 + * if the end of the file is reached, 0 is returned. 53 + */ 54 + static int next(int fd, char *buf, int size, char c) 55 + { 56 + int n; 57 + char *ptr; 58 + 59 + while((ptr = strchr(buf, c)) == NULL){ 60 + n = read(fd, buf, size - 1); 61 + if(n == 0) 62 + return 0; 63 + else if(n < 0) 64 + return -errno; 65 + 66 + buf[n] = '\0'; 67 + } 68 + 69 + ptr++; 70 + memmove(buf, ptr, strlen(ptr) + 1); 71 + return 1; 72 + } 73 + 74 + static int checked_tmpdir = 0; 75 + 76 + /* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner 77 + * way to do this than to parse /proc/mounts. statfs will return the 78 + * same filesystem magic number and fs id for both /dev and /dev/shm 79 + * when they are both tmpfs, so you can't tell if they are different 80 + * filesystems. Also, there seems to be no other way of finding the 81 + * mount point of a filesystem from within it. 82 + * 83 + * If a /dev/shm tmpfs entry is found, then we switch to using it. 84 + * Otherwise, we stay with the default /tmp. 85 + */ 86 + static void which_tmpdir(void) 87 + { 88 + int fd, found; 89 + char buf[128] = { '\0' }; 90 + 91 + if(checked_tmpdir) 92 + return; 93 + 94 + checked_tmpdir = 1; 95 + 96 + printf("Checking for tmpfs mount on /dev/shm..."); 97 + 98 + fd = open("/proc/mounts", O_RDONLY); 99 + if(fd < 0){ 100 + printf("failed to open /proc/mounts, errno = %d\n", errno); 101 + return; 102 + } 103 + 104 + while(1){ 105 + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); 106 + if(found != 1) 107 + break; 108 + 109 + if(!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) 110 + goto found; 111 + 112 + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n'); 113 + if(found != 1) 114 + break; 115 + } 116 + 117 + err: 118 + if(found == 0) 119 + printf("nothing mounted on /dev/shm\n"); 120 + else if(found < 0) 121 + printf("read returned errno %d\n", -found); 122 + 123 + return; 124 + 125 + found: 126 + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); 127 + if(found != 1) 128 + goto err; 129 + 130 + if(strncmp(buf, "tmpfs", strlen("tmpfs"))){ 131 + printf("not tmpfs\n"); 132 + return; 133 + } 134 + 135 + printf("OK\n"); 136 + default_tmpdir = "/dev/shm"; 49 137 } 50 138 51 139 /* ··· 148 56 char *tempname; 149 57 int fd; 150 58 59 + which_tmpdir(); 151 60 tempname = malloc(MAXPATHLEN); 152 61 153 62 find_tempdir(); ··· 229 136 perror("exec_close"); 230 137 } 231 138 return(fd); 139 + } 140 + 141 + 142 + void check_tmpexec(void) 143 + { 144 + void *addr; 145 + int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); 146 + 147 + addr = mmap(NULL, UM_KERN_PAGE_SIZE, 148 + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); 149 + printf("Checking PROT_EXEC mmap in %s...",tempdir); 150 + fflush(stdout); 151 + if(addr == MAP_FAILED){ 152 + err = errno; 153 + perror("failed"); 154 + if(err == EPERM) 155 + printf("%s must be not mounted noexec\n",tempdir); 156 + exit(1); 157 + } 158 + printf("OK\n"); 159 + munmap(addr, UM_KERN_PAGE_SIZE); 160 + 161 + close(fd); 232 162 }
+1 -23
arch/um/os-Linux/start_up.c
··· 296 296 check_sysemu(); 297 297 } 298 298 299 - extern int create_tmp_file(unsigned long long len); 300 - 301 - static void check_tmpexec(void) 302 - { 303 - void *addr; 304 - int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); 305 - 306 - addr = mmap(NULL, UM_KERN_PAGE_SIZE, 307 - PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); 308 - printf("Checking PROT_EXEC mmap in /tmp..."); 309 - fflush(stdout); 310 - if(addr == MAP_FAILED){ 311 - err = errno; 312 - perror("failed"); 313 - if(err == EPERM) 314 - printf("/tmp must be not mounted noexec\n"); 315 - exit(1); 316 - } 317 - printf("OK\n"); 318 - munmap(addr, UM_KERN_PAGE_SIZE); 319 - 320 - close(fd); 321 - } 299 + extern void check_tmpexec(void); 322 300 323 301 void os_early_checks(void) 324 302 {