diff options
-rw-r--r-- | kernel/fork.c | 46 |
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 | */ | ||
1728 | static 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 | |||
1740 | static void __delayed_free_task(struct rcu_head *rhp) | 1715 | static 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: | |||
2234 | bad_fork_cgroup_threadgroup_change_end: | 2222 | bad_fork_cgroup_threadgroup_change_end: |
2235 | cgroup_threadgroup_change_end(current); | 2223 | cgroup_threadgroup_change_end(current); |
2236 | bad_fork_put_pidfd: | 2224 | bad_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 | } | ||
2239 | bad_fork_free_pid: | 2229 | bad_fork_free_pid: |
2240 | if (pid != &init_struct_pid) | 2230 | if (pid != &init_struct_pid) |
2241 | free_pid(pid); | 2231 | free_pid(pid); |