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 a27e42bf3400..ba24cb2ff6ce 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 }
@@ -826,10 +836,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
826 } 836 }
827 837
828 /* OK, This is the point of no return */ 838 /* OK, This is the point of no return */
829 current->mm->start_data = 0;
830 current->mm->end_data = 0;
831 current->mm->end_code = 0;
832 current->mm->mmap = NULL;
833 current->flags &= ~PF_FORKNOEXEC; 839 current->flags &= ~PF_FORKNOEXEC;
834 current->mm->def_flags = def_flags; 840 current->mm->def_flags = def_flags;
835 841
@@ -1051,9 +1057,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
1051 1057
1052 compute_creds(bprm); 1058 compute_creds(bprm);
1053 current->flags &= ~PF_FORKNOEXEC; 1059 current->flags &= ~PF_FORKNOEXEC;
1054 create_elf_tables(bprm, &loc->elf_ex, 1060 retval = create_elf_tables(bprm, &loc->elf_ex,
1055 (interpreter_type == INTERPRETER_AOUT), 1061 (interpreter_type == INTERPRETER_AOUT),
1056 load_addr, interp_load_addr); 1062 load_addr, interp_load_addr);
1063 if (retval < 0) {
1064 send_sig(SIGKILL, current, 0);
1065 goto out;
1066 }
1057 /* N.B. passed_fileno might not be initialized? */ 1067 /* N.B. passed_fileno might not be initialized? */
1058 if (interpreter_type == INTERPRETER_AOUT) 1068 if (interpreter_type == INTERPRETER_AOUT)
1059 current->mm->arg_start += strlen(passed_fileno) + 1; 1069 current->mm->arg_start += strlen(passed_fileno) + 1;
@@ -1252,7 +1262,7 @@ static int dump_seek(struct file *file, loff_t off)
1252 * 1262 *
1253 * I think we should skip something. But I am not sure how. H.J. 1263 * I think we should skip something. But I am not sure how. H.J.
1254 */ 1264 */
1255static int maydump(struct vm_area_struct *vma) 1265static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
1256{ 1266{
1257 /* The vma can be set up to tell us the answer directly. */ 1267 /* The vma can be set up to tell us the answer directly. */
1258 if (vma->vm_flags & VM_ALWAYSDUMP) 1268 if (vma->vm_flags & VM_ALWAYSDUMP)
@@ -1262,15 +1272,19 @@ static int maydump(struct vm_area_struct *vma)
1262 if (vma->vm_flags & (VM_IO | VM_RESERVED)) 1272 if (vma->vm_flags & (VM_IO | VM_RESERVED))
1263 return 0; 1273 return 0;
1264 1274
1265 /* Dump shared memory only if mapped from an anonymous file. */ 1275 /* By default, dump shared memory if mapped from an anonymous file. */
1266 if (vma->vm_flags & VM_SHARED) 1276 if (vma->vm_flags & VM_SHARED) {
1267 return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0; 1277 if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0)
1278 return test_bit(MMF_DUMP_ANON_SHARED, &mm_flags);
1279 else
1280 return test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags);
1281 }
1268 1282
1269 /* If it hasn't been written to, don't write it out */ 1283 /* By default, if it hasn't been written to, don't write it out. */
1270 if (!vma->anon_vma) 1284 if (!vma->anon_vma)
1271 return 0; 1285 return test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags);
1272 1286
1273 return 1; 1287 return test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags);
1274} 1288}
1275 1289
1276/* An ELF note in memory */ 1290/* An ELF note in memory */
@@ -1562,6 +1576,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1562#endif 1576#endif
1563 int thread_status_size = 0; 1577 int thread_status_size = 0;
1564 elf_addr_t *auxv; 1578 elf_addr_t *auxv;
1579 unsigned long mm_flags;
1565#ifdef ELF_CORE_WRITE_EXTRA_NOTES 1580#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1566 int extra_notes_size; 1581 int extra_notes_size;
1567#endif 1582#endif
@@ -1705,6 +1720,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1705 1720
1706 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1721 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
1707 1722
1723 /*
1724 * We must use the same mm->flags while dumping core to avoid
1725 * inconsistency between the program headers and bodies, otherwise an
1726 * unusable core file can be generated.
1727 */
1728 mm_flags = current->mm->flags;
1729
1708 /* Write program headers for segments dump */ 1730 /* Write program headers for segments dump */
1709 for (vma = first_vma(current, gate_vma); vma != NULL; 1731 for (vma = first_vma(current, gate_vma); vma != NULL;
1710 vma = next_vma(vma, gate_vma)) { 1732 vma = next_vma(vma, gate_vma)) {
@@ -1717,7 +1739,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1717 phdr.p_offset = offset; 1739 phdr.p_offset = offset;
1718 phdr.p_vaddr = vma->vm_start; 1740 phdr.p_vaddr = vma->vm_start;
1719 phdr.p_paddr = 0; 1741 phdr.p_paddr = 0;
1720 phdr.p_filesz = maydump(vma) ? sz : 0; 1742 phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
1721 phdr.p_memsz = sz; 1743 phdr.p_memsz = sz;
1722 offset += phdr.p_filesz; 1744 offset += phdr.p_filesz;
1723 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1745 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1761,7 +1783,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1761 vma = next_vma(vma, gate_vma)) { 1783 vma = next_vma(vma, gate_vma)) {
1762 unsigned long addr; 1784 unsigned long addr;
1763 1785
1764 if (!maydump(vma)) 1786 if (!maydump(vma, mm_flags))
1765 continue; 1787 continue;
1766 1788
1767 for (addr = vma->vm_start; 1789 for (addr = vma->vm_start;