for-linus-20190627
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE7btrcuORLb1XUhEwjrBW1T7ssS0FAl0UnRoACgkQjrBW1T7s sS1T0w/+PFooDZNaKJkhJCGm0XyRDYmmuivEX9ydUR1x9/doRbDZTqfjsQBJLoVK PulxDiuFbQWXzhBJFEMuU6YBR2fjFqUGsXz5qAXPB0zaahWcSY/0Y8VCU/PKq7A6 3oJPl/lYwYkLTYUKsnN08hByosUA7WeRQRAxbSFWdCTlUfIw72mDhprMGjJIVAlu snLA5lUoy7hyoFdXR5qNhYAcX8sASmi01hXhdnsKMOv4z2Vb5NoQsgqL1W8tAnsf BdJKL82Qd7vWQahlbOtur46aeJAL2ukGSTskuA2jOQqsKxmpos+hWq36gToq7usa XgPii0Rz7/2s6ZvhmxV5kmzqHylT9giU1DxWybSVo9IZBsU2i1o9DV+yBY50tr45 s0bmpSA/u4DP2uT8oRvh47LbDqiQFA8dyVWQKE25smSdjekuZHTO0tgXf8mwC2CW hDci4z+ONOyqIQyFrhP7UaKuSK6tAAUbYKtXUIN6rnuq1FjuTA2+wtIlOPZuDZQ2 yrsSUefh4/sFMBSAgoGTg9f+PiCejBMKcxoqhU2/27mvkiInAyDPfoc4oGQcinOy OVX3B0A8B88l26sDkWdv15d92E1GKzZLj8h66TlYwDpN+seevftKtpblZ9fJWsSf 0NejoMV/GcA/KsAp1sxqWwouRob8H6pbGXWb97DYRA2IVyjK3q4= =APjA -----END PGP SIGNATURE----- Merge tag 'for-linus-20190627' of gitolite.kernel.org:pub/scm/linux/kernel/git/brauner/linux Pull pidfd fixes from Christian Brauner: "Userspace tools and libraries such as strace or glibc need a cheap and reliable way to tell whether CLONE_PIDFD is supported. The easiest way is to pass an invalid fd value in the return argument, perform the syscall and verify the value in the return argument has been changed to a valid fd. However, if CLONE_PIDFD is specified we currently check if pidfd == 0 and return EINVAL if not. The check for pidfd == 0 was originally added to enable us to abuse the return argument for passing additional flags along with CLONE_PIDFD in the future. However, extending legacy clone this way would be a terrible idea and with clone3 on the horizon and the ability to reuse CLONE_DETACHED with CLONE_PIDFD there's no real need for this clutch. So remove the pidfd == 0 check and help userspace out. Also, accordig to Al, anon_inode_getfd() should only be used past the point of no failure and ksys_close() should not be used at all since it is far too easy to get wrong. Al's motto being "basically, once it's in descriptor table, it's out of your control". So Al's patch switches back to what we already had in v1 of the original patchset and uses a anon_inode_getfile() + put_user() + fd_install() sequence in the success path and a fput() + put_unused_fd() in the failure path. The other two changes should be trivial" * tag 'for-linus-20190627' of gitolite.kernel.org:pub/scm/linux/kernel/git/brauner/linux: proc: remove useless d_is_dir() check copy_process(): don't use ksys_close() on cleanups samples: make pidfd-metadata fail gracefully on older kernels fork: don't check parent_tidptr with CLONE_PIDFD
This commit is contained in:
Коммит
7a702b4e82
|
@ -3077,8 +3077,7 @@ static const struct file_operations proc_tgid_base_operations = {
|
|||
|
||||
struct pid *tgid_pidfd_to_pid(const struct file *file)
|
||||
{
|
||||
if (!d_is_dir(file->f_path.dentry) ||
|
||||
(file->f_op != &proc_tgid_base_operations))
|
||||
if (file->f_op != &proc_tgid_base_operations)
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
return proc_pid(file_inode(file));
|
||||
|
|
|
@ -1712,31 +1712,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);
|
||||
|
@ -1774,6 +1749,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
|
||||
|
@ -1822,8 +1798,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.
|
||||
|
@ -1834,16 +1808,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2058,11 +2022,20 @@ 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);
|
||||
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;
|
||||
|
@ -2180,6 +2153,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)) {
|
||||
|
@ -2246,8 +2222,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);
|
||||
|
|
|
@ -83,7 +83,7 @@ static int pidfd_metadata_fd(pid_t pid, int pidfd)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int pidfd = 0, ret = EXIT_FAILURE;
|
||||
int pidfd = -1, ret = EXIT_FAILURE;
|
||||
char buf[4096] = { 0 };
|
||||
pid_t pid;
|
||||
int procfd, statusfd;
|
||||
|
@ -91,7 +91,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
pid = pidfd_clone(CLONE_PIDFD, &pidfd);
|
||||
if (pid < 0)
|
||||
exit(ret);
|
||||
err(ret, "CLONE_PIDFD");
|
||||
if (pidfd == -1) {
|
||||
warnx("CLONE_PIDFD is not supported by the kernel");
|
||||
goto out;
|
||||
}
|
||||
|
||||
procfd = pidfd_metadata_fd(pid, pidfd);
|
||||
close(pidfd);
|
||||
|
|
Загрузка…
Ссылка в новой задаче