git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
revert #include statement to be just like imported FC+VS code
[linux-2.6.git]
/
fs
/
binfmt_aout.c
diff --git
a/fs/binfmt_aout.c
b/fs/binfmt_aout.c
index
ee8feb0
..
be6dfe8
100644
(file)
--- a/
fs/binfmt_aout.c
+++ b/
fs/binfmt_aout.c
@@
-34,8
+34,6
@@
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(struct file*);
static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
static int load_aout_library(struct file*);
static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
-extern void dump_thread(struct pt_regs *, struct user *);
-
static struct linux_binfmt aout_format = {
.module = THIS_MODULE,
.load_binary = load_aout_binary,
static struct linux_binfmt aout_format = {
.module = THIS_MODULE,
.load_binary = load_aout_binary,
@@
-44,13
+42,21
@@
static struct linux_binfmt aout_format = {
.min_coredump = PAGE_SIZE
};
.min_coredump = PAGE_SIZE
};
-static void set_brk(unsigned long start, unsigned long end)
+#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
+
+static int set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
{
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
- if (end <= start)
- return;
- do_brk(start, end - start);
+ if (end > start) {
+ unsigned long addr;
+ down_write(¤t->mm->mmap_sem);
+ addr = do_brk(start, end - start);
+ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+ return 0;
}
/*
}
/*
@@
-108,7
+114,7
@@
static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
set_fs(KERNEL_DS);
has_dumped = 1;
current->flags |= PF_DUMPCORE;
set_fs(KERNEL_DS);
has_dumped = 1;
current->flags |= PF_DUMPCORE;
- strncpy(dump.u_comm, current->comm, sizeof(
current->
comm));
+ strncpy(dump.u_comm, current->comm, sizeof(
dump.u_
comm));
#ifndef __sparc__
dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
#endif
#ifndef __sparc__
dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
#endif
@@
-119,36
+125,36
@@
static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
if we wrote the stack, but not the data area. */
#ifdef __sparc__
if ((dump.u_dsize+dump.u_ssize) >
if we wrote the stack, but not the data area. */
#ifdef __sparc__
if ((dump.u_dsize+dump.u_ssize) >
- current->rlim[RLIMIT_CORE].rlim_cur)
+ current->
signal->
rlim[RLIMIT_CORE].rlim_cur)
dump.u_dsize = 0;
#else
if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
dump.u_dsize = 0;
#else
if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
- current->rlim[RLIMIT_CORE].rlim_cur)
+ current->
signal->
rlim[RLIMIT_CORE].rlim_cur)
dump.u_dsize = 0;
#endif
/* Make sure we have enough room to write the stack and data areas. */
#ifdef __sparc__
if ((dump.u_ssize) >
dump.u_dsize = 0;
#endif
/* Make sure we have enough room to write the stack and data areas. */
#ifdef __sparc__
if ((dump.u_ssize) >
- current->rlim[RLIMIT_CORE].rlim_cur)
+ current->
signal->
rlim[RLIMIT_CORE].rlim_cur)
dump.u_ssize = 0;
#else
if ((dump.u_ssize+1) * PAGE_SIZE >
dump.u_ssize = 0;
#else
if ((dump.u_ssize+1) * PAGE_SIZE >
- current->rlim[RLIMIT_CORE].rlim_cur)
+ current->
signal->
rlim[RLIMIT_CORE].rlim_cur)
dump.u_ssize = 0;
#endif
/* make sure we actually have a data and stack area to dump */
set_fs(USER_DS);
#ifdef __sparc__
dump.u_ssize = 0;
#endif
/* make sure we actually have a data and stack area to dump */
set_fs(USER_DS);
#ifdef __sparc__
- if (
verify_area
(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
+ if (
!access_ok
(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
dump.u_dsize = 0;
dump.u_dsize = 0;
- if (
verify_area
(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
+ if (
!access_ok
(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
dump.u_ssize = 0;
#else
dump.u_ssize = 0;
#else
- if (
verify_area
(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+ if (
!access_ok
(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
dump.u_dsize = 0;
dump.u_dsize = 0;
- if (
verify_area
(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+ if (
!access_ok
(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
dump.u_ssize = 0;
#endif
dump.u_ssize = 0;
#endif
@@
-269,17
+275,24
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ i_size_read(bprm->file->f_
path.
dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
return -ENOEXEC;
}
+ /*
+ * Requires a mmap handler. This prevents people from using a.out
+ * as part of an exploit attack against /proc-related vulnerabilities.
+ */
+ if (!bprm->file->f_op || !bprm->file->f_op->mmap)
+ return -ENOEXEC;
+
fd_offset = N_TXTOFF(ex);
/* Check initial limits. This avoids letting people circumvent
* size limits imposed on them by creating programs with large
* arrays in the data or bss.
*/
fd_offset = N_TXTOFF(ex);
/* Check initial limits. This avoids letting people circumvent
* size limits imposed on them by creating programs with large
* arrays in the data or bss.
*/
- rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+ rlim = current->
signal->
rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (ex.a_data + ex.a_bss > rlim)
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (ex.a_data + ex.a_bss > rlim)
@@
-308,11
+321,9
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(current->mm->start_data = N_DATADDR(ex));
current->mm->brk = ex.a_bss +
(current->mm->start_brk = N_BSSADDR(ex));
(current->mm->start_data = N_DATADDR(ex));
current->mm->brk = ex.a_bss +
(current->mm->start_brk = N_BSSADDR(ex));
- current->mm->free_area_cache = TASK_UNMAPPED_BASE;
- /* unlimited stack is larger than TASK_SIZE */
- current->mm->non_executable_cache = current->mm->mmap_top;
- // current->mm->rss = 0;
- vx_rsspages_sub(current->mm, current->mm->rss);
+ current->mm->free_area_cache = current->mm->mmap_base;
+ current->mm->cached_hole_size = 0;
+
current->mm->mmap = NULL;
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
current->mm->mmap = NULL;
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
@@
-321,10
+332,14
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
loff_t pos = fd_offset;
/* Fuck me plenty... */
/* <AOL></AOL> */
loff_t pos = fd_offset;
/* Fuck me plenty... */
/* <AOL></AOL> */
+ down_write(¤t->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text);
error = do_brk(N_TXTADDR(ex), ex.a_text);
+ up_write(¤t->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
ex.a_text, &pos);
bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
ex.a_text, &pos);
+ down_write(¤t->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data);
error = do_brk(N_DATADDR(ex), ex.a_data);
+ up_write(¤t->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
ex.a_data, &pos);
goto beyond_if;
bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
ex.a_data, &pos);
goto beyond_if;
@@
-344,14
+359,16
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
pos = 32;
map_size = ex.a_text+ex.a_data;
#endif
pos = 32;
map_size = ex.a_text+ex.a_data;
#endif
-
+ down_write(¤t->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size);
error = do_brk(text_addr & PAGE_MASK, map_size);
+ up_write(¤t->mm->mmap_sem);
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
return error;
}
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
return error;
}
- error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
+ error = bprm->file->f_op->read(bprm->file,
+ (char __user *)text_addr,
ex.a_text+ex.a_data, &pos);
if ((signed long)error < 0) {
send_sig(SIGKILL, current, 0);
ex.a_text+ex.a_data, &pos);
if ((signed long)error < 0) {
send_sig(SIGKILL, current, 0);
@@
-373,14
+390,17
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
printk(KERN_WARNING
"fd_offset is not page aligned. Please convert program: %s\n",
{
printk(KERN_WARNING
"fd_offset is not page aligned. Please convert program: %s\n",
- bprm->file->f_dentry->d_name.name);
+ bprm->file->f_
path.
dentry->d_name.name);
error_time = jiffies;
}
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset;
error_time = jiffies;
}
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset;
+ down_write(¤t->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
- bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
flush_icache_range((unsigned long) N_TXTADDR(ex),
(unsigned long) N_TXTADDR(ex) +
ex.a_text+ex.a_data, &pos);
flush_icache_range((unsigned long) N_TXTADDR(ex),
(unsigned long) N_TXTADDR(ex) +
@@
-414,9
+434,13
@@
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
beyond_if:
set_binfmt(&aout_format);
beyond_if:
set_binfmt(&aout_format);
- set_brk(current->mm->start_brk, current->mm->brk);
+ retval = set_brk(current->mm->start_brk, current->mm->brk);
+ if (retval < 0) {
+ send_sig(SIGKILL, current, 0);
+ return retval;
+ }
- retval = setup_arg_pages(bprm, EXSTACK_DEFAULT);
+ retval = setup_arg_pages(bprm,
STACK_TOP,
EXSTACK_DEFAULT);
if (retval < 0) {
/* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0);
if (retval < 0) {
/* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0);
@@
-429,12
+453,6
@@
beyond_if:
regs->gp = ex.a_gpvalue;
#endif
start_thread(regs, ex.a_entry, current->mm->start_stack);
regs->gp = ex.a_gpvalue;
#endif
start_thread(regs, ex.a_entry, current->mm->start_stack);
- if (unlikely(current->ptrace & PT_PTRACED)) {
- if (current->ptrace & PT_TRACE_EXEC)
- ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
- else
- send_sig(SIGTRAP, current, 0);
- }
return 0;
}
return 0;
}
@@
-446,7
+464,7
@@
static int load_aout_library(struct file *file)
int retval;
struct exec ex;
int retval;
struct exec ex;
- inode = file->f_dentry->d_inode;
+ inode = file->f_
path.
dentry->d_inode;
retval = -ENOEXEC;
error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
retval = -ENOEXEC;
error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
@@
-460,6
+478,13
@@
static int load_aout_library(struct file *file)
goto out;
}
goto out;
}
+ /*
+ * Requires a mmap handler. This prevents people from using a.out
+ * as part of an exploit attack against /proc-related vulnerabilities.
+ */
+ if (!file->f_op || !file->f_op->mmap)
+ goto out;
+
if (N_FLAGS(ex))
goto out;
if (N_FLAGS(ex))
goto out;
@@
-476,13
+501,14
@@
static int load_aout_library(struct file *file)
{
printk(KERN_WARNING
"N_TXTOFF is not page aligned. Please convert library: %s\n",
{
printk(KERN_WARNING
"N_TXTOFF is not page aligned. Please convert library: %s\n",
- file->f_dentry->d_name.name);
+ file->f_
path.
dentry->d_name.name);
error_time = jiffies;
}
error_time = jiffies;
}
-
+ down_write(¤t->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+ up_write(¤t->mm->mmap_sem);
- file->f_op->read(file, (char *)start_addr,
+ file->f_op->read(file, (char
__user
*)start_addr,
ex.a_text + ex.a_data, &pos);
flush_icache_range((unsigned long) start_addr,
(unsigned long) start_addr + ex.a_text + ex.a_data);
ex.a_text + ex.a_data, &pos);
flush_icache_range((unsigned long) start_addr,
(unsigned long) start_addr + ex.a_text + ex.a_data);
@@
-504,7
+530,9
@@
static int load_aout_library(struct file *file)
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
+ down_write(¤t->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len);
error = do_brk(start_addr + len, bss - len);
+ up_write(¤t->mm->mmap_sem);
retval = error;
if (error != start_addr + len)
goto out;
retval = error;
if (error != start_addr + len)
goto out;