summaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c43
1 files changed, 19 insertions, 24 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d0434406eae..6eb48e1446e 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -84,7 +84,7 @@ static struct linux_binfmt elf_format = {
.min_coredump = ELF_EXEC_PAGESIZE
};
-#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
+#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
static int set_brk(unsigned long start, unsigned long end)
{
@@ -394,7 +394,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
* <= p_memsize so it's only necessary to check p_memsz.
*/
k = load_addr + eppnt->p_vaddr;
- if (k > TASK_SIZE ||
+ if (BAD_ADDR(k) ||
eppnt->p_filesz > eppnt->p_memsz ||
eppnt->p_memsz > TASK_SIZE ||
TASK_SIZE - eppnt->p_memsz < k) {
@@ -515,7 +515,8 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
{
unsigned int random_variable = 0;
- if (current->flags & PF_RANDOMIZE) {
+ if ((current->flags & PF_RANDOMIZE) &&
+ !(current->personality & ADDR_NO_RANDOMIZE)) {
random_variable = get_random_int() & STACK_RND_MASK;
random_variable <<= PAGE_SHIFT;
}
@@ -887,7 +888,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
- if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
+ if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
elf_ppnt->p_memsz > TASK_SIZE ||
TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */
@@ -941,10 +942,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
interpreter,
&interp_load_addr);
if (BAD_ADDR(elf_entry)) {
- printk(KERN_ERR "Unable to load interpreter %.128s\n",
- elf_interpreter);
force_sig(SIGSEGV, current);
- retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+ retval = IS_ERR((void *)elf_entry) ?
+ (int)elf_entry : -EINVAL;
goto out_free_dentry;
}
reloc_func_desc = interp_load_addr;
@@ -955,8 +955,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
} else {
elf_entry = loc->elf_ex.e_entry;
if (BAD_ADDR(elf_entry)) {
- send_sig(SIGSEGV, current, 0);
- retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+ force_sig(SIGSEGV, current);
+ retval = -EINVAL;
goto out_free_dentry;
}
}
@@ -1038,10 +1038,8 @@ out_free_interp:
out_free_file:
sys_close(elf_exec_fileno);
out_free_fh:
- if (files) {
- put_files_struct(current->files);
- current->files = files;
- }
+ if (files)
+ reset_files_struct(current, files);
out_free_ph:
kfree(elf_phdata);
goto out;
@@ -1186,8 +1184,6 @@ static int maydump(struct vm_area_struct *vma)
return 1;
}
-#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-
/* An ELF note in memory */
struct memelfnote
{
@@ -1265,7 +1261,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs)
return;
}
-static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
+static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
{
phdr->p_type = PT_NOTE;
phdr->p_offset = offset;
@@ -1431,7 +1427,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
int i;
struct vm_area_struct *vma;
struct elfhdr *elf = NULL;
- off_t offset = 0, dataoff;
+ loff_t offset = 0, dataoff;
unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
int numnote;
struct memelfnote *notes = NULL;
@@ -1483,20 +1479,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
if (signr) {
struct elf_thread_status *tmp;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
do_each_thread(g,p)
if (current->mm == p->mm && current != p) {
tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
if (!tmp) {
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
goto cleanup;
}
- INIT_LIST_HEAD(&tmp->list);
tmp->thread = p;
list_add(&tmp->list, &thread_list);
}
while_each_thread(g,p);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
list_for_each(t, &thread_list) {
struct elf_thread_status *tmp;
int sz;
@@ -1664,11 +1659,11 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
ELF_CORE_WRITE_EXTRA_DATA;
#endif
- if ((off_t)file->f_pos != offset) {
+ if (file->f_pos != offset) {
/* Sanity check */
printk(KERN_WARNING
- "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
- (off_t)file->f_pos, offset);
+ "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
+ file->f_pos, offset);
}
end_coredump: