diff --git a/Makefile-ostree.am b/Makefile-ostree.am index d2447ffe9d..3df930de53 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -86,6 +86,7 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-unlock.c \ src/ostree/ot-admin-builtin-state-overlay.c \ + src/ostree/ot-admin-builtin-nsenter.c \ src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \ src/ostree/ot-admin-instutil-builtin-set-kargs.c \ diff --git a/src/ostree/ot-admin-builtin-nsenter.c b/src/ostree/ot-admin-builtin-nsenter.c new file mode 100644 index 0000000000..463c991b8d --- /dev/null +++ b/src/ostree/ot-admin-builtin-nsenter.c @@ -0,0 +1,122 @@ +/* +* Copyright (C) 2024 Colin Walters + * + * SPDX-License-Identifier: LGPL-2.0+ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Misaki Kasumi + */ + +#include "config.h" + +#include "libglnx.h" +#include "ostree.h" +#include "ot-admin-builtins.h" +#include "ot-admin-functions.h" + +#include +#include + +static gboolean opt_lock; + +static GOptionEntry options[] = { + { "lock", 0, 0, G_OPTION_ARG_NONE, &opt_lock, + "Make /sysroot writable in the mount namespace and acquire an exclusive multi-process write lock", NULL }, + { NULL } }; + +gboolean +ot_admin_builtin_nsenter (int argc, char **argv, OstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + g_autoptr (GOptionContext) context = NULL; + g_autoptr (OstreeSysroot) sysroot = NULL; + g_autofree char **arguments = NULL; + + context = g_option_context_new ("[PROGRAM [ARGUMENTS...]]"); + + int new_argc = argc; + char **new_argv = argv; + + for (int i = 1; i < argc; i++) + { + if (g_str_equal (argv[i], "--")) + { + new_argc -= i; + argc = i; + new_argv = argv + i; + argv[i] = NULL; + break; + } + } + + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, invocation, &sysroot, + cancellable, error)) + return FALSE; + + argc = new_argc; + argv = new_argv; + if (argc <= 1) + { + arguments = g_malloc_n (2, sizeof (char *)); + if ((arguments[0] = getenv ("SHELL")) == NULL) + arguments[0] = "/bin/sh"; + arguments[1] = NULL; + } + else + { + arguments = g_malloc_n (argc, sizeof (char *)); + memcpy (arguments, argv + 1, (argc - 1) * sizeof (char *)); + arguments[argc - 1] = NULL; + } + + if (opt_lock) + { + if (!ostree_sysroot_lock (sysroot, error)) + return FALSE; + } + + pid_t child_pid; + if (posix_spawnp (&child_pid, arguments[0], NULL, NULL, arguments, environ) != 0) + { + glnx_throw_errno_prefix (error, "posix_spawnp"); + return FALSE; + } + + int status; + while (waitpid (child_pid, &status, 0) < 0) + { + if (errno != EINTR) + { + glnx_throw_errno_prefix (error, "waitpid"); + return FALSE; + } + } + + if (opt_lock) + ostree_sysroot_unlock (sysroot); + + if (!WIFEXITED (status)) + { + glnx_throw (error, "child process killed by signal"); + return FALSE; + } + + int exit_status = WEXITSTATUS (status); + if (exit_status != EXIT_SUCCESS) + exit (exit_status); + + return TRUE; +} diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h index cd1472bf3d..9f19345ffd 100644 --- a/src/ostree/ot-admin-builtins.h +++ b/src/ostree/ot-admin-builtins.h @@ -51,6 +51,7 @@ BUILTINPROTO (kargs); BUILTINPROTO (post_copy); BUILTINPROTO (lock_finalization); BUILTINPROTO (state_overlay); +BUILTINPROTO (nsenter); #undef BUILTINPROTO diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index 53face6a2d..b5f0395c15 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -70,6 +70,8 @@ static OstreeCommand admin_subcommands[] = { { "upgrade", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_upgrade, "Construct new tree from current origin and deploy it, if it changed" }, { "kargs", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_kargs, "Change kernel arguments" }, + {"nsenter", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, ot_admin_builtin_nsenter, + "Run program in the mount namespace where /sysroot is present"}, { NULL, 0, NULL, NULL } }; @@ -121,11 +123,6 @@ ostree_builtin_admin (int argc, char **argv, OstreeCommandInvocation *invocation } } - else if (g_str_equal (argv[in], "--")) - { - break; - } - argv[out] = argv[in]; }