projects
/
linux-2.6-block.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
fs/sysv: dereferencing ERR_PTR()
[linux-2.6-block.git]
/
fs
/
exec.c
diff --git
a/fs/exec.c
b/fs/exec.c
index cce6bbdbdbb11705afbe6c729007ede3b8714e92..e6e94c626c2cbebb7699597271a953b65e611e6e 100644
(file)
--- a/
fs/exec.c
+++ b/
fs/exec.c
@@
-195,7
+195,7
@@
static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
* to work from.
*/
rlim = current->signal->rlim;
* to work from.
*/
rlim = current->signal->rlim;
- if (size >
rlim[RLIMIT_STACK].rlim_cur
/ 4) {
+ if (size >
ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)
/ 4) {
put_page(page);
return NULL;
}
put_page(page);
return NULL;
}
@@
-246,6
+246,7
@@
static int __bprm_mm_init(struct linux_binprm *bprm)
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_STACK_FLAGS;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_STACK_FLAGS;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
err = insert_vm_struct(mm, vma);
if (err)
goto err;
err = insert_vm_struct(mm, vma);
if (err)
goto err;
@@
-516,7
+517,8
@@
static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
/*
* cover the whole range: [new_start, old_end)
*/
/*
* cover the whole range: [new_start, old_end)
*/
- vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL);
+ if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
+ return -ENOMEM;
/*
* move the page tables downwards, on failure we rely on
/*
* move the page tables downwards, on failure we rely on
@@
-547,15
+549,13
@@
static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
tlb_finish_mmu(tlb, new_end, old_end);
/*
tlb_finish_mmu(tlb, new_end, old_end);
/*
- *
shrink the vma to just the new range
.
+ *
Shrink the vma to just the new range. Always succeeds
.
*/
vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
return 0;
}
*/
vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
return 0;
}
-#define EXTRA_STACK_VM_PAGES 20 /* random */
-
/*
* Finalizes the stack vm_area_struct. The flags and permissions are updated,
* the stack is optionally relocated, and some extra space is added.
/*
* Finalizes the stack vm_area_struct. The flags and permissions are updated,
* the stack is optionally relocated, and some extra space is added.
@@
-577,7
+577,7
@@
int setup_arg_pages(struct linux_binprm *bprm,
#ifdef CONFIG_STACK_GROWSUP
/* Limit stack size to 1GB */
#ifdef CONFIG_STACK_GROWSUP
/* Limit stack size to 1GB */
- stack_base =
current->signal->rlim[RLIMIT_STACK].rlim_max
;
+ stack_base =
rlimit_max(RLIMIT_STACK)
;
if (stack_base > (1 << 30))
stack_base = 1 << 30;
if (stack_base > (1 << 30))
stack_base = 1 << 30;
@@
-630,7
+630,7
@@
int setup_arg_pages(struct linux_binprm *bprm,
goto out_unlock;
}
goto out_unlock;
}
- stack_expand =
EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+ stack_expand =
131072UL; /* randomly 32*4k (or 2*64k) pages */
stack_size = vma->vm_end - vma->vm_start;
/*
* Align this down to a page boundary as expand_stack
stack_size = vma->vm_end - vma->vm_start;
/*
* Align this down to a page boundary as expand_stack
@@
-718,6
+718,7
@@
static int exec_mmap(struct mm_struct *mm)
/* Notify parent that we're no longer interested in the old VM */
tsk = current;
old_mm = current->mm;
/* Notify parent that we're no longer interested in the old VM */
tsk = current;
old_mm = current->mm;
+ sync_mm_rss(tsk, old_mm);
mm_release(tsk, old_mm);
if (old_mm) {
mm_release(tsk, old_mm);
if (old_mm) {
@@
-1386,8
+1387,6
@@
int do_execve(char * filename,
if (retval < 0)
goto out;
if (retval < 0)
goto out;
- current->stack_start = current->mm->start_stack;
-
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
@@
-1532,7
+1531,7
@@
static int format_corename(char *corename, long signr)
/* core limit size */
case 'c':
rc = snprintf(out_ptr, out_end - out_ptr,
/* core limit size */
case 'c':
rc = snprintf(out_ptr, out_end - out_ptr,
- "%lu",
current->signal->rlim[RLIMIT_CORE].rlim_cur
);
+ "%lu",
rlimit(RLIMIT_CORE)
);
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@
-1560,12
+1559,13
@@
out:
return ispipe;
}
return ispipe;
}
-static int zap_process(struct task_struct *start)
+static int zap_process(struct task_struct *start
, int exit_code
)
{
struct task_struct *t;
int nr = 0;
start->signal->flags = SIGNAL_GROUP_EXIT;
{
struct task_struct *t;
int nr = 0;
start->signal->flags = SIGNAL_GROUP_EXIT;
+ start->signal->group_exit_code = exit_code;
start->signal->group_stop_count = 0;
t = start;
start->signal->group_stop_count = 0;
t = start;
@@
-1590,8
+1590,7
@@
static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
spin_lock_irq(&tsk->sighand->siglock);
if (!signal_group_exit(tsk->signal)) {
mm->core_state = core_state;
spin_lock_irq(&tsk->sighand->siglock);
if (!signal_group_exit(tsk->signal)) {
mm->core_state = core_state;
- tsk->signal->group_exit_code = exit_code;
- nr = zap_process(tsk);
+ nr = zap_process(tsk, exit_code);
}
spin_unlock_irq(&tsk->sighand->siglock);
if (unlikely(nr < 0))
}
spin_unlock_irq(&tsk->sighand->siglock);
if (unlikely(nr < 0))
@@
-1640,7
+1639,7
@@
static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
if (p->mm) {
if (unlikely(p->mm == mm)) {
lock_task_sighand(p, &flags);
if (p->mm) {
if (unlikely(p->mm == mm)) {
lock_task_sighand(p, &flags);
- nr += zap_process(p);
+ nr += zap_process(p
, exit_code
);
unlock_task_sighand(p, &flags);
}
break;
unlock_task_sighand(p, &flags);
}
break;
@@
-1747,14
+1746,19
@@
void set_dumpable(struct mm_struct *mm, int value)
}
}
}
}
-
int get_dumpable(struct mm_struct *mm
)
+
static int __get_dumpable(unsigned long mm_flags
)
{
int ret;
{
int ret;
- ret = mm
->flags & 0x3
;
+ ret = mm
_flags & MMF_DUMPABLE_MASK
;
return (ret >= 2) ? 2 : ret;
}
return (ret >= 2) ? 2 : ret;
}
+int get_dumpable(struct mm_struct *mm)
+{
+ return __get_dumpable(mm->flags);
+}
+
static void wait_for_dump_helpers(struct file *file)
{
struct pipe_inode_info *pipe;
static void wait_for_dump_helpers(struct file *file)
{
struct pipe_inode_info *pipe;
@@
-1797,7
+1801,13
@@
void do_coredump(long signr, int exit_code, struct pt_regs *regs)
struct coredump_params cprm = {
.signr = signr,
.regs = regs,
struct coredump_params cprm = {
.signr = signr,
.regs = regs,
- .limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+ .limit = rlimit(RLIMIT_CORE),
+ /*
+ * We must use the same mm->flags while dumping core to avoid
+ * inconsistency of bit flags, since this flag is not protected
+ * by any locks.
+ */
+ .mm_flags = mm->flags,
};
audit_core_dumps(signr);
};
audit_core_dumps(signr);
@@
-1816,7
+1826,7
@@
void do_coredump(long signr, int exit_code, struct pt_regs *regs)
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
- if (mm->core_state || !
get_dumpable(mm
)) {
+ if (mm->core_state || !
__get_dumpable(cprm.mm_flags
)) {
up_write(&mm->mmap_sem);
put_cred(cred);
goto fail;
up_write(&mm->mmap_sem);
put_cred(cred);
goto fail;
@@
-1827,7
+1837,8
@@
void do_coredump(long signr, int exit_code, struct pt_regs *regs)
* process nor do we know its entire history. We only know it
* was tainted so we dump it as root in mode 2.
*/
* process nor do we know its entire history. We only know it
* was tainted so we dump it as root in mode 2.
*/
- if (get_dumpable(mm) == 2) { /* Setuid core dump mode */
+ if (__get_dumpable(cprm.mm_flags) == 2) {
+ /* Setuid core dump mode */
flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = 0; /* Dump root private */
}
flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = 0; /* Dump root private */
}
@@
-1923,8
+1934,9
@@
void do_coredump(long signr, int exit_code, struct pt_regs *regs)
/*
* Dont allow local users get cute and trick others to coredump
* into their pre-created files:
/*
* Dont allow local users get cute and trick others to coredump
* into their pre-created files:
+ * Note, this is not relevant for pipes
*/
*/
- if (
inode->i_uid != current_fsuid(
))
+ if (
!ispipe && (inode->i_uid != current_fsuid()
))
goto close_fail;
if (!cprm.file->f_op)
goto close_fail;
goto close_fail;
if (!cprm.file->f_op)
goto close_fail;