nsenter: add support for the time namespace

Just as with unshare and lsns this adds time namespace support to
nsenter.

In contrast to unshare nsenter does not have the options '--boottime'
and '--monotonic' as that offset can only be set as long as there have
no processes being started in the corresponding time namespace.

Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
Adrian Reber 2020-03-09 13:02:45 +00:00
parent 40c28f51c9
commit 7f1f0584c2
No known key found for this signature in database
GPG key ID: 82C9378ED3C4906A
2 changed files with 28 additions and 1 deletions

View file

@ -92,6 +92,13 @@ and the discussion of the
flag in flag in
.BR clone (2). .BR clone (2).
.TP .TP
.B time namespace
The process can have a distinct view of
.B CLOCK_MONOTONIC
and/or
.B CLOCK_BOOTTIME
which can be changed using \fI/proc/self/timens_offsets\fP.
.TP
See \fBclone\fP(2) for the exact semantics of the flags. See \fBclone\fP(2) for the exact semantics of the flags.
.SH OPTIONS .SH OPTIONS
Various of the options below that relate to namespaces take an optional Various of the options below that relate to namespaces take an optional
@ -144,6 +151,9 @@ the user namespace
/proc/\fIpid\fR/ns/cgroup /proc/\fIpid\fR/ns/cgroup
the cgroup namespace the cgroup namespace
.TP .TP
/proc/\fIpid\fR/ns/time
the time namespace
.TP
/proc/\fIpid\fR/root /proc/\fIpid\fR/root
the root directory the root directory
.TP .TP
@ -210,6 +220,14 @@ If
is specified, enter the cgroup namespace specified by is specified, enter the cgroup namespace specified by
.IR file . .IR file .
.TP .TP
\fB\-T\fR, \fB\-\-time\fR[=\fIfile\fR]
Enter the time namespace. If no file is specified, enter the time namespace of
the target process.
If
.I file
is specified, enter the time namespace specified by
.IR file .
.TP
\fB\-G\fR, \fB\-\-setgid\fR \fIgid\fR \fB\-G\fR, \fB\-\-setgid\fR \fIgid\fR
Set the group ID which will be used in the entered namespace and drop Set the group ID which will be used in the entered namespace and drop
supplementary groups. supplementary groups.

View file

@ -62,6 +62,7 @@ static struct namespace_file {
{ .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 }, { .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 },
{ .nstype = CLONE_NEWPID, .name = "ns/pid", .fd = -1 }, { .nstype = CLONE_NEWPID, .name = "ns/pid", .fd = -1 },
{ .nstype = CLONE_NEWNS, .name = "ns/mnt", .fd = -1 }, { .nstype = CLONE_NEWNS, .name = "ns/mnt", .fd = -1 },
{ .nstype = CLONE_NEWTIME, .name = "ns/time", .fd = -1 },
{ .nstype = 0, .name = NULL, .fd = -1 } { .nstype = 0, .name = NULL, .fd = -1 }
}; };
@ -86,6 +87,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -p, --pid[=<file>] enter pid namespace\n"), out); fputs(_(" -p, --pid[=<file>] enter pid namespace\n"), out);
fputs(_(" -C, --cgroup[=<file>] enter cgroup namespace\n"), out); fputs(_(" -C, --cgroup[=<file>] enter cgroup namespace\n"), out);
fputs(_(" -U, --user[=<file>] enter user namespace\n"), out); fputs(_(" -U, --user[=<file>] enter user namespace\n"), out);
fputs(_(" -T, --time[=<file>] enter time namespace\n"), out);
fputs(_(" -S, --setuid <uid> set uid in entered namespace\n"), out); fputs(_(" -S, --setuid <uid> set uid in entered namespace\n"), out);
fputs(_(" -G, --setgid <gid> set gid in entered namespace\n"), out); fputs(_(" -G, --setgid <gid> set gid in entered namespace\n"), out);
fputs(_(" --preserve-credentials do not touch uids or gids\n"), out); fputs(_(" --preserve-credentials do not touch uids or gids\n"), out);
@ -219,6 +221,7 @@ int main(int argc, char *argv[])
{ "pid", optional_argument, NULL, 'p' }, { "pid", optional_argument, NULL, 'p' },
{ "user", optional_argument, NULL, 'U' }, { "user", optional_argument, NULL, 'U' },
{ "cgroup", optional_argument, NULL, 'C' }, { "cgroup", optional_argument, NULL, 'C' },
{ "time", optional_argument, NULL, 'T' },
{ "setuid", required_argument, NULL, 'S' }, { "setuid", required_argument, NULL, 'S' },
{ "setgid", required_argument, NULL, 'G' }, { "setgid", required_argument, NULL, 'G' },
{ "root", optional_argument, NULL, 'r' }, { "root", optional_argument, NULL, 'r' },
@ -248,7 +251,7 @@ int main(int argc, char *argv[])
close_stdout_atexit(); close_stdout_atexit();
while ((c = while ((c =
getopt_long(argc, argv, "+ahVt:m::u::i::n::p::C::U::S:G:r::w::FZ", getopt_long(argc, argv, "+ahVt:m::u::i::n::p::C::U::T::S:G:r::w::FZ",
longopts, NULL)) != -1) { longopts, NULL)) != -1) {
switch (c) { switch (c) {
case 'a': case 'a':
@ -300,6 +303,12 @@ int main(int argc, char *argv[])
else else
namespaces |= CLONE_NEWUSER; namespaces |= CLONE_NEWUSER;
break; break;
case 'T':
if (optarg)
open_namespace_fd(CLONE_NEWTIME, optarg);
else
namespaces |= CLONE_NEWTIME;
break;
case 'S': case 'S':
uid = strtoul_or_err(optarg, _("failed to parse uid")); uid = strtoul_or_err(optarg, _("failed to parse uid"));
force_uid = true; force_uid = true;