From: ebiederm@xmission.com (Eric W. Biederman)
To: michael-dev@fami-braun.de
Cc: util-linux@vger.kernel.org
Subject: Re: [PATCH] Fix PID namespace persistence
Date: Thu, 16 Apr 2020 15:49:14 -0500 [thread overview]
Message-ID: <87o8rrdulx.fsf@x220.int.ebiederm.org> (raw)
In-Reply-To: <20200415211653.5455-1-michael-dev@fami-braun.de> (michael-dev's message of "Wed, 15 Apr 2020 23:16:53 +0200")
michael-dev@fami-braun.de writes:
> From: michael-dev <michael-dev@fami-braun.de>
>
> After unshare(...) is called, /proc/self/ns/pid does not change.
> Instead, only /proc/self/ns/pid_for_children is affected. So bind-mounting /proc/self/ns/pid results in the original namespace getting bind-mounted.
>
> Fix this by instead bind-mounting ns/pid_for_children.
Why all of the extra code motion and change?
Your description sounds like only the first hunk is necessary. Did
something else get mixed into this change? Or are all of the hunks
necessary?
Eric
> Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
> ---
> sys-utils/unshare.c | 66 ++++++++++++++++++++++++++-------------------
> 1 file changed, 38 insertions(+), 28 deletions(-)
>
> diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
> index 8652ebdaf..c3ba18e32 100644
> --- a/sys-utils/unshare.c
> +++ b/sys-utils/unshare.c
> @@ -63,7 +63,7 @@ static struct namespace_file {
> { .type = CLONE_NEWIPC, .name = "ns/ipc" },
> { .type = CLONE_NEWUTS, .name = "ns/uts" },
> { .type = CLONE_NEWNET, .name = "ns/net" },
> - { .type = CLONE_NEWPID, .name = "ns/pid" },
> + { .type = CLONE_NEWPID, .name = "ns/pid_for_children" },
> { .type = CLONE_NEWNS, .name = "ns/mnt" },
> { .type = CLONE_NEWTIME, .name = "ns/time" },
> { .name = NULL }
> @@ -361,6 +361,7 @@ int main(int argc, char *argv[])
> const char *procmnt = NULL;
> const char *newroot = NULL;
> const char *newdir = NULL;
> + pid_t pid_bind = 0;
> pid_t pid = 0;
> int fds[2];
> int status;
> @@ -501,13 +502,37 @@ int main(int argc, char *argv[])
> "unsharing of a time namespace (-t)"));
>
> if (npersists && (unshare_flags & CLONE_NEWNS))
> - bind_ns_files_from_child(&pid, fds);
> + bind_ns_files_from_child(&pid_bind, fds);
>
> if (-1 == unshare(unshare_flags))
> err(EXIT_FAILURE, _("unshare failed"));
>
> - if (npersists) {
> - if (pid && (unshare_flags & CLONE_NEWNS)) {
> + if (force_boottime)
> + settime(boottime, CLOCK_BOOTTIME);
> +
> + if (force_monotonic)
> + settime(monotonic, CLOCK_MONOTONIC);
> +
> + if (forkit) {
> + // force child forking before mountspace binding
> + // so pid_for_children is populated
> + pid = fork();
> +
> + switch(pid) {
> + case -1:
> + err(EXIT_FAILURE, _("fork failed"));
> + case 0: /* child */
> + if (pid_bind && (unshare_flags & CLONE_NEWNS))
> + close(fds[1]);
> + break;
> + default: /* parent */
> + break;
> + }
> + }
> +
> + if (npersists && (pid || !forkit)) {
> + // run in parent
> + if (pid_bind && (unshare_flags & CLONE_NEWNS)) {
> int rc;
> char ch = PIPE_SYNC_BYTE;
>
> @@ -518,7 +543,7 @@ int main(int argc, char *argv[])
>
> /* wait for bind_ns_files_from_child() */
> do {
> - rc = waitpid(pid, &status, 0);
> + rc = waitpid(pid_bind, &status, 0);
> if (rc < 0) {
> if (errno == EINTR)
> continue;
> @@ -533,29 +558,14 @@ int main(int argc, char *argv[])
> bind_ns_files(getpid());
> }
>
> - if (force_boottime)
> - settime(boottime, CLOCK_BOOTTIME);
> -
> - if (force_monotonic)
> - settime(monotonic, CLOCK_MONOTONIC);
> -
> - if (forkit) {
> - pid = fork();
> -
> - switch(pid) {
> - case -1:
> - err(EXIT_FAILURE, _("fork failed"));
> - case 0: /* child */
> - break;
> - default: /* parent */
> - if (waitpid(pid, &status, 0) == -1)
> - err(EXIT_FAILURE, _("waitpid failed"));
> - if (WIFEXITED(status))
> - return WEXITSTATUS(status);
> - else if (WIFSIGNALED(status))
> - kill(getpid(), WTERMSIG(status));
> - err(EXIT_FAILURE, _("child exit failed"));
> - }
> + if (pid) {
> + if (waitpid(pid, &status, 0) == -1)
> + err(EXIT_FAILURE, _("waitpid failed"));
> + if (WIFEXITED(status))
> + return WEXITSTATUS(status);
> + else if (WIFSIGNALED(status))
> + kill(getpid(), WTERMSIG(status));
> + err(EXIT_FAILURE, _("child exit failed"));
> }
>
> if (kill_child_signo != 0 && prctl(PR_SET_PDEATHSIG, kill_child_signo) < 0)
next prev parent reply other threads:[~2020-04-16 20:52 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-15 21:16 [PATCH] Fix PID namespace persistence michael-dev
2020-04-16 8:52 ` Karel Zak
2020-04-16 20:49 ` Eric W. Biederman [this message]
2020-04-18 23:05 ` michael-dev
2020-04-24 9:21 ` Michael Kerrisk
2020-04-27 9:33 ` Karel Zak
2020-04-27 10:50 ` Michael Kerrisk (man-pages)
2020-04-30 9:06 ` Karel Zak
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=87o8rrdulx.fsf@x220.int.ebiederm.org \
--to=ebiederm@xmission.com \
--cc=michael-dev@fami-braun.de \
--cc=util-linux@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox