time: settimeofday: Validate the values of tv from user
[pandora-kernel.git] / kernel / fork.c
index ba0d172..29b4604 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/audit.h>
 #include <linux/memcontrol.h>
 #include <linux/ftrace.h>
+#include <linux/proc_fs.h>
 #include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/ksm.h>
@@ -66,6 +67,7 @@
 #include <linux/user-return-notifier.h>
 #include <linux/oom.h>
 #include <linux/khugepaged.h>
+#include <linux/signalfd.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -162,7 +164,6 @@ static void account_kernel_stack(struct thread_info *ti, int account)
 
 void free_task(struct task_struct *tsk)
 {
-       prop_local_destroy_single(&tsk->dirties);
        account_kernel_stack(tsk->stack, -1);
        free_thread_info(tsk->stack);
        rt_mutex_debug_task_free(tsk);
@@ -274,10 +275,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        tsk->stack = ti;
 
-       err = prop_local_init_single(&tsk->dirties);
-       if (err)
-               goto out;
-
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
        clear_tsk_need_resched(tsk);
@@ -355,7 +352,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                }
                charge = 0;
                if (mpnt->vm_flags & VM_ACCOUNT) {
-                       unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+                       unsigned long len;
+                       len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
                        if (security_vm_enough_memory(len))
                                goto fail_nomem;
                        charge = len;
@@ -915,8 +913,10 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
 
 void __cleanup_sighand(struct sighand_struct *sighand)
 {
-       if (atomic_dec_and_test(&sighand->count))
+       if (atomic_dec_and_test(&sighand->count)) {
+               signalfd_cleanup(sighand);
                kmem_cache_free(sighand_cachep, sighand);
+       }
 }
 
 
@@ -979,6 +979,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 #ifdef CONFIG_CGROUPS
        init_rwsem(&sig->threadgroup_fork_lock);
 #endif
+#ifdef CONFIG_CPUSETS
+       seqcount_init(&tsk->mems_allowed_seq);
+#endif
 
        sig->oom_adj = current->signal->oom_adj;
        sig->oom_score_adj = current->signal->oom_score_adj;
@@ -1054,7 +1057,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 {
        int retval;
        struct task_struct *p;
-       int cgroup_callbacks_done = 0;
 
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
@@ -1219,7 +1221,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                goto bad_fork_cleanup_policy;
        retval = audit_alloc(p);
        if (retval)
-               goto bad_fork_cleanup_policy;
+               goto bad_fork_cleanup_perf;
        /* copy all the process information */
        retval = copy_semundo(clone_flags, p);
        if (retval)
@@ -1309,12 +1311,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        p->group_leader = p;
        INIT_LIST_HEAD(&p->thread_group);
 
-       /* Now that the task is set up, run cgroup callbacks if
-        * necessary. We need to run them before the task is visible
-        * on the tasklist. */
-       cgroup_fork_callbacks(p);
-       cgroup_callbacks_done = 1;
-
        /* Need tasklist lock for parent etc handling! */
        write_lock_irq(&tasklist_lock);
 
@@ -1374,7 +1370,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        total_forks++;
        spin_unlock(&current->sighand->siglock);
+       syscall_tracepoint_update(p);
        write_unlock_irq(&tasklist_lock);
+
        proc_fork_connector(p);
        cgroup_post_fork(p);
        if (clone_flags & CLONE_THREAD)
@@ -1389,6 +1387,8 @@ bad_fork_cleanup_io:
        if (p->io_context)
                exit_io_context(p);
 bad_fork_cleanup_namespaces:
+       if (unlikely(clone_flags & CLONE_NEWPID))
+               pid_ns_release_proc(p->nsproxy->pid_ns);
        exit_task_namespaces(p);
 bad_fork_cleanup_mm:
        if (p->mm)
@@ -1406,15 +1406,16 @@ bad_fork_cleanup_semundo:
        exit_sem(p);
 bad_fork_cleanup_audit:
        audit_free(p);
-bad_fork_cleanup_policy:
+bad_fork_cleanup_perf:
        perf_event_free_task(p);
+bad_fork_cleanup_policy:
 #ifdef CONFIG_NUMA
        mpol_put(p->mempolicy);
 bad_fork_cleanup_cgroup:
 #endif
        if (clone_flags & CLONE_THREAD)
                threadgroup_fork_read_unlock(current);
-       cgroup_exit(p, cgroup_callbacks_done);
+       cgroup_exit(p, 0);
        delayacct_tsk_free(p);
        module_put(task_thread_info(p)->exec_domain->module);
 bad_fork_cleanup_count:
@@ -1515,10 +1516,12 @@ long do_fork(unsigned long clone_flags,
         */
        if (!IS_ERR(p)) {
                struct completion vfork;
+               struct pid *pid;
 
                trace_sched_process_fork(current, p);
 
-               nr = task_pid_vnr(p);
+               pid = get_task_pid(p, PIDTYPE_PID);
+               nr = pid_vnr(pid);
 
                if (clone_flags & CLONE_PARENT_SETTID)
                        put_user(nr, parent_tidptr);
@@ -1542,14 +1545,16 @@ long do_fork(unsigned long clone_flags,
 
                /* forking complete and child started to run, tell ptracer */
                if (unlikely(trace))
-                       ptrace_event(trace, nr);
+                       ptrace_event_pid(trace, pid);
 
                if (clone_flags & CLONE_VFORK) {
                        freezer_do_not_count();
                        wait_for_completion(&vfork);
                        freezer_count();
-                       ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
+                       ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
                }
+
+               put_pid(pid);
        } else {
                nr = PTR_ERR(p);
        }