diff options
Diffstat (limited to 'fs/binfmt_elf.c')
| -rw-r--r-- | fs/binfmt_elf.c | 43 |
1 files changed, 19 insertions, 24 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d0434406eaeb..6eb48e1446ec 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -84,7 +84,7 @@ static struct linux_binfmt elf_format = { | |||
| 84 | .min_coredump = ELF_EXEC_PAGESIZE | 84 | .min_coredump = ELF_EXEC_PAGESIZE |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) | 87 | #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) |
| 88 | 88 | ||
| 89 | static int set_brk(unsigned long start, unsigned long end) | 89 | static int set_brk(unsigned long start, unsigned long end) |
| 90 | { | 90 | { |
| @@ -394,7 +394,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
| 394 | * <= p_memsize so it's only necessary to check p_memsz. | 394 | * <= p_memsize so it's only necessary to check p_memsz. |
| 395 | */ | 395 | */ |
| 396 | k = load_addr + eppnt->p_vaddr; | 396 | k = load_addr + eppnt->p_vaddr; |
| 397 | if (k > TASK_SIZE || | 397 | if (BAD_ADDR(k) || |
| 398 | eppnt->p_filesz > eppnt->p_memsz || | 398 | eppnt->p_filesz > eppnt->p_memsz || |
| 399 | eppnt->p_memsz > TASK_SIZE || | 399 | eppnt->p_memsz > TASK_SIZE || |
| 400 | TASK_SIZE - eppnt->p_memsz < k) { | 400 | TASK_SIZE - eppnt->p_memsz < k) { |
| @@ -515,7 +515,8 @@ static unsigned long randomize_stack_top(unsigned long stack_top) | |||
| 515 | { | 515 | { |
| 516 | unsigned int random_variable = 0; | 516 | unsigned int random_variable = 0; |
| 517 | 517 | ||
| 518 | if (current->flags & PF_RANDOMIZE) { | 518 | if ((current->flags & PF_RANDOMIZE) && |
| 519 | !(current->personality & ADDR_NO_RANDOMIZE)) { | ||
| 519 | random_variable = get_random_int() & STACK_RND_MASK; | 520 | random_variable = get_random_int() & STACK_RND_MASK; |
| 520 | random_variable <<= PAGE_SHIFT; | 521 | random_variable <<= PAGE_SHIFT; |
| 521 | } | 522 | } |
| @@ -887,7 +888,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 887 | * allowed task size. Note that p_filesz must always be | 888 | * allowed task size. Note that p_filesz must always be |
| 888 | * <= p_memsz so it is only necessary to check p_memsz. | 889 | * <= p_memsz so it is only necessary to check p_memsz. |
| 889 | */ | 890 | */ |
| 890 | if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || | 891 | if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || |
| 891 | elf_ppnt->p_memsz > TASK_SIZE || | 892 | elf_ppnt->p_memsz > TASK_SIZE || |
| 892 | TASK_SIZE - elf_ppnt->p_memsz < k) { | 893 | TASK_SIZE - elf_ppnt->p_memsz < k) { |
| 893 | /* set_brk can never work. Avoid overflows. */ | 894 | /* set_brk can never work. Avoid overflows. */ |
| @@ -941,10 +942,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 941 | interpreter, | 942 | interpreter, |
| 942 | &interp_load_addr); | 943 | &interp_load_addr); |
| 943 | if (BAD_ADDR(elf_entry)) { | 944 | if (BAD_ADDR(elf_entry)) { |
| 944 | printk(KERN_ERR "Unable to load interpreter %.128s\n", | ||
| 945 | elf_interpreter); | ||
| 946 | force_sig(SIGSEGV, current); | 945 | force_sig(SIGSEGV, current); |
| 947 | retval = -ENOEXEC; /* Nobody gets to see this, but.. */ | 946 | retval = IS_ERR((void *)elf_entry) ? |
| 947 | (int)elf_entry : -EINVAL; | ||
| 948 | goto out_free_dentry; | 948 | goto out_free_dentry; |
| 949 | } | 949 | } |
| 950 | reloc_func_desc = interp_load_addr; | 950 | reloc_func_desc = interp_load_addr; |
| @@ -955,8 +955,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 955 | } else { | 955 | } else { |
| 956 | elf_entry = loc->elf_ex.e_entry; | 956 | elf_entry = loc->elf_ex.e_entry; |
| 957 | if (BAD_ADDR(elf_entry)) { | 957 | if (BAD_ADDR(elf_entry)) { |
| 958 | send_sig(SIGSEGV, current, 0); | 958 | force_sig(SIGSEGV, current); |
| 959 | retval = -ENOEXEC; /* Nobody gets to see this, but.. */ | 959 | retval = -EINVAL; |
| 960 | goto out_free_dentry; | 960 | goto out_free_dentry; |
| 961 | } | 961 | } |
| 962 | } | 962 | } |
| @@ -1038,10 +1038,8 @@ out_free_interp: | |||
| 1038 | out_free_file: | 1038 | out_free_file: |
| 1039 | sys_close(elf_exec_fileno); | 1039 | sys_close(elf_exec_fileno); |
| 1040 | out_free_fh: | 1040 | out_free_fh: |
| 1041 | if (files) { | 1041 | if (files) |
| 1042 | put_files_struct(current->files); | 1042 | reset_files_struct(current, files); |
| 1043 | current->files = files; | ||
| 1044 | } | ||
| 1045 | out_free_ph: | 1043 | out_free_ph: |
| 1046 | kfree(elf_phdata); | 1044 | kfree(elf_phdata); |
| 1047 | goto out; | 1045 | goto out; |
| @@ -1186,8 +1184,6 @@ static int maydump(struct vm_area_struct *vma) | |||
| 1186 | return 1; | 1184 | return 1; |
| 1187 | } | 1185 | } |
| 1188 | 1186 | ||
| 1189 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) | ||
| 1190 | |||
| 1191 | /* An ELF note in memory */ | 1187 | /* An ELF note in memory */ |
| 1192 | struct memelfnote | 1188 | struct memelfnote |
| 1193 | { | 1189 | { |
| @@ -1265,7 +1261,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs) | |||
| 1265 | return; | 1261 | return; |
| 1266 | } | 1262 | } |
| 1267 | 1263 | ||
| 1268 | static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) | 1264 | static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset) |
| 1269 | { | 1265 | { |
| 1270 | phdr->p_type = PT_NOTE; | 1266 | phdr->p_type = PT_NOTE; |
| 1271 | phdr->p_offset = offset; | 1267 | phdr->p_offset = offset; |
| @@ -1431,7 +1427,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1431 | int i; | 1427 | int i; |
| 1432 | struct vm_area_struct *vma; | 1428 | struct vm_area_struct *vma; |
| 1433 | struct elfhdr *elf = NULL; | 1429 | struct elfhdr *elf = NULL; |
| 1434 | off_t offset = 0, dataoff; | 1430 | loff_t offset = 0, dataoff; |
| 1435 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1431 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
| 1436 | int numnote; | 1432 | int numnote; |
| 1437 | struct memelfnote *notes = NULL; | 1433 | struct memelfnote *notes = NULL; |
| @@ -1483,20 +1479,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1483 | 1479 | ||
| 1484 | if (signr) { | 1480 | if (signr) { |
| 1485 | struct elf_thread_status *tmp; | 1481 | struct elf_thread_status *tmp; |
| 1486 | read_lock(&tasklist_lock); | 1482 | rcu_read_lock(); |
| 1487 | do_each_thread(g,p) | 1483 | do_each_thread(g,p) |
| 1488 | if (current->mm == p->mm && current != p) { | 1484 | if (current->mm == p->mm && current != p) { |
| 1489 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | 1485 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); |
| 1490 | if (!tmp) { | 1486 | if (!tmp) { |
| 1491 | read_unlock(&tasklist_lock); | 1487 | rcu_read_unlock(); |
| 1492 | goto cleanup; | 1488 | goto cleanup; |
| 1493 | } | 1489 | } |
| 1494 | INIT_LIST_HEAD(&tmp->list); | ||
| 1495 | tmp->thread = p; | 1490 | tmp->thread = p; |
| 1496 | list_add(&tmp->list, &thread_list); | 1491 | list_add(&tmp->list, &thread_list); |
| 1497 | } | 1492 | } |
| 1498 | while_each_thread(g,p); | 1493 | while_each_thread(g,p); |
| 1499 | read_unlock(&tasklist_lock); | 1494 | rcu_read_unlock(); |
| 1500 | list_for_each(t, &thread_list) { | 1495 | list_for_each(t, &thread_list) { |
| 1501 | struct elf_thread_status *tmp; | 1496 | struct elf_thread_status *tmp; |
| 1502 | int sz; | 1497 | int sz; |
| @@ -1664,11 +1659,11 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1664 | ELF_CORE_WRITE_EXTRA_DATA; | 1659 | ELF_CORE_WRITE_EXTRA_DATA; |
| 1665 | #endif | 1660 | #endif |
| 1666 | 1661 | ||
| 1667 | if ((off_t)file->f_pos != offset) { | 1662 | if (file->f_pos != offset) { |
| 1668 | /* Sanity check */ | 1663 | /* Sanity check */ |
| 1669 | printk(KERN_WARNING | 1664 | printk(KERN_WARNING |
| 1670 | "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", | 1665 | "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n", |
| 1671 | (off_t)file->f_pos, offset); | 1666 | file->f_pos, offset); |
| 1672 | } | 1667 | } |
| 1673 | 1668 | ||
| 1674 | end_coredump: | 1669 | end_coredump: |
