From: ebiederm@xmission.com (Eric W. Biederman)
To: "Dmitry V. Levin" <ldv@altlinux.org>
Cc: "David S. Miller" <davem@davemloft.net>,
Alexey Gladkov <gladkov.alexey@gmail.com>,
Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>,
Anatoly Pugachev <matorola@gmail.com>,
sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] sparc: make copy_thread honor pid namespaces
Date: Thu, 18 Feb 2021 18:21:40 +0000 [thread overview]
Message-ID: <m1tuq9nsnf.fsf@fess.ebiederm.org> (raw)
In-Reply-To: <20210217080000.GA25861@altlinux.org> (Dmitry V. Levin's message of "Wed, 17 Feb 2021 08:00:00 +0000")
"Dmitry V. Levin" <ldv@altlinux.org> writes:
> On sparc, fork and clone syscalls have an unusual semantics of
> returning the pid of the parent process to the child process.
>
> Apparently, the implementation did not honor pid namespaces at all,
> so the child used to get the pid of its parent in the init namespace.
>
> This bug was found by strace test suite.
>
> Reproducer:
>
> $ gcc -Wall -O2 -xc - <<'EOF'
> #define _GNU_SOURCE
> #include <err.h>
> #include <errno.h>
> #include <sched.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/wait.h>
> #include <unistd.h>
> #include <asm/unistd.h>
> #include <linux/sched.h>
> int main(void)
> {
> if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0)
> err(1, "unshare");
> int pid = syscall(__NR_fork);
> if (pid < 0)
> err(1, "fork");
> fprintf(stderr, "current: %d, parent: %d, fork returned: %d\n",
> getpid(), getppid(), pid);
> int status;
> if (wait(&status) < 0) {
> if (errno = ECHILD)
> _exit(0);
> err(1, "wait");
> }
> return !WIFEXITED(status) || WEXITSTATUS(status) != 0;
> }
> EOF
> $ sh -c ./a.out
> current: 10001, parent: 10000, fork returned: 10002
> current: 1, parent: 0, fork returned: 10001
From glibc's sysdeps/unix/sparc/fork.S:
> SYSCALL__ (fork, 0)
> /* %o1 is now 0 for the parent and 1 for the child. Decrement it to
> make it -1 (all bits set) for the parent, and 0 (no bits set)
> for the child. Then AND it with %o0, so the parent gets
> %o0&-1=pid, and the child gets %o0&0=0. */
> sub %o1, 1, %o1
> retl
> and %o0, %o1, %o0
> libc_hidden_def (__fork)
>
> weak_alias (__fork, fork)
This needs to be shared to make the test case make sense.
The change below looks reasonable. Unfortunately because copy_thread
comes before init_task_pid task_active_pid_ns(p) will not work
correctly.
The code below needs to use current->nsproxy->pid_ns_for_children
instead of task_active_pid_ns(p).
For sparc people. Do we know of anyone who actually uses the parent pid
returned from fork to the child process? If not the code can simply
return 0 and we don't have to do this.
Eric
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
> ---
>
> Although the fix seems to be obvious, I have no means to test it myself,
> so any help with the testing is much appreciated.
>
> arch/sparc/kernel/process_32.c | 2 +-
> arch/sparc/kernel/process_64.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
> index a02363735915..7a89969befa8 100644
> --- a/arch/sparc/kernel/process_32.c
> +++ b/arch/sparc/kernel/process_32.c
> @@ -368,7 +368,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
> #endif
>
> /* Set the return value for the child. */
> - childregs->u_regs[UREG_I0] = current->pid;
> + childregs->u_regs[UREG_I0] = task_pid_nr_ns(current, task_active_pid_ns(p));
> childregs->u_regs[UREG_I1] = 1;
>
> /* Set the return value for the parent. */
> diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
> index 6f8c7822fc06..ec97217ab970 100644
> --- a/arch/sparc/kernel/process_64.c
> +++ b/arch/sparc/kernel/process_64.c
> @@ -629,7 +629,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
> t->utraps[0]++;
>
> /* Set the return value for the child. */
> - t->kregs->u_regs[UREG_I0] = current->pid;
> + t->kregs->u_regs[UREG_I0] = task_pid_nr_ns(current, task_active_pid_ns(p));
> t->kregs->u_regs[UREG_I1] = 1;
>
> /* Set the second return value for the parent. */
WARNING: multiple messages have this Message-ID (diff)
From: ebiederm@xmission.com (Eric W. Biederman)
To: "Dmitry V. Levin" <ldv@altlinux.org>
Cc: "David S. Miller" <davem@davemloft.net>,
Alexey Gladkov <gladkov.alexey@gmail.com>,
Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>,
Anatoly Pugachev <matorola@gmail.com>,
sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] sparc: make copy_thread honor pid namespaces
Date: Thu, 18 Feb 2021 12:21:40 -0600 [thread overview]
Message-ID: <m1tuq9nsnf.fsf@fess.ebiederm.org> (raw)
In-Reply-To: <20210217080000.GA25861@altlinux.org> (Dmitry V. Levin's message of "Wed, 17 Feb 2021 08:00:00 +0000")
"Dmitry V. Levin" <ldv@altlinux.org> writes:
> On sparc, fork and clone syscalls have an unusual semantics of
> returning the pid of the parent process to the child process.
>
> Apparently, the implementation did not honor pid namespaces at all,
> so the child used to get the pid of its parent in the init namespace.
>
> This bug was found by strace test suite.
>
> Reproducer:
>
> $ gcc -Wall -O2 -xc - <<'EOF'
> #define _GNU_SOURCE
> #include <err.h>
> #include <errno.h>
> #include <sched.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/wait.h>
> #include <unistd.h>
> #include <asm/unistd.h>
> #include <linux/sched.h>
> int main(void)
> {
> if (unshare(CLONE_NEWPID | CLONE_NEWUSER) < 0)
> err(1, "unshare");
> int pid = syscall(__NR_fork);
> if (pid < 0)
> err(1, "fork");
> fprintf(stderr, "current: %d, parent: %d, fork returned: %d\n",
> getpid(), getppid(), pid);
> int status;
> if (wait(&status) < 0) {
> if (errno == ECHILD)
> _exit(0);
> err(1, "wait");
> }
> return !WIFEXITED(status) || WEXITSTATUS(status) != 0;
> }
> EOF
> $ sh -c ./a.out
> current: 10001, parent: 10000, fork returned: 10002
> current: 1, parent: 0, fork returned: 10001
From glibc's sysdeps/unix/sparc/fork.S:
> SYSCALL__ (fork, 0)
> /* %o1 is now 0 for the parent and 1 for the child. Decrement it to
> make it -1 (all bits set) for the parent, and 0 (no bits set)
> for the child. Then AND it with %o0, so the parent gets
> %o0&-1==pid, and the child gets %o0&0==0. */
> sub %o1, 1, %o1
> retl
> and %o0, %o1, %o0
> libc_hidden_def (__fork)
>
> weak_alias (__fork, fork)
This needs to be shared to make the test case make sense.
The change below looks reasonable. Unfortunately because copy_thread
comes before init_task_pid task_active_pid_ns(p) will not work
correctly.
The code below needs to use current->nsproxy->pid_ns_for_children
instead of task_active_pid_ns(p).
For sparc people. Do we know of anyone who actually uses the parent pid
returned from fork to the child process? If not the code can simply
return 0 and we don't have to do this.
Eric
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
> ---
>
> Although the fix seems to be obvious, I have no means to test it myself,
> so any help with the testing is much appreciated.
>
> arch/sparc/kernel/process_32.c | 2 +-
> arch/sparc/kernel/process_64.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
> index a02363735915..7a89969befa8 100644
> --- a/arch/sparc/kernel/process_32.c
> +++ b/arch/sparc/kernel/process_32.c
> @@ -368,7 +368,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
> #endif
>
> /* Set the return value for the child. */
> - childregs->u_regs[UREG_I0] = current->pid;
> + childregs->u_regs[UREG_I0] = task_pid_nr_ns(current, task_active_pid_ns(p));
> childregs->u_regs[UREG_I1] = 1;
>
> /* Set the return value for the parent. */
> diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
> index 6f8c7822fc06..ec97217ab970 100644
> --- a/arch/sparc/kernel/process_64.c
> +++ b/arch/sparc/kernel/process_64.c
> @@ -629,7 +629,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
> t->utraps[0]++;
>
> /* Set the return value for the child. */
> - t->kregs->u_regs[UREG_I0] = current->pid;
> + t->kregs->u_regs[UREG_I0] = task_pid_nr_ns(current, task_active_pid_ns(p));
> t->kregs->u_regs[UREG_I1] = 1;
>
> /* Set the second return value for the parent. */
next prev parent reply other threads:[~2021-02-18 18:21 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-17 8:00 [PATCH] sparc: make copy_thread honor pid namespaces Dmitry V. Levin
2021-02-17 8:00 ` Dmitry V. Levin
2021-02-18 15:28 ` David Laight
2021-02-18 18:21 ` Eric W. Biederman [this message]
2021-02-18 18:21 ` Eric W. Biederman
2021-02-19 22:50 ` [PATCH v2] " Dmitry V. Levin
2021-02-19 22:50 ` Dmitry V. Levin
2021-02-22 21:30 ` Eric W. Biederman
2021-02-22 21:30 ` Eric W. Biederman
2021-02-23 11:14 ` Anatoly Pugachev
2021-02-23 11:14 ` Anatoly Pugachev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m1tuq9nsnf.fsf@fess.ebiederm.org \
--to=ebiederm@xmission.com \
--cc=davem@davemloft.net \
--cc=gladkov.alexey@gmail.com \
--cc=glebfm@altlinux.org \
--cc=ldv@altlinux.org \
--cc=linux-kernel@vger.kernel.org \
--cc=matorola@gmail.com \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.