summaryrefslogtreecommitdiffstats
path: root/sys-utils/nsenter.c
diff options
context:
space:
mode:
authorKarel Zak2016-12-13 14:44:33 +0100
committerKarel Zak2016-12-13 14:56:48 +0100
commit974cc006f122f36e2187cedb9d3e58dc2d24814c (patch)
treee16075477324618687eddaa2b27af0f443dc063c /sys-utils/nsenter.c
parentbuild-sys: cleanup UL_NCURSES_CHECK (diff)
downloadkernel-qcow2-util-linux-974cc006f122f36e2187cedb9d3e58dc2d24814c.tar.gz
kernel-qcow2-util-linux-974cc006f122f36e2187cedb9d3e58dc2d24814c.tar.xz
kernel-qcow2-util-linux-974cc006f122f36e2187cedb9d3e58dc2d24814c.zip
nsenter: add --all option
Let's make it easy for users to enter target process namespaces. Addresses: https://github.com/karelzak/util-linux/issues/382 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/nsenter.c')
-rw-r--r--sys-utils/nsenter.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c
index f85ace9fc..fc301d9f3 100644
--- a/sys-utils/nsenter.c
+++ b/sys-utils/nsenter.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <grp.h>
+#include <sys/stat.h>
#ifdef HAVE_LIBSELINUX
# include <selinux/selinux.h>
@@ -76,6 +77,7 @@ static void usage(int status)
fputs(_("Run a program with namespaces of other processes.\n"), out);
fputs(USAGE_OPTIONS, out);
+ fputs(_(" -a, --all enter all namespaces\n"), out);
fputs(_(" -t, --target <pid> target process to get namespaces from\n"), out);
fputs(_(" -m, --mount[=<file>] enter mount namespace\n"), out);
fputs(_(" -u, --uts[=<file>] enter UTS namespace (hostname etc)\n"), out);
@@ -143,6 +145,32 @@ static void open_namespace_fd(int nstype, const char *path)
assert(nsfile->nstype);
}
+static int get_ns_ino(const char *path, ino_t *ino)
+{
+ struct stat st;
+
+ if (stat(path, &st) != 0)
+ return -errno;
+ *ino = st.st_ino;
+ return 0;
+}
+
+static int is_same_namespace(pid_t a, pid_t b, const char *type)
+{
+ char path[PATH_MAX];
+ ino_t a_ino, b_ino;
+
+ snprintf(path, sizeof(path), "/proc/%u/%s", a, type);
+ if (get_ns_ino(path, &a_ino) != 0)
+ err(EXIT_FAILURE, _("stat of %s failed"), path);
+
+ snprintf(path, sizeof(path), "/proc/%u/%s", b, type);
+ if (get_ns_ino(path, &b_ino) != 0)
+ err(EXIT_FAILURE, _("stat of %s failed"), path);
+
+ return a_ino == b_ino;
+}
+
static void continue_as_child(void)
{
pid_t child = fork();
@@ -181,6 +209,7 @@ int main(int argc, char *argv[])
OPT_PRESERVE_CRED = CHAR_MAX + 1
};
static const struct option longopts[] = {
+ { "all", no_argument, NULL, 'a' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V'},
{ "target", required_argument, NULL, 't' },
@@ -206,6 +235,7 @@ int main(int argc, char *argv[])
struct namespace_file *nsfile;
int c, pass, namespaces = 0, setgroups_nerrs = 0, preserve_cred = 0;
bool do_rd = false, do_wd = false, force_uid = false, force_gid = false;
+ bool do_all = false;
int do_fork = -1; /* unknown yet */
uid_t uid = 0;
gid_t gid = 0;
@@ -219,7 +249,7 @@ int main(int argc, char *argv[])
atexit(close_stdout);
while ((c =
- getopt_long(argc, argv, "+hVt:m::u::i::n::p::C::U::S:G:r::w::FZ",
+ getopt_long(argc, argv, "+ahVt:m::u::i::n::p::C::U::S:G:r::w::FZ",
longopts, NULL)) != -1) {
switch (c) {
case 'h':
@@ -227,6 +257,9 @@ int main(int argc, char *argv[])
case 'V':
printf(UTIL_LINUX_VERSION);
return EXIT_SUCCESS;
+ case 'a':
+ do_all = true;
+ break;
case 't':
namespace_target_pid =
strtoul_or_err(optarg, _("failed to parse pid"));
@@ -323,6 +356,25 @@ int main(int argc, char *argv[])
freecon(scon);
}
#endif
+
+ if (do_all) {
+ if (!namespace_target_pid)
+ errx(EXIT_FAILURE, _("no target PID specified for --all"));
+ for (nsfile = namespace_files; nsfile->nstype; nsfile++) {
+ if (nsfile->fd >= 0)
+ continue; /* namespace already specified */
+
+ /* It is not permitted to use setns(2) to reenter the caller's
+ * current user namespace; see setns(2) man page for more details.
+ */
+ if (nsfile->nstype & CLONE_NEWUSER
+ && is_same_namespace(getpid(), namespace_target_pid, nsfile->name))
+ continue;
+
+ namespaces |= nsfile->nstype;
+ }
+ }
+
/*
* Open remaining namespace and directory descriptors.
*/