aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/mem.c118
-rw-r--r--arch/um/os-Linux/process.c8
-rw-r--r--arch/um/os-Linux/skas/process.c36
-rw-r--r--arch/um/os-Linux/start_up.c24
-rw-r--r--arch/um/os-Linux/trap.c4
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/util.c2
7 files changed, 145 insertions, 51 deletions
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 71bb90a7606d..c6432e729241 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
8#include <fcntl.h> 8#include <fcntl.h>
9#include <sys/types.h> 9#include <sys/types.h>
10#include <sys/mman.h> 10#include <sys/mman.h>
11#include <sys/statfs.h>
11#include "kern_util.h" 12#include "kern_util.h"
12#include "user.h" 13#include "user.h"
13#include "user_util.h" 14#include "user_util.h"
@@ -19,6 +20,7 @@
19 20
20#include <sys/param.h> 21#include <sys/param.h>
21 22
23static char *default_tmpdir = "/tmp";
22static char *tempdir = NULL; 24static char *tempdir = NULL;
23 25
24static void __init find_tempdir(void) 26static void __init find_tempdir(void)
@@ -34,7 +36,7 @@ static void __init find_tempdir(void)
34 break; 36 break;
35 } 37 }
36 if((dir == NULL) || (*dir == '\0')) 38 if((dir == NULL) || (*dir == '\0'))
37 dir = "/tmp"; 39 dir = default_tmpdir;
38 40
39 tempdir = malloc(strlen(dir) + 2); 41 tempdir = malloc(strlen(dir) + 2);
40 if(tempdir == NULL){ 42 if(tempdir == NULL){
@@ -46,6 +48,96 @@ static void __init find_tempdir(void)
46 strcat(tempdir, "/"); 48 strcat(tempdir, "/");
47} 49}
48 50
51/* This will return 1, with the first character in buf being the
52 * character following the next instance of c in the file. This will
53 * read the file as needed. If there's an error, -errno is returned;
54 * if the end of the file is reached, 0 is returned.
55 */
56static int next(int fd, char *buf, int size, char c)
57{
58 int n;
59 char *ptr;
60
61 while((ptr = strchr(buf, c)) == NULL){
62 n = read(fd, buf, size - 1);
63 if(n == 0)
64 return 0;
65 else if(n < 0)
66 return -errno;
67
68 buf[n] = '\0';
69 }
70
71 ptr++;
72 memmove(buf, ptr, strlen(ptr) + 1);
73 return 1;
74}
75
76static int checked_tmpdir = 0;
77
78/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
79 * way to do this than to parse /proc/mounts. statfs will return the
80 * same filesystem magic number and fs id for both /dev and /dev/shm
81 * when they are both tmpfs, so you can't tell if they are different
82 * filesystems. Also, there seems to be no other way of finding the
83 * mount point of a filesystem from within it.
84 *
85 * If a /dev/shm tmpfs entry is found, then we switch to using it.
86 * Otherwise, we stay with the default /tmp.
87 */
88static void which_tmpdir(void)
89{
90 int fd, found;
91 char buf[128] = { '\0' };
92
93 if(checked_tmpdir)
94 return;
95
96 checked_tmpdir = 1;
97
98 printf("Checking for tmpfs mount on /dev/shm...");
99
100 fd = open("/proc/mounts", O_RDONLY);
101 if(fd < 0){
102 printf("failed to open /proc/mounts, errno = %d\n", errno);
103 return;
104 }
105
106 while(1){
107 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
108 if(found != 1)
109 break;
110
111 if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
112 goto found;
113
114 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
115 if(found != 1)
116 break;
117 }
118
119err:
120 if(found == 0)
121 printf("nothing mounted on /dev/shm\n");
122 else if(found < 0)
123 printf("read returned errno %d\n", -found);
124
125 return;
126
127found:
128 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
129 if(found != 1)
130 goto err;
131
132 if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
133 printf("not tmpfs\n");
134 return;
135 }
136
137 printf("OK\n");
138 default_tmpdir = "/dev/shm";
139}
140
49/* 141/*
50 * This proc still used in tt-mode 142 * This proc still used in tt-mode
51 * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). 143 * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -56,6 +148,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
56 char *tempname; 148 char *tempname;
57 int fd; 149 int fd;
58 150
151 which_tmpdir();
59 tempname = malloc(MAXPATHLEN); 152 tempname = malloc(MAXPATHLEN);
60 153
61 find_tempdir(); 154 find_tempdir();
@@ -137,3 +230,26 @@ int create_mem_file(unsigned long long len)
137 } 230 }
138 return(fd); 231 return(fd);
139} 232}
233
234
235void check_tmpexec(void)
236{
237 void *addr;
238 int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
239
240 addr = mmap(NULL, UM_KERN_PAGE_SIZE,
241 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
242 printf("Checking PROT_EXEC mmap in %s...",tempdir);
243 fflush(stdout);
244 if(addr == MAP_FAILED){
245 err = errno;
246 perror("failed");
247 if(err == EPERM)
248 printf("%s must be not mounted noexec\n",tempdir);
249 exit(1);
250 }
251 printf("OK\n");
252 munmap(addr, UM_KERN_PAGE_SIZE);
253
254 close(fd);
255}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 8176b0b52047..3505f44f8a25 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -190,7 +190,7 @@ int os_unmap_memory(void *addr, int len)
190} 190}
191 191
192#ifndef MADV_REMOVE 192#ifndef MADV_REMOVE
193#define MADV_REMOVE 0x5 /* remove these pages & resources */ 193#define MADV_REMOVE KERNEL_MADV_REMOVE
194#endif 194#endif
195 195
196int os_drop_memory(void *addr, int length) 196int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@ int can_drop_memory(void)
216 } 216 }
217 217
218 addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 218 addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
219 MAP_PRIVATE, fd, 0); 219 MAP_SHARED, fd, 0);
220 if(addr == MAP_FAILED){ 220 if(addr == MAP_FAILED){
221 printk("Mapping test memory file failed, err = %d\n", -errno); 221 printk("Mapping test memory file failed, err = %d\n", -errno);
222 return 0; 222 return 0;
@@ -266,11 +266,11 @@ void init_new_thread_signals(int altstack)
266 266
267int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 267int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
268{ 268{
269 sigjmp_buf buf; 269 jmp_buf buf;
270 int n, enable; 270 int n, enable;
271 271
272 *jmp_ptr = &buf; 272 *jmp_ptr = &buf;
273 n = UML_SIGSETJMP(&buf, enable); 273 n = UML_SETJMP(&buf, enable);
274 if(n != 0) 274 if(n != 0)
275 return(n); 275 return(n);
276 (*fn)(arg); 276 (*fn)(arg);
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 045ae0037456..0776bc18ca85 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -434,7 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
434 void (*handler)(int)) 434 void (*handler)(int))
435{ 435{
436 unsigned long flags; 436 unsigned long flags;
437 sigjmp_buf switch_buf, fork_buf; 437 jmp_buf switch_buf, fork_buf;
438 int enable; 438 int enable;
439 439
440 *switch_buf_ptr = &switch_buf; 440 *switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
450 */ 450 */
451 flags = get_signals(); 451 flags = get_signals();
452 block_signals(); 452 block_signals();
453 if(UML_SIGSETJMP(&fork_buf, enable) == 0) 453 if(UML_SETJMP(&fork_buf, enable) == 0)
454 new_thread_proc(stack, handler); 454 new_thread_proc(stack, handler);
455 455
456 remove_sigstack(); 456 remove_sigstack();
@@ -466,35 +466,35 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
466 466
467void thread_wait(void *sw, void *fb) 467void thread_wait(void *sw, void *fb)
468{ 468{
469 sigjmp_buf buf, **switch_buf = sw, *fork_buf; 469 jmp_buf buf, **switch_buf = sw, *fork_buf;
470 int enable; 470 int enable;
471 471
472 *switch_buf = &buf; 472 *switch_buf = &buf;
473 fork_buf = fb; 473 fork_buf = fb;
474 if(UML_SIGSETJMP(&buf, enable) == 0) 474 if(UML_SETJMP(&buf, enable) == 0)
475 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); 475 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
476} 476}
477 477
478void switch_threads(void *me, void *next) 478void switch_threads(void *me, void *next)
479{ 479{
480 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; 480 jmp_buf my_buf, **me_ptr = me, *next_buf = next;
481 int enable; 481 int enable;
482 482
483 *me_ptr = &my_buf; 483 *me_ptr = &my_buf;
484 if(UML_SIGSETJMP(&my_buf, enable) == 0) 484 if(UML_SETJMP(&my_buf, enable) == 0)
485 UML_SIGLONGJMP(next_buf, 1); 485 UML_LONGJMP(next_buf, 1);
486} 486}
487 487
488static sigjmp_buf initial_jmpbuf; 488static jmp_buf initial_jmpbuf;
489 489
490/* XXX Make these percpu */ 490/* XXX Make these percpu */
491static void (*cb_proc)(void *arg); 491static void (*cb_proc)(void *arg);
492static void *cb_arg; 492static void *cb_arg;
493static sigjmp_buf *cb_back; 493static jmp_buf *cb_back;
494 494
495int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) 495int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
496{ 496{
497 sigjmp_buf **switch_buf = switch_buf_ptr; 497 jmp_buf **switch_buf = switch_buf_ptr;
498 int n, enable; 498 int n, enable;
499 499
500 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 500 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
502 SIGVTALRM, -1); 502 SIGVTALRM, -1);
503 503
504 *fork_buf_ptr = &initial_jmpbuf; 504 *fork_buf_ptr = &initial_jmpbuf;
505 n = UML_SIGSETJMP(&initial_jmpbuf, enable); 505 n = UML_SETJMP(&initial_jmpbuf, enable);
506 switch(n){ 506 switch(n){
507 case INIT_JMP_NEW_THREAD: 507 case INIT_JMP_NEW_THREAD:
508 new_thread_proc((void *) stack, new_thread_handler); 508 new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
512 break; 512 break;
513 case INIT_JMP_CALLBACK: 513 case INIT_JMP_CALLBACK:
514 (*cb_proc)(cb_arg); 514 (*cb_proc)(cb_arg);
515 UML_SIGLONGJMP(cb_back, 1); 515 UML_LONGJMP(cb_back, 1);
516 break; 516 break;
517 case INIT_JMP_HALT: 517 case INIT_JMP_HALT:
518 kmalloc_ok = 0; 518 kmalloc_ok = 0;
@@ -523,12 +523,12 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
523 default: 523 default:
524 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 524 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
525 } 525 }
526 UML_SIGLONGJMP(*switch_buf, 1); 526 UML_LONGJMP(*switch_buf, 1);
527} 527}
528 528
529void initial_thread_cb_skas(void (*proc)(void *), void *arg) 529void initial_thread_cb_skas(void (*proc)(void *), void *arg)
530{ 530{
531 sigjmp_buf here; 531 jmp_buf here;
532 int enable; 532 int enable;
533 533
534 cb_proc = proc; 534 cb_proc = proc;
@@ -536,8 +536,8 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
536 cb_back = &here; 536 cb_back = &here;
537 537
538 block_signals(); 538 block_signals();
539 if(UML_SIGSETJMP(&here, enable) == 0) 539 if(UML_SETJMP(&here, enable) == 0)
540 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); 540 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
541 unblock_signals(); 541 unblock_signals();
542 542
543 cb_proc = NULL; 543 cb_proc = NULL;
@@ -548,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
548void halt_skas(void) 548void halt_skas(void)
549{ 549{
550 block_signals(); 550 block_signals();
551 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT); 551 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
552} 552}
553 553
554void reboot_skas(void) 554void reboot_skas(void)
555{ 555{
556 block_signals(); 556 block_signals();
557 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); 557 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
558} 558}
559 559
560void switch_mm_skas(struct mm_id *mm_idp) 560void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 387e26af301a..503148504009 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,29 +296,7 @@ static void __init check_ptrace(void)
296 check_sysemu(); 296 check_sysemu();
297} 297}
298 298
299extern int create_tmp_file(unsigned long long len); 299extern void check_tmpexec(void);
300
301static 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}
322 300
323void os_early_checks(void) 301void os_early_checks(void)
324{ 302{
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26f9828..90b29ae9af46 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@ void os_fill_handlinfo(struct kern_handlers h)
35 35
36void do_longjmp(void *b, int val) 36void do_longjmp(void *b, int val)
37{ 37{
38 sigjmp_buf *buf = b; 38 jmp_buf *buf = b;
39 39
40 UML_SIGLONGJMP(buf, val); 40 UML_LONGJMP(buf, val);
41} 41}
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66995df..e523719330b2 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
16 unsigned long *faddrp = (unsigned long *) fault_addr, ret; 16 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
17 int enable; 17 int enable;
18 18
19 sigjmp_buf jbuf; 19 jmp_buf jbuf;
20 *fault_catcher = &jbuf; 20 *fault_catcher = &jbuf;
21 if(UML_SIGSETJMP(&jbuf, enable) == 0){ 21 if(UML_SETJMP(&jbuf, enable) == 0){
22 (*op)(to, from, n); 22 (*op)(to, from, n);
23 ret = 0; 23 ret = 0;
24 *faulted_out = 0; 24 *faulted_out = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e2fdc8..c47a2a7ce70e 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@ void setup_hostinfo(void)
104int setjmp_wrapper(void (*proc)(void *, void *), ...) 104int setjmp_wrapper(void (*proc)(void *, void *), ...)
105{ 105{
106 va_list args; 106 va_list args;
107 sigjmp_buf buf; 107 jmp_buf buf;
108 int n; 108 int n;
109 109
110 n = sigsetjmp(buf, 1); 110 n = sigsetjmp(buf, 1);