Skip to content

Commit 699a816

Browse files
committed
ostree: Add command admin nsenter
1 parent 97efc44 commit 699a816

File tree

4 files changed

+133
-5
lines changed

4 files changed

+133
-5
lines changed

Makefile-ostree.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ ostree_SOURCES += \
8686
src/ostree/ot-admin-builtin-upgrade.c \
8787
src/ostree/ot-admin-builtin-unlock.c \
8888
src/ostree/ot-admin-builtin-state-overlay.c \
89+
src/ostree/ot-admin-builtin-nsenter.c \
8990
src/ostree/ot-admin-builtins.h \
9091
src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \
9192
src/ostree/ot-admin-instutil-builtin-set-kargs.c \
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (C) 2024 Colin Walters <walters@verbum.org>
3+
*
4+
* SPDX-License-Identifier: LGPL-2.0+
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
18+
*
19+
* Author: Misaki Kasumi <misakikasumi@outlook.com>
20+
*/
21+
22+
#include "config.h"
23+
24+
#include "libglnx.h"
25+
#include "ostree.h"
26+
#include "ot-admin-builtins.h"
27+
#include "ot-admin-functions.h"
28+
29+
#include <spawn.h>
30+
#include <sys/wait.h>
31+
32+
static gboolean opt_lock;
33+
static gboolean opt_exec;
34+
35+
static GOptionEntry options[] = {
36+
{ "lock", 0, 0, G_OPTION_ARG_NONE, &opt_lock,
37+
"Make /sysroot writable in the mount namespace and acquire an exclusive multi-process write lock", NULL },
38+
{ "exec", 0, 0, G_OPTION_ARG_NONE, &opt_exec,
39+
"Replace the process instead of spawning the program as child", NULL},
40+
{ NULL } };
41+
42+
gboolean
43+
ot_admin_builtin_nsenter (int argc, char **argv, OstreeCommandInvocation *invocation,
44+
GCancellable *cancellable, GError **error)
45+
{
46+
g_autoptr (GOptionContext) context = NULL;
47+
g_autoptr (OstreeSysroot) sysroot = NULL;
48+
g_autofree char **arguments = NULL;
49+
50+
context = g_option_context_new ("[PROGRAM [ARGUMENTS...]]");
51+
52+
int new_argc = 0;
53+
char **new_argv = NULL;
54+
55+
for (int i = 1; i < argc; i++)
56+
{
57+
if (g_str_equal (argv[i], "--"))
58+
{
59+
new_argc = argc - i;
60+
argc = i;
61+
new_argv = argv + i;
62+
argv[i] = NULL;
63+
break;
64+
}
65+
}
66+
67+
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
68+
OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, invocation, &sysroot,
69+
cancellable, error))
70+
return FALSE;
71+
72+
if (new_argv)
73+
{
74+
argc = new_argc;
75+
argv = new_argv;
76+
}
77+
if (argc <= 1)
78+
{
79+
arguments = g_malloc_n (2, sizeof (char *));
80+
if ((arguments[0] = getenv ("SHELL")) == NULL)
81+
arguments[0] = "/bin/sh";
82+
arguments[1] = NULL;
83+
}
84+
else
85+
{
86+
arguments = g_malloc_n (argc, sizeof (char *));
87+
memcpy (arguments, argv + 1, (argc - 1) * sizeof (char *));
88+
arguments[argc - 1] = NULL;
89+
}
90+
91+
if (opt_lock)
92+
{
93+
if (opt_exec)
94+
return glnx_throw (error, "cannot specify both --lock and --exec");
95+
if (!ostree_sysroot_lock (sysroot, error))
96+
return FALSE;
97+
}
98+
99+
pid_t child_pid;
100+
if (opt_exec)
101+
{
102+
if (execvp (arguments[0], arguments) < 0)
103+
return glnx_throw_errno_prefix (error, "execvp");
104+
}
105+
else
106+
{
107+
if (posix_spawnp (&child_pid, arguments[0], NULL, NULL, arguments, environ) != 0)
108+
return glnx_throw_errno_prefix (error, "posix_spawnp");
109+
}
110+
111+
int status;
112+
while (waitpid (child_pid, &status, 0) < 0)
113+
{
114+
if (errno != EINTR)
115+
return glnx_throw_errno_prefix (error, "waitpid");
116+
}
117+
118+
if (opt_lock)
119+
ostree_sysroot_unlock (sysroot);
120+
121+
if (!WIFEXITED (status))
122+
return glnx_throw (error, "child process killed by signal");
123+
124+
int exit_status = WEXITSTATUS (status);
125+
if (exit_status != EXIT_SUCCESS)
126+
exit (exit_status);
127+
128+
return TRUE;
129+
}

src/ostree/ot-admin-builtins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ BUILTINPROTO (kargs);
5151
BUILTINPROTO (post_copy);
5252
BUILTINPROTO (lock_finalization);
5353
BUILTINPROTO (state_overlay);
54+
BUILTINPROTO (nsenter);
5455

5556
#undef BUILTINPROTO
5657

src/ostree/ot-builtin-admin.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ static OstreeCommand admin_subcommands[] = {
7070
{ "upgrade", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_upgrade,
7171
"Construct new tree from current origin and deploy it, if it changed" },
7272
{ "kargs", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_kargs, "Change kernel arguments" },
73+
{"nsenter", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, ot_admin_builtin_nsenter,
74+
"Run program in the mount namespace where /sysroot is present"},
7375
{ NULL, 0, NULL, NULL }
7476
};
7577

@@ -121,11 +123,6 @@ ostree_builtin_admin (int argc, char **argv, OstreeCommandInvocation *invocation
121123
}
122124
}
123125

124-
else if (g_str_equal (argv[in], "--"))
125-
{
126-
break;
127-
}
128-
129126
argv[out] = argv[in];
130127
}
131128

0 commit comments

Comments
 (0)