aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/fork.c46
1 files changed, 18 insertions, 28 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 39a3adaa4ad1..399aca51ff75 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1712,31 +1712,6 @@ const struct file_operations pidfd_fops = {
1712#endif 1712#endif
1713}; 1713};
1714 1714
1715/**
1716 * pidfd_create() - Create a new pid file descriptor.
1717 *
1718 * @pid: struct pid that the pidfd will reference
1719 *
1720 * This creates a new pid file descriptor with the O_CLOEXEC flag set.
1721 *
1722 * Note, that this function can only be called after the fd table has
1723 * been unshared to avoid leaking the pidfd to the new process.
1724 *
1725 * Return: On success, a cloexec pidfd is returned.
1726 * On error, a negative errno number will be returned.
1727 */
1728static int pidfd_create(struct pid *pid)
1729{
1730 int fd;
1731
1732 fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid),
1733 O_RDWR | O_CLOEXEC);
1734 if (fd < 0)
1735 put_pid(pid);
1736
1737 return fd;
1738}
1739
1740static void __delayed_free_task(struct rcu_head *rhp) 1715static void __delayed_free_task(struct rcu_head *rhp)
1741{ 1716{
1742 struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); 1717 struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
@@ -1774,6 +1749,7 @@ static __latent_entropy struct task_struct *copy_process(
1774 int pidfd = -1, retval; 1749 int pidfd = -1, retval;
1775 struct task_struct *p; 1750 struct task_struct *p;
1776 struct multiprocess_signals delayed; 1751 struct multiprocess_signals delayed;
1752 struct file *pidfile = NULL;
1777 1753
1778 /* 1754 /*
1779 * Don't allow sharing the root directory with processes in a different 1755 * Don't allow sharing the root directory with processes in a different
@@ -2046,11 +2022,20 @@ static __latent_entropy struct task_struct *copy_process(
2046 * if the fd table isn't shared). 2022 * if the fd table isn't shared).
2047 */ 2023 */
2048 if (clone_flags & CLONE_PIDFD) { 2024 if (clone_flags & CLONE_PIDFD) {
2049 retval = pidfd_create(pid); 2025 retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
2050 if (retval < 0) 2026 if (retval < 0)
2051 goto bad_fork_free_pid; 2027 goto bad_fork_free_pid;
2052 2028
2053 pidfd = retval; 2029 pidfd = retval;
2030
2031 pidfile = anon_inode_getfile("[pidfd]", &pidfd_fops, pid,
2032 O_RDWR | O_CLOEXEC);
2033 if (IS_ERR(pidfile)) {
2034 put_unused_fd(pidfd);
2035 goto bad_fork_free_pid;
2036 }
2037 get_pid(pid); /* held by pidfile now */
2038
2054 retval = put_user(pidfd, parent_tidptr); 2039 retval = put_user(pidfd, parent_tidptr);
2055 if (retval) 2040 if (retval)
2056 goto bad_fork_put_pidfd; 2041 goto bad_fork_put_pidfd;
@@ -2168,6 +2153,9 @@ static __latent_entropy struct task_struct *copy_process(
2168 goto bad_fork_cancel_cgroup; 2153 goto bad_fork_cancel_cgroup;
2169 } 2154 }
2170 2155
2156 /* past the last point of failure */
2157 if (pidfile)
2158 fd_install(pidfd, pidfile);
2171 2159
2172 init_task_pid_links(p); 2160 init_task_pid_links(p);
2173 if (likely(p->pid)) { 2161 if (likely(p->pid)) {
@@ -2234,8 +2222,10 @@ bad_fork_cancel_cgroup:
2234bad_fork_cgroup_threadgroup_change_end: 2222bad_fork_cgroup_threadgroup_change_end:
2235 cgroup_threadgroup_change_end(current); 2223 cgroup_threadgroup_change_end(current);
2236bad_fork_put_pidfd: 2224bad_fork_put_pidfd:
2237 if (clone_flags & CLONE_PIDFD) 2225 if (clone_flags & CLONE_PIDFD) {
2238 ksys_close(pidfd); 2226 fput(pidfile);
2227 put_unused_fd(pidfd);
2228 }
2239bad_fork_free_pid: 2229bad_fork_free_pid:
2240 if (pid != &init_struct_pid) 2230 if (pid != &init_struct_pid)
2241 free_pid(pid); 2231 free_pid(pid);