From: michael-dev@fami-braun.de
To: util-linux@vger.kernel.org
Cc: michael-dev@fami-braun.de
Subject: [PATCH] Fix PID namespace persistence
Date: Wed, 15 Apr 2020 23:16:53 +0200 [thread overview]
Message-ID: <20200415211653.5455-1-michael-dev@fami-braun.de> (raw)
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.
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)
--
2.17.1
next reply other threads:[~2020-04-15 21:20 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-15 21:16 michael-dev [this message]
2020-04-16 8:52 ` [PATCH] Fix PID namespace persistence Karel Zak
2020-04-16 20:49 ` Eric W. Biederman
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=20200415211653.5455-1-michael-dev@fami-braun.de \
--to=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