Merge tag 'pidfd-updates-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/braun...
[linux-2.6-block.git] / kernel / fork.c
index 2cdf295b72c7fcc7f90e03987644075ae0bee5ee..187c02ce534c87a955cf93d1d01f9fba57c723e2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  *  linux/kernel/fork.c
  *
 unsigned long total_forks;     /* Handle normal Linux uptimes. */
 int nr_threads;                        /* The idle threads do not count.. */
 
-int max_threads;               /* tunable limit on nr_threads */
+static int max_threads;                /* tunable limit on nr_threads */
 
 DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
@@ -247,7 +248,11 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
        struct page *page = alloc_pages_node(node, THREADINFO_GFP,
                                             THREAD_SIZE_ORDER);
 
-       return page ? page_address(page) : NULL;
+       if (likely(page)) {
+               tsk->stack = page_address(page);
+               return tsk->stack;
+       }
+       return NULL;
 #endif
 }
 
@@ -893,6 +898,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 #ifdef CONFIG_STACKPROTECTOR
        tsk->stack_canary = get_random_canary();
 #endif
+       if (orig->cpus_ptr == &orig->cpus_mask)
+               tsk->cpus_ptr = &tsk->cpus_mask;
 
        /*
         * One for us, one for whoever does the "release_task()" (usually
@@ -1737,31 +1744,6 @@ const struct file_operations pidfd_fops = {
 #endif
 };
 
-/**
- * pidfd_create() - Create a new pid file descriptor.
- *
- * @pid:  struct pid that the pidfd will reference
- *
- * This creates a new pid file descriptor with the O_CLOEXEC flag set.
- *
- * Note, that this function can only be called after the fd table has
- * been unshared to avoid leaking the pidfd to the new process.
- *
- * Return: On success, a cloexec pidfd is returned.
- *         On error, a negative errno number will be returned.
- */
-static int pidfd_create(struct pid *pid)
-{
-       int fd;
-
-       fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid),
-                             O_RDWR | O_CLOEXEC);
-       if (fd < 0)
-               put_pid(pid);
-
-       return fd;
-}
-
 static void __delayed_free_task(struct rcu_head *rhp)
 {
        struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
@@ -1799,6 +1781,7 @@ static __latent_entropy struct task_struct *copy_process(
        int pidfd = -1, retval;
        struct task_struct *p;
        struct multiprocess_signals delayed;
+       struct file *pidfile = NULL;
 
        /*
         * Don't allow sharing the root directory with processes in a different
@@ -1847,8 +1830,6 @@ static __latent_entropy struct task_struct *copy_process(
        }
 
        if (clone_flags & CLONE_PIDFD) {
-               int reserved;
-
                /*
                 * - CLONE_PARENT_SETTID is useless for pidfds and also
                 *   parent_tidptr is used to return pidfds.
@@ -1859,16 +1840,6 @@ static __latent_entropy struct task_struct *copy_process(
                if (clone_flags &
                    (CLONE_DETACHED | CLONE_PARENT_SETTID | CLONE_THREAD))
                        return ERR_PTR(-EINVAL);
-
-               /*
-                * Verify that parent_tidptr is sane so we can potentially
-                * reuse it later.
-                */
-               if (get_user(reserved, parent_tidptr))
-                       return ERR_PTR(-EFAULT);
-
-               if (reserved != 0)
-                       return ERR_PTR(-EINVAL);
        }
 
        /*
@@ -2009,9 +1980,6 @@ static __latent_entropy struct task_struct *copy_process(
        p->pagefault_disabled = 0;
 
 #ifdef CONFIG_LOCKDEP
-       p->lockdep_depth = 0; /* no locks held yet */
-       p->curr_chain_key = 0;
-       p->lockdep_recursion = 0;
        lockdep_init_task(p);
 #endif
 
@@ -2083,11 +2051,21 @@ static __latent_entropy struct task_struct *copy_process(
         * if the fd table isn't shared).
         */
        if (clone_flags & CLONE_PIDFD) {
-               retval = pidfd_create(pid);
+               retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
                if (retval < 0)
                        goto bad_fork_free_pid;
 
                pidfd = retval;
+
+               pidfile = anon_inode_getfile("[pidfd]", &pidfd_fops, pid,
+                                             O_RDWR | O_CLOEXEC);
+               if (IS_ERR(pidfile)) {
+                       put_unused_fd(pidfd);
+                       retval = PTR_ERR(pidfile);
+                       goto bad_fork_free_pid;
+               }
+               get_pid(pid);   /* held by pidfile now */
+
                retval = put_user(pidfd, parent_tidptr);
                if (retval)
                        goto bad_fork_put_pidfd;
@@ -2164,7 +2142,7 @@ static __latent_entropy struct task_struct *copy_process(
         */
 
        p->start_time = ktime_get_ns();
-       p->real_start_time = ktime_get_boot_ns();
+       p->real_start_time = ktime_get_boottime_ns();
 
        /*
         * Make it visible to the rest of the system, but dont wake it up yet.
@@ -2205,6 +2183,9 @@ static __latent_entropy struct task_struct *copy_process(
                goto bad_fork_cancel_cgroup;
        }
 
+       /* past the last point of failure */
+       if (pidfile)
+               fd_install(pidfd, pidfile);
 
        init_task_pid_links(p);
        if (likely(p->pid)) {
@@ -2271,8 +2252,10 @@ bad_fork_cancel_cgroup:
 bad_fork_cgroup_threadgroup_change_end:
        cgroup_threadgroup_change_end(current);
 bad_fork_put_pidfd:
-       if (clone_flags & CLONE_PIDFD)
-               ksys_close(pidfd);
+       if (clone_flags & CLONE_PIDFD) {
+               fput(pidfile);
+               put_unused_fd(pidfd);
+       }
 bad_fork_free_pid:
        if (pid != &init_struct_pid)
                free_pid(pid);