Skip to content

Commit 6fd2fe4

Browse files
Al Virobrauner
authored andcommitted
copy_process(): don't use ksys_close() on cleanups
anon_inode_getfd() should be used *ONLY* in situations when we are guaranteed to be past the last failure point (including copying the descriptor number to userland, at that). And ksys_close() should not be used for cleanups at all. anon_inode_getfile() is there for all nontrivial cases like that. Just use that... Fixes: b3e5838 ("clone: add CLONE_PIDFD") Signed-off-by: Al Viro <[email protected]> Reviewed-by: Jann Horn <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent bee19cd commit 6fd2fe4

File tree

1 file changed

+18
-28
lines changed

1 file changed

+18
-28
lines changed

kernel/fork.c

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,31 +1712,6 @@ const struct file_operations pidfd_fops = {
17121712
#endif
17131713
};
17141714

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-
17401715
static void __delayed_free_task(struct rcu_head *rhp)
17411716
{
17421717
struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
@@ -1774,6 +1749,7 @@ static __latent_entropy struct task_struct *copy_process(
17741749
int pidfd = -1, retval;
17751750
struct task_struct *p;
17761751
struct multiprocess_signals delayed;
1752+
struct file *pidfile = NULL;
17771753

17781754
/*
17791755
* Don't allow sharing the root directory with processes in a different
@@ -2046,11 +2022,20 @@ static __latent_entropy struct task_struct *copy_process(
20462022
* if the fd table isn't shared).
20472023
*/
20482024
if (clone_flags & CLONE_PIDFD) {
2049-
retval = pidfd_create(pid);
2025+
retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
20502026
if (retval < 0)
20512027
goto bad_fork_free_pid;
20522028

20532029
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+
20542039
retval = put_user(pidfd, parent_tidptr);
20552040
if (retval)
20562041
goto bad_fork_put_pidfd;
@@ -2168,6 +2153,9 @@ static __latent_entropy struct task_struct *copy_process(
21682153
goto bad_fork_cancel_cgroup;
21692154
}
21702155

2156+
/* past the last point of failure */
2157+
if (pidfile)
2158+
fd_install(pidfd, pidfile);
21712159

21722160
init_task_pid_links(p);
21732161
if (likely(p->pid)) {
@@ -2234,8 +2222,10 @@ static __latent_entropy struct task_struct *copy_process(
22342222
bad_fork_cgroup_threadgroup_change_end:
22352223
cgroup_threadgroup_change_end(current);
22362224
bad_fork_put_pidfd:
2237-
if (clone_flags & CLONE_PIDFD)
2238-
ksys_close(pidfd);
2225+
if (clone_flags & CLONE_PIDFD) {
2226+
fput(pidfile);
2227+
put_unused_fd(pidfd);
2228+
}
22392229
bad_fork_free_pid:
22402230
if (pid != &init_struct_pid)
22412231
free_pid(pid);

0 commit comments

Comments
 (0)