aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 08e4414b8374..4482a0673b15 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -148,6 +148,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
148 elf_addr_t *elf_info; 148 elf_addr_t *elf_info;
149 int ei_index = 0; 149 int ei_index = 0;
150 struct task_struct *tsk = current; 150 struct task_struct *tsk = current;
151 struct vm_area_struct *vma;
151 152
152 /* 153 /*
153 * If this architecture has a platform capability string, copy it 154 * If this architecture has a platform capability string, copy it
@@ -234,6 +235,15 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
234 sp = (elf_addr_t __user *)bprm->p; 235 sp = (elf_addr_t __user *)bprm->p;
235#endif 236#endif
236 237
238
239 /*
240 * Grow the stack manually; some architectures have a limit on how
241 * far ahead a user-space access may be in order to grow the stack.
242 */
243 vma = find_extend_vma(current->mm, bprm->p);
244 if (!vma)
245 return -EFAULT;
246
237 /* Now, let's put argc (and argv, envp if appropriate) on the stack */ 247 /* Now, let's put argc (and argv, envp if appropriate) on the stack */
238 if (__put_user(argc, sp++)) 248 if (__put_user(argc, sp++))
239 return -EFAULT; 249 return -EFAULT;
@@ -254,8 +264,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
254 size_t len; 264 size_t len;
255 if (__put_user((elf_addr_t)p, argv++)) 265 if (__put_user((elf_addr_t)p, argv++))
256 return -EFAULT; 266 return -EFAULT;
257 len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES); 267 len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
258 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES) 268 if (!len || len > MAX_ARG_STRLEN)
259 return 0; 269 return 0;
260 p += len; 270 p += len;
261 } 271 }
@@ -266,8 +276,8 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
266 size_t len; 276 size_t len;
267 if (__put_user((elf_addr_t)p, envp++)) 277 if (__put_user((elf_addr_t)p, envp++))
268 return -EFAULT; 278 return -EFAULT;
269 len = strnlen_user((void __user *)p, PAGE_SIZE*MAX_ARG_PAGES); 279 len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
270 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES) 280 if (!len || len > MAX_ARG_STRLEN)
271 return 0; 281 return 0;
272 p += len; 282 p += len;
273 } 283 }
@@ -777,10 +787,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
777 } 787 }
778 788
779 /* OK, This is the point of no return */ 789 /* OK, This is the point of no return */
780 current->mm->start_data = 0;
781 current->mm->end_data = 0;
782 current->mm->end_code = 0;
783 current->mm->mmap = NULL;
784 current->flags &= ~PF_FORKNOEXEC; 790 current->flags &= ~PF_FORKNOEXEC;
785 current->mm->def_flags = def_flags; 791 current->mm->def_flags = def_flags;
786 792
@@ -988,9 +994,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
988 994
989 compute_creds(bprm); 995 compute_creds(bprm);
990 current->flags &= ~PF_FORKNOEXEC; 996 current->flags &= ~PF_FORKNOEXEC;
991 create_elf_tables(bprm, &loc->elf_ex, 997 retval = create_elf_tables(bprm, &loc->elf_ex,
992 (interpreter_type == INTERPRETER_AOUT), 998 (interpreter_type == INTERPRETER_AOUT),
993 load_addr, interp_load_addr); 999 load_addr, interp_load_addr);
1000 if (retval < 0) {
1001 send_sig(SIGKILL, current, 0);
1002 goto out;
1003 }
994 /* N.B. passed_fileno might not be initialized? */ 1004 /* N.B. passed_fileno might not be initialized? */
995 if (interpreter_type == INTERPRETER_AOUT) 1005 if (interpreter_type == INTERPRETER_AOUT)
996 current->mm->arg_start += strlen(passed_fileno) + 1; 1006 current->mm->arg_start += strlen(passed_fileno) + 1;
@@ -1189,7 +1199,7 @@ static int dump_seek(struct file *file, loff_t off)
1189 * 1199 *
1190 * I think we should skip something. But I am not sure how. H.J. 1200 * I think we should skip something. But I am not sure how. H.J.
1191 */ 1201 */
1192static int maydump(struct vm_area_struct *vma) 1202static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
1193{ 1203{
1194 /* The vma can be set up to tell us the answer directly. */ 1204 /* The vma can be set up to tell us the answer directly. */
1195 if (vma->vm_flags & VM_ALWAYSDUMP) 1205 if (vma->vm_flags & VM_ALWAYSDUMP)
@@ -1199,15 +1209,19 @@ static int maydump(struct vm_area_struct *vma)
1199 if (vma->vm_flags & (VM_IO | VM_RESERVED)) 1209 if (vma->vm_flags & (VM_IO | VM_RESERVED))
1200 return 0; 1210 return 0;
1201 1211
1202 /* Dump shared memory only if mapped from an anonymous file. */ 1212 /* By default, dump shared memory if mapped from an anonymous file. */
1203 if (vma->vm_flags & VM_SHARED) 1213 if (vma->vm_flags & VM_SHARED) {
1204 return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0; 1214 if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0)
1215 return test_bit(MMF_DUMP_ANON_SHARED, &mm_flags);
1216 else
1217 return test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags);
1218 }
1205 1219
1206 /* If it hasn't been written to, don't write it out */ 1220 /* By default, if it hasn't been written to, don't write it out. */
1207 if (!vma->anon_vma) 1221 if (!vma->anon_vma)
1208 return 0; 1222 return test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags);
1209 1223
1210 return 1; 1224 return test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags);
1211} 1225}
1212 1226
1213/* An ELF note in memory */ 1227/* An ELF note in memory */
@@ -1499,6 +1513,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1499#endif 1513#endif
1500 int thread_status_size = 0; 1514 int thread_status_size = 0;
1501 elf_addr_t *auxv; 1515 elf_addr_t *auxv;
1516 unsigned long mm_flags;
1502#ifdef ELF_CORE_WRITE_EXTRA_NOTES 1517#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1503 int extra_notes_size; 1518 int extra_notes_size;
1504#endif 1519#endif
@@ -1642,6 +1657,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1642 1657
1643 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1658 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
1644 1659
1660 /*
1661 * We must use the same mm->flags while dumping core to avoid
1662 * inconsistency between the program headers and bodies, otherwise an
1663 * unusable core file can be generated.
1664 */
1665 mm_flags = current->mm->flags;
1666
1645 /* Write program headers for segments dump */ 1667 /* Write program headers for segments dump */
1646 for (vma = first_vma(current, gate_vma); vma != NULL; 1668 for (vma = first_vma(current, gate_vma); vma != NULL;
1647 vma = next_vma(vma, gate_vma)) { 1669 vma = next_vma(vma, gate_vma)) {
@@ -1654,7 +1676,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1654 phdr.p_offset = offset; 1676 phdr.p_offset = offset;
1655 phdr.p_vaddr = vma->vm_start; 1677 phdr.p_vaddr = vma->vm_start;
1656 phdr.p_paddr = 0; 1678 phdr.p_paddr = 0;
1657 phdr.p_filesz = maydump(vma) ? sz : 0; 1679 phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
1658 phdr.p_memsz = sz; 1680 phdr.p_memsz = sz;
1659 offset += phdr.p_filesz; 1681 offset += phdr.p_filesz;
1660 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1682 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1698,7 +1720,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1698 vma = next_vma(vma, gate_vma)) { 1720 vma = next_vma(vma, gate_vma)) {
1699 unsigned long addr; 1721 unsigned long addr;
1700 1722
1701 if (!maydump(vma)) 1723 if (!maydump(vma, mm_flags))
1702 continue; 1724 continue;
1703 1725
1704 for (addr = vma->vm_start; 1726 for (addr = vma->vm_start;