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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML fixes from Richard Weinberger:
"Assorted fixes for UML"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
um: Memory corruption on startup
um: Missing pipe handling
uml: Simplify tempdir logic.

+98 -311
+1
arch/um/include/shared/os.h
··· 136 136 extern int os_get_ifname(int fd, char *namebuf); 137 137 extern int os_set_slip(int fd); 138 138 extern int os_mode_fd(int fd, int mode); 139 + extern int os_fsync_file(int fd); 139 140 140 141 extern int os_seek_file(int fd, unsigned long long offset); 141 142 extern int os_open_file(const char *file, struct openflags flags, int mode);
+1
arch/um/kernel/physmem.c
··· 103 103 */ 104 104 os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); 105 105 os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); 106 + os_fsync_file(physmem_fd); 106 107 107 108 bootmap_size = init_bootmem(pfn, pfn + delta); 108 109 free_bootmem(__pa(reserve_end) + bootmap_size,
+6
arch/um/os-Linux/file.c
··· 237 237 { 238 238 close(fd); 239 239 } 240 + int os_fsync_file(int fd) 241 + { 242 + if (fsync(fd) < 0) 243 + return -errno; 244 + return 0; 245 + } 240 246 241 247 int os_seek_file(int fd, unsigned long long offset) 242 248 {
+1
arch/um/os-Linux/main.c
··· 151 151 #endif 152 152 153 153 do_uml_initcalls(); 154 + change_sig(SIGPIPE, 0); 154 155 ret = linux_main(argc, argv); 155 156 156 157 /*
+89 -311
arch/um/os-Linux/mem.c
··· 12 12 #include <string.h> 13 13 #include <sys/stat.h> 14 14 #include <sys/mman.h> 15 - #include <sys/param.h> 15 + #include <sys/vfs.h> 16 + #include <linux/magic.h> 16 17 #include <init.h> 17 18 #include <os.h> 18 19 19 - /* Modified by which_tmpdir, which is called during early boot */ 20 - static char *default_tmpdir = "/tmp"; 21 - 22 - /* 23 - * Modified when creating the physical memory file and when checking 24 - * the tmp filesystem for usability, both happening during early boot. 25 - */ 20 + /* Set by make_tempfile() during early boot. */ 26 21 static char *tempdir = NULL; 27 22 28 - static void __init find_tempdir(void) 23 + /* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */ 24 + static int __init check_tmpfs(const char *dir) 29 25 { 30 - const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; 31 - int i; 32 - char *dir = NULL; 26 + struct statfs st; 33 27 34 - if (tempdir != NULL) 35 - /* We've already been called */ 36 - return; 37 - for (i = 0; dirs[i]; i++) { 38 - dir = getenv(dirs[i]); 39 - if ((dir != NULL) && (*dir != '\0')) 40 - break; 41 - } 42 - if ((dir == NULL) || (*dir == '\0')) 43 - dir = default_tmpdir; 44 - 45 - tempdir = malloc(strlen(dir) + 2); 46 - if (tempdir == NULL) { 47 - fprintf(stderr, "Failed to malloc tempdir, " 48 - "errno = %d\n", errno); 49 - return; 50 - } 51 - strcpy(tempdir, dir); 52 - strcat(tempdir, "/"); 53 - } 54 - 55 - /* 56 - * Remove bytes from the front of the buffer and refill it so that if there's a 57 - * partial string that we care about, it will be completed, and we can recognize 58 - * it. 59 - */ 60 - static int pop(int fd, char *buf, size_t size, size_t npop) 61 - { 62 - ssize_t n; 63 - size_t len = strlen(&buf[npop]); 64 - 65 - memmove(buf, &buf[npop], len + 1); 66 - n = read(fd, &buf[len], size - len - 1); 67 - if (n < 0) 68 - return -errno; 69 - 70 - buf[len + n] = '\0'; 71 - return 1; 72 - } 73 - 74 - /* 75 - * This will return 1, with the first character in buf being the 76 - * character following the next instance of c in the file. This will 77 - * read the file as needed. If there's an error, -errno is returned; 78 - * if the end of the file is reached, 0 is returned. 79 - */ 80 - static int next(int fd, char *buf, size_t size, char c) 81 - { 82 - ssize_t n; 83 - char *ptr; 84 - 85 - while ((ptr = strchr(buf, c)) == NULL) { 86 - n = read(fd, buf, size - 1); 87 - if (n == 0) 88 - return 0; 89 - else if (n < 0) 90 - return -errno; 91 - 92 - buf[n] = '\0'; 93 - } 94 - 95 - return pop(fd, buf, size, ptr - buf + 1); 96 - } 97 - 98 - /* 99 - * Decode an octal-escaped and space-terminated path of the form used by 100 - * /proc/mounts. May be used to decode a path in-place. "out" must be at least 101 - * as large as the input. The output is always null-terminated. "len" gets the 102 - * length of the output, excluding the trailing null. Returns 0 if a full path 103 - * was successfully decoded, otherwise an error. 104 - */ 105 - static int decode_path(const char *in, char *out, size_t *len) 106 - { 107 - char *first = out; 108 - int c; 109 - int i; 110 - int ret = -EINVAL; 111 - while (1) { 112 - switch (*in) { 113 - case '\0': 114 - goto out; 115 - 116 - case ' ': 117 - ret = 0; 118 - goto out; 119 - 120 - case '\\': 121 - in++; 122 - c = 0; 123 - for (i = 0; i < 3; i++) { 124 - if (*in < '0' || *in > '7') 125 - goto out; 126 - c = (c << 3) | (*in++ - '0'); 127 - } 128 - *(unsigned char *)out++ = (unsigned char) c; 129 - break; 130 - 131 - default: 132 - *out++ = *in++; 133 - break; 134 - } 135 - } 136 - 137 - out: 138 - *out = '\0'; 139 - *len = out - first; 140 - return ret; 141 - } 142 - 143 - /* 144 - * Computes the length of s when encoded with three-digit octal escape sequences 145 - * for the characters in chars. 146 - */ 147 - static size_t octal_encoded_length(const char *s, const char *chars) 148 - { 149 - size_t len = strlen(s); 150 - while ((s = strpbrk(s, chars)) != NULL) { 151 - len += 3; 152 - s++; 153 - } 154 - 155 - return len; 156 - } 157 - 158 - enum { 159 - OUTCOME_NOTHING_MOUNTED, 160 - OUTCOME_TMPFS_MOUNT, 161 - OUTCOME_NON_TMPFS_MOUNT, 162 - }; 163 - 164 - /* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */ 165 - static int read_mount(int fd, char *buf, size_t bufsize, const char *path, 166 - int *outcome) 167 - { 168 - int found; 169 - int match; 170 - char *space; 171 - size_t len; 172 - 173 - enum { 174 - MATCH_NONE, 175 - MATCH_EXACT, 176 - MATCH_PARENT, 177 - }; 178 - 179 - found = next(fd, buf, bufsize, ' '); 180 - if (found != 1) 181 - return found; 182 - 183 - /* 184 - * If there's no following space in the buffer, then this path is 185 - * truncated, so it can't be the one we're looking for. 186 - */ 187 - space = strchr(buf, ' '); 188 - if (space) { 189 - match = MATCH_NONE; 190 - if (!decode_path(buf, buf, &len)) { 191 - if (!strcmp(buf, path)) 192 - match = MATCH_EXACT; 193 - else if (!strncmp(buf, path, len) 194 - && (path[len] == '/' || !strcmp(buf, "/"))) 195 - match = MATCH_PARENT; 196 - } 197 - 198 - found = pop(fd, buf, bufsize, space - buf + 1); 199 - if (found != 1) 200 - return found; 201 - 202 - switch (match) { 203 - case MATCH_EXACT: 204 - if (!strncmp(buf, "tmpfs", strlen("tmpfs"))) 205 - *outcome = OUTCOME_TMPFS_MOUNT; 206 - else 207 - *outcome = OUTCOME_NON_TMPFS_MOUNT; 208 - break; 209 - 210 - case MATCH_PARENT: 211 - /* This mount obscures any previous ones. */ 212 - *outcome = OUTCOME_NOTHING_MOUNTED; 213 - break; 214 - } 215 - } 216 - 217 - return next(fd, buf, bufsize, '\n'); 218 - } 219 - 220 - /* which_tmpdir is called only during early boot */ 221 - static int checked_tmpdir = 0; 222 - 223 - /* 224 - * Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner 225 - * way to do this than to parse /proc/mounts. statfs will return the 226 - * same filesystem magic number and fs id for both /dev and /dev/shm 227 - * when they are both tmpfs, so you can't tell if they are different 228 - * filesystems. Also, there seems to be no other way of finding the 229 - * mount point of a filesystem from within it. 230 - * 231 - * If a /dev/shm tmpfs entry is found, then we switch to using it. 232 - * Otherwise, we stay with the default /tmp. 233 - */ 234 - static void which_tmpdir(void) 235 - { 236 - int fd; 237 - int found; 238 - int outcome; 239 - char *path; 240 - char *buf; 241 - size_t bufsize; 242 - 243 - if (checked_tmpdir) 244 - return; 245 - 246 - checked_tmpdir = 1; 247 - 248 - printf("Checking for tmpfs mount on /dev/shm..."); 249 - 250 - path = realpath("/dev/shm", NULL); 251 - if (!path) { 252 - printf("failed to check real path, errno = %d\n", errno); 253 - return; 254 - } 255 - printf("%s...", path); 256 - 257 - /* 258 - * The buffer needs to be able to fit the full octal-escaped path, a 259 - * space, and a trailing null in order to successfully decode it. 260 - */ 261 - bufsize = octal_encoded_length(path, " \t\n\\") + 2; 262 - 263 - if (bufsize < 128) 264 - bufsize = 128; 265 - 266 - buf = malloc(bufsize); 267 - if (!buf) { 268 - printf("malloc failed, errno = %d\n", errno); 269 - goto out; 270 - } 271 - buf[0] = '\0'; 272 - 273 - fd = open("/proc/mounts", O_RDONLY); 274 - if (fd < 0) { 275 - printf("failed to open /proc/mounts, errno = %d\n", errno); 276 - goto out1; 277 - } 278 - 279 - outcome = OUTCOME_NOTHING_MOUNTED; 280 - while (1) { 281 - found = read_mount(fd, buf, bufsize, path, &outcome); 282 - if (found != 1) 283 - break; 284 - } 285 - 286 - if (found < 0) { 287 - printf("read returned errno %d\n", -found); 28 + printf("Checking if %s is on tmpfs...", dir); 29 + if (statfs(dir, &st) < 0) { 30 + printf("%s\n", strerror(errno)); 31 + } else if (st.f_type != TMPFS_MAGIC) { 32 + printf("no\n"); 288 33 } else { 289 - switch (outcome) { 290 - case OUTCOME_TMPFS_MOUNT: 291 - printf("OK\n"); 292 - default_tmpdir = "/dev/shm"; 293 - break; 294 - 295 - case OUTCOME_NON_TMPFS_MOUNT: 296 - printf("not tmpfs\n"); 297 - break; 298 - 299 - default: 300 - printf("nothing mounted on /dev/shm\n"); 301 - break; 302 - } 34 + printf("OK\n"); 35 + return 0; 303 36 } 304 - 305 - close(fd); 306 - out1: 307 - free(buf); 308 - out: 309 - free(path); 37 + return -1; 310 38 } 311 39 312 - static int __init make_tempfile(const char *template, char **out_tempname, 313 - int do_unlink) 40 + /* 41 + * Choose the tempdir to use. We want something on tmpfs so that our memory is 42 + * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the 43 + * environment, we use that even if it's not on tmpfs, but we warn the user. 44 + * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found 45 + * then we fall back to /tmp. 46 + */ 47 + static char * __init choose_tempdir(void) 48 + { 49 + static const char * const vars[] = { 50 + "TMPDIR", 51 + "TMP", 52 + "TEMP", 53 + NULL 54 + }; 55 + static const char fallback_dir[] = "/tmp"; 56 + static const char * const tmpfs_dirs[] = { 57 + "/dev/shm", 58 + fallback_dir, 59 + NULL 60 + }; 61 + int i; 62 + const char *dir; 63 + 64 + printf("Checking environment variables for a tempdir..."); 65 + for (i = 0; vars[i]; i++) { 66 + dir = getenv(vars[i]); 67 + if ((dir != NULL) && (*dir != '\0')) { 68 + printf("%s\n", dir); 69 + if (check_tmpfs(dir) >= 0) 70 + goto done; 71 + else 72 + goto warn; 73 + } 74 + } 75 + printf("none found\n"); 76 + 77 + for (i = 0; tmpfs_dirs[i]; i++) { 78 + dir = tmpfs_dirs[i]; 79 + if (check_tmpfs(dir) >= 0) 80 + goto done; 81 + } 82 + 83 + dir = fallback_dir; 84 + warn: 85 + printf("Warning: tempdir %s is not on tmpfs\n", dir); 86 + done: 87 + /* Make a copy since getenv results may not remain valid forever. */ 88 + return strdup(dir); 89 + } 90 + 91 + /* 92 + * Create an unlinked tempfile in a suitable tempdir. template must be the 93 + * basename part of the template with a leading '/'. 94 + */ 95 + static int __init make_tempfile(const char *template) 314 96 { 315 97 char *tempname; 316 98 int fd; 317 99 318 - which_tmpdir(); 319 - tempname = malloc(MAXPATHLEN); 100 + if (tempdir == NULL) { 101 + tempdir = choose_tempdir(); 102 + if (tempdir == NULL) { 103 + fprintf(stderr, "Failed to choose tempdir: %s\n", 104 + strerror(errno)); 105 + return -1; 106 + } 107 + } 108 + 109 + tempname = malloc(strlen(tempdir) + strlen(template) + 1); 320 110 if (tempname == NULL) 321 111 return -1; 322 112 323 - find_tempdir(); 324 - if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) 325 - goto out; 326 - 327 - if (template[0] != '/') 328 - strcpy(tempname, tempdir); 329 - else 330 - tempname[0] = '\0'; 331 - strncat(tempname, template, MAXPATHLEN-1-strlen(tempname)); 113 + strcpy(tempname, tempdir); 114 + strcat(tempname, template); 332 115 fd = mkstemp(tempname); 333 116 if (fd < 0) { 334 117 fprintf(stderr, "open - cannot create %s: %s\n", tempname, 335 118 strerror(errno)); 336 119 goto out; 337 120 } 338 - if (do_unlink && (unlink(tempname) < 0)) { 121 + if (unlink(tempname) < 0) { 339 122 perror("unlink"); 340 123 goto close; 341 124 } 342 - if (out_tempname) { 343 - *out_tempname = tempname; 344 - } else 345 - free(tempname); 125 + free(tempname); 346 126 return fd; 347 127 close: 348 128 close(fd); ··· 131 351 return -1; 132 352 } 133 353 134 - #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" 354 + #define TEMPNAME_TEMPLATE "/vm_file-XXXXXX" 135 355 136 356 static int __init create_tmp_file(unsigned long long len) 137 357 { 138 358 int fd, err; 139 359 char zero; 140 360 141 - fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); 361 + fd = make_tempfile(TEMPNAME_TEMPLATE); 142 362 if (fd < 0) 143 363 exit(1); 144 364 ··· 182 402 return fd; 183 403 } 184 404 185 - 186 405 void __init check_tmpexec(void) 187 406 { 188 407 void *addr; ··· 189 410 190 411 addr = mmap(NULL, UM_KERN_PAGE_SIZE, 191 412 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); 192 - printf("Checking PROT_EXEC mmap in %s...",tempdir); 193 - fflush(stdout); 413 + printf("Checking PROT_EXEC mmap in %s...", tempdir); 194 414 if (addr == MAP_FAILED) { 195 415 err = errno; 196 - perror("failed"); 416 + printf("%s\n", strerror(err)); 197 417 close(fd); 198 418 if (err == EPERM) 199 - printf("%s must be not mounted noexec\n",tempdir); 419 + printf("%s must be not mounted noexec\n", tempdir); 200 420 exit(1); 201 421 } 202 422 printf("OK\n");