From: Karel Zak Date: Thu, 31 Mar 2022 08:55:30 +0000 (+0200) Subject: unshare: make pidfd_open() use more portable and robust X-Git-Tag: v2.39-rc1~743 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=153607e20377f60ab9ff026c1a5c0d07f89f49a3;p=thirdparty%2Futil-linux.git unshare: make pidfd_open() use more portable and robust * use #ifdef UL_HAVE_PIDFD for better portability * open and close fd_parent_pid only when --kill-child specified Signed-off-by: Karel Zak --- diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c index d35f1df274..755631ff4d 100644 --- a/sys-utils/unshare.c +++ b/sys-utils/unshare.c @@ -766,7 +766,9 @@ int main(int argc, char *argv[]) const char *newdir = NULL; pid_t pid_bind = 0, pid_idmap = 0; pid_t pid = 0; +#ifdef UL_HAVE_PIDFD int fd_parent_pid = -1; +#endif int fd_idmap, fd_bind = -1; sigset_t sigset, oldsigset; int status; @@ -956,13 +958,16 @@ int main(int argc, char *argv[]) sigaddset(&sigset, SIGTERM) != 0 || sigprocmask(SIG_BLOCK, &sigset, &oldsigset) != 0) err(EXIT_FAILURE, _("sigprocmask block failed")); - - /* force child forking before mountspace binding - * so pid_for_children is populated */ - fd_parent_pid = pidfd_open(getpid(), 0); - if (0 > fd_parent_pid) - err(EXIT_FAILURE, _("pidfd_open failed")); - +#ifdef UL_HAVE_PIDFD + if (kill_child_signo != 0) { + /* make a connection to the original process (parent) */ + fd_parent_pid = pidfd_open(getpid(), 0); + if (0 > fd_parent_pid) + err(EXIT_FAILURE, _("pidfd_open failed")); + } +#endif + /* force child forking before mountspace binding so + * pid_for_children is populated */ pid = fork(); switch(pid) { @@ -1017,29 +1022,30 @@ int main(int argc, char *argv[]) if (kill_child_signo != 0) { if (prctl(PR_SET_PDEATHSIG, kill_child_signo) < 0) err(EXIT_FAILURE, "prctl failed"); - - struct pollfd pollfds[1] = { - { - .fd = fd_parent_pid, - .events = POLLIN, - } - }; - - int nfds = poll(pollfds, 1, 0); - if (0 > nfds) - err(EXIT_FAILURE, "poll parent pidfd failed"); - - /* If the child was re-parented before prctl(2) was called, - * the new parent will likely not be interested in the - * precise exit status of the orphan. - */ - if (nfds) - exit(EXIT_FAILURE); +#ifdef UL_HAVE_PIDFD + /* Use poll() to check that there is still the original parent. */ + if (fd_parent_pid != -1) { + struct pollfd pollfds[1] = { + { .fd = fd_parent_pid, .events = POLLIN } + }; + int nfds = poll(pollfds, 1, 0); + + if (0 > nfds) + err(EXIT_FAILURE, "poll parent pidfd failed"); + + /* If the child was re-parented before prctl(2) was called, the + * new parent will likely not be interested in the precise exit + * status of the orphan. + */ + if (nfds) + exit(EXIT_FAILURE); + + close(fd_parent_pid); + fd_parent_pid = -1; + } +#endif } - close(fd_parent_pid); - fd_parent_pid = -1; - if (mapuser != (uid_t) -1 && !usermap) map_id(_PATH_PROC_UIDMAP, mapuser, real_euid);