diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 79 |
1 files changed, 67 insertions, 12 deletions
@@ -361,13 +361,13 @@ err: | |||
361 | /* | 361 | /* |
362 | * count() counts the number of strings in array ARGV. | 362 | * count() counts the number of strings in array ARGV. |
363 | */ | 363 | */ |
364 | static int count(char __user * __user * argv, int max) | 364 | static int count(const char __user * const __user * argv, int max) |
365 | { | 365 | { |
366 | int i = 0; | 366 | int i = 0; |
367 | 367 | ||
368 | if (argv != NULL) { | 368 | if (argv != NULL) { |
369 | for (;;) { | 369 | for (;;) { |
370 | char __user * p; | 370 | const char __user * p; |
371 | 371 | ||
372 | if (get_user(p, argv)) | 372 | if (get_user(p, argv)) |
373 | return -EFAULT; | 373 | return -EFAULT; |
@@ -376,6 +376,9 @@ static int count(char __user * __user * argv, int max) | |||
376 | argv++; | 376 | argv++; |
377 | if (i++ >= max) | 377 | if (i++ >= max) |
378 | return -E2BIG; | 378 | return -E2BIG; |
379 | |||
380 | if (fatal_signal_pending(current)) | ||
381 | return -ERESTARTNOHAND; | ||
379 | cond_resched(); | 382 | cond_resched(); |
380 | } | 383 | } |
381 | } | 384 | } |
@@ -387,7 +390,7 @@ static int count(char __user * __user * argv, int max) | |||
387 | * processes's memory to the new process's stack. The call to get_user_pages() | 390 | * processes's memory to the new process's stack. The call to get_user_pages() |
388 | * ensures the destination page is created and not swapped out. | 391 | * ensures the destination page is created and not swapped out. |
389 | */ | 392 | */ |
390 | static int copy_strings(int argc, char __user * __user * argv, | 393 | static int copy_strings(int argc, const char __user *const __user *argv, |
391 | struct linux_binprm *bprm) | 394 | struct linux_binprm *bprm) |
392 | { | 395 | { |
393 | struct page *kmapped_page = NULL; | 396 | struct page *kmapped_page = NULL; |
@@ -396,7 +399,7 @@ static int copy_strings(int argc, char __user * __user * argv, | |||
396 | int ret; | 399 | int ret; |
397 | 400 | ||
398 | while (argc-- > 0) { | 401 | while (argc-- > 0) { |
399 | char __user *str; | 402 | const char __user *str; |
400 | int len; | 403 | int len; |
401 | unsigned long pos; | 404 | unsigned long pos; |
402 | 405 | ||
@@ -419,6 +422,12 @@ static int copy_strings(int argc, char __user * __user * argv, | |||
419 | while (len > 0) { | 422 | while (len > 0) { |
420 | int offset, bytes_to_copy; | 423 | int offset, bytes_to_copy; |
421 | 424 | ||
425 | if (fatal_signal_pending(current)) { | ||
426 | ret = -ERESTARTNOHAND; | ||
427 | goto out; | ||
428 | } | ||
429 | cond_resched(); | ||
430 | |||
422 | offset = pos % PAGE_SIZE; | 431 | offset = pos % PAGE_SIZE; |
423 | if (offset == 0) | 432 | if (offset == 0) |
424 | offset = PAGE_SIZE; | 433 | offset = PAGE_SIZE; |
@@ -470,12 +479,13 @@ out: | |||
470 | /* | 479 | /* |
471 | * Like copy_strings, but get argv and its values from kernel memory. | 480 | * Like copy_strings, but get argv and its values from kernel memory. |
472 | */ | 481 | */ |
473 | int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm) | 482 | int copy_strings_kernel(int argc, const char *const *argv, |
483 | struct linux_binprm *bprm) | ||
474 | { | 484 | { |
475 | int r; | 485 | int r; |
476 | mm_segment_t oldfs = get_fs(); | 486 | mm_segment_t oldfs = get_fs(); |
477 | set_fs(KERNEL_DS); | 487 | set_fs(KERNEL_DS); |
478 | r = copy_strings(argc, (char __user * __user *)argv, bprm); | 488 | r = copy_strings(argc, (const char __user *const __user *)argv, bprm); |
479 | set_fs(oldfs); | 489 | set_fs(oldfs); |
480 | return r; | 490 | return r; |
481 | } | 491 | } |
@@ -593,6 +603,11 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
593 | #else | 603 | #else |
594 | stack_top = arch_align_stack(stack_top); | 604 | stack_top = arch_align_stack(stack_top); |
595 | stack_top = PAGE_ALIGN(stack_top); | 605 | stack_top = PAGE_ALIGN(stack_top); |
606 | |||
607 | if (unlikely(stack_top < mmap_min_addr) || | ||
608 | unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr)) | ||
609 | return -ENOMEM; | ||
610 | |||
596 | stack_shift = vma->vm_end - stack_top; | 611 | stack_shift = vma->vm_end - stack_top; |
597 | 612 | ||
598 | bprm->p -= stack_shift; | 613 | bprm->p -= stack_shift; |
@@ -997,7 +1012,7 @@ EXPORT_SYMBOL(flush_old_exec); | |||
997 | void setup_new_exec(struct linux_binprm * bprm) | 1012 | void setup_new_exec(struct linux_binprm * bprm) |
998 | { | 1013 | { |
999 | int i, ch; | 1014 | int i, ch; |
1000 | char * name; | 1015 | const char *name; |
1001 | char tcomm[sizeof(current->comm)]; | 1016 | char tcomm[sizeof(current->comm)]; |
1002 | 1017 | ||
1003 | arch_pick_mmap_layout(current->mm); | 1018 | arch_pick_mmap_layout(current->mm); |
@@ -1117,7 +1132,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) | |||
1117 | bprm->unsafe = tracehook_unsafe_exec(p); | 1132 | bprm->unsafe = tracehook_unsafe_exec(p); |
1118 | 1133 | ||
1119 | n_fs = 1; | 1134 | n_fs = 1; |
1120 | write_lock(&p->fs->lock); | 1135 | spin_lock(&p->fs->lock); |
1121 | rcu_read_lock(); | 1136 | rcu_read_lock(); |
1122 | for (t = next_thread(p); t != p; t = next_thread(t)) { | 1137 | for (t = next_thread(p); t != p; t = next_thread(t)) { |
1123 | if (t->fs == p->fs) | 1138 | if (t->fs == p->fs) |
@@ -1134,7 +1149,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) | |||
1134 | res = 1; | 1149 | res = 1; |
1135 | } | 1150 | } |
1136 | } | 1151 | } |
1137 | write_unlock(&p->fs->lock); | 1152 | spin_unlock(&p->fs->lock); |
1138 | 1153 | ||
1139 | return res; | 1154 | return res; |
1140 | } | 1155 | } |
@@ -1316,9 +1331,9 @@ EXPORT_SYMBOL(search_binary_handler); | |||
1316 | /* | 1331 | /* |
1317 | * sys_execve() executes a new program. | 1332 | * sys_execve() executes a new program. |
1318 | */ | 1333 | */ |
1319 | int do_execve(char * filename, | 1334 | int do_execve(const char * filename, |
1320 | char __user *__user *argv, | 1335 | const char __user *const __user *argv, |
1321 | char __user *__user *envp, | 1336 | const char __user *const __user *envp, |
1322 | struct pt_regs * regs) | 1337 | struct pt_regs * regs) |
1323 | { | 1338 | { |
1324 | struct linux_binprm *bprm; | 1339 | struct linux_binprm *bprm; |
@@ -1999,3 +2014,43 @@ fail_creds: | |||
1999 | fail: | 2014 | fail: |
2000 | return; | 2015 | return; |
2001 | } | 2016 | } |
2017 | |||
2018 | /* | ||
2019 | * Core dumping helper functions. These are the only things you should | ||
2020 | * do on a core-file: use only these functions to write out all the | ||
2021 | * necessary info. | ||
2022 | */ | ||
2023 | int dump_write(struct file *file, const void *addr, int nr) | ||
2024 | { | ||
2025 | return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; | ||
2026 | } | ||
2027 | EXPORT_SYMBOL(dump_write); | ||
2028 | |||
2029 | int dump_seek(struct file *file, loff_t off) | ||
2030 | { | ||
2031 | int ret = 1; | ||
2032 | |||
2033 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { | ||
2034 | if (file->f_op->llseek(file, off, SEEK_CUR) < 0) | ||
2035 | return 0; | ||
2036 | } else { | ||
2037 | char *buf = (char *)get_zeroed_page(GFP_KERNEL); | ||
2038 | |||
2039 | if (!buf) | ||
2040 | return 0; | ||
2041 | while (off > 0) { | ||
2042 | unsigned long n = off; | ||
2043 | |||
2044 | if (n > PAGE_SIZE) | ||
2045 | n = PAGE_SIZE; | ||
2046 | if (!dump_write(file, buf, n)) { | ||
2047 | ret = 0; | ||
2048 | break; | ||
2049 | } | ||
2050 | off -= n; | ||
2051 | } | ||
2052 | free_page((unsigned long)buf); | ||
2053 | } | ||
2054 | return ret; | ||
2055 | } | ||
2056 | EXPORT_SYMBOL(dump_seek); | ||