diff options
Diffstat (limited to 'arch/um/os-Linux')
| -rw-r--r-- | arch/um/os-Linux/mem.c | 118 | ||||
| -rw-r--r-- | arch/um/os-Linux/process.c | 8 | ||||
| -rw-r--r-- | arch/um/os-Linux/skas/process.c | 36 | ||||
| -rw-r--r-- | arch/um/os-Linux/start_up.c | 24 | ||||
| -rw-r--r-- | arch/um/os-Linux/trap.c | 4 | ||||
| -rw-r--r-- | arch/um/os-Linux/uaccess.c | 4 | ||||
| -rw-r--r-- | arch/um/os-Linux/util.c | 2 |
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 | ||
| 23 | static char *default_tmpdir = "/tmp"; | ||
| 22 | static char *tempdir = NULL; | 24 | static char *tempdir = NULL; |
| 23 | 25 | ||
| 24 | static void __init find_tempdir(void) | 26 | static 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 | */ | ||
| 56 | static 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 | |||
| 76 | static 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 | */ | ||
| 88 | static 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 | |||
| 119 | err: | ||
| 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 | |||
| 127 | found: | ||
| 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 | |||
| 235 | void 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 | ||
| 196 | int os_drop_memory(void *addr, int length) | 196 | int 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 | ||
| 267 | int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) | 267 | int 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 | ||
| 467 | void thread_wait(void *sw, void *fb) | 467 | void 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 | ||
| 478 | void switch_threads(void *me, void *next) | 478 | void 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 | ||
| 488 | static sigjmp_buf initial_jmpbuf; | 488 | static jmp_buf initial_jmpbuf; |
| 489 | 489 | ||
| 490 | /* XXX Make these percpu */ | 490 | /* XXX Make these percpu */ |
| 491 | static void (*cb_proc)(void *arg); | 491 | static void (*cb_proc)(void *arg); |
| 492 | static void *cb_arg; | 492 | static void *cb_arg; |
| 493 | static sigjmp_buf *cb_back; | 493 | static jmp_buf *cb_back; |
| 494 | 494 | ||
| 495 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | 495 | int 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 | ||
| 529 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 529 | void 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) | |||
| 548 | void halt_skas(void) | 548 | void 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 | ||
| 554 | void reboot_skas(void) | 554 | void 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 | ||
| 560 | void switch_mm_skas(struct mm_id *mm_idp) | 560 | void 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 | ||
| 299 | extern int create_tmp_file(unsigned long long len); | 299 | extern void check_tmpexec(void); |
| 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 | } | ||
| 322 | 300 | ||
| 323 | void os_early_checks(void) | 301 | void 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 | ||
| 36 | void do_longjmp(void *b, int val) | 36 | void 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) | |||
| 104 | int setjmp_wrapper(void (*proc)(void *, void *), ...) | 104 | int 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); |
