Add kernel namespace detection for bwrap integration
Add detect_bwrap_unshare_args(), which probes the running kernel for which namespace types (user, ipc, pid, net, uts, cgroup) can actually be unshared and returns the matching bwrap --unshare-xxx flags. Each probe forks a throwaway child to call unshare() so the calling process's own namespaces are never touched. Needed because the target device (Android, stock kernel) only supports a subset of namespace types, so bwrap must be invoked with just the flags it can honor. Temporarily wired into -t/--test so it can be exercised on-device ahead of the real bwrap invocation; will be removed once that lands. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -17,7 +17,8 @@ conf_data.set10('ENABLE_TESTS', get_option('enable_tests'))
|
|||||||
configure_file(output : 'config.h', configuration : conf_data)
|
configure_file(output : 'config.h', configuration : conf_data)
|
||||||
|
|
||||||
slocker_lite = executable('slocker_lite',
|
slocker_lite = executable('slocker_lite',
|
||||||
['src/main.cpp', 'src/process.cpp', 'src/oci_image.cpp', 'src/containers_storage.cpp'],
|
['src/main.cpp', 'src/process.cpp', 'src/oci_image.cpp', 'src/containers_storage.cpp',
|
||||||
|
'src/bwrap.cpp'],
|
||||||
include_directories : include_directories('.'),
|
include_directories : include_directories('.'),
|
||||||
dependencies : [fmt_dep, catch2_dep, yaml_dep, archive_dep, json_dep, spdlog_dep],
|
dependencies : [fmt_dep, catch2_dep, yaml_dep, archive_dep, json_dep, spdlog_dep],
|
||||||
install : true)
|
install : true)
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (C) 2026 Viorel Munteanu
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
#include "bwrap.h"
|
||||||
|
|
||||||
|
#include <sched.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct NamespaceProbe {
|
||||||
|
int clone_flag;
|
||||||
|
const char* bwrap_arg;
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<NamespaceProbe, 6> kNamespaceProbes = {{
|
||||||
|
{CLONE_NEWUSER, "--unshare-user", "user"},
|
||||||
|
{CLONE_NEWIPC, "--unshare-ipc", "ipc"},
|
||||||
|
{CLONE_NEWPID, "--unshare-pid", "pid"},
|
||||||
|
{CLONE_NEWNET, "--unshare-net", "net"},
|
||||||
|
{CLONE_NEWUTS, "--unshare-uts", "uts"},
|
||||||
|
{CLONE_NEWCGROUP, "--unshare-cgroup", "cgroup"},
|
||||||
|
}};
|
||||||
|
|
||||||
|
// unshare(2) affects the calling process's own namespaces, so support for each
|
||||||
|
// namespace type is probed in a throwaway forked child rather than the caller.
|
||||||
|
bool kernel_supports_namespace(int clone_flag) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pid == 0) {
|
||||||
|
_exit(unshare(clone_flag) == 0 ? 0 : 1);
|
||||||
|
}
|
||||||
|
int status = 0;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::vector<std::string> detect_bwrap_unshare_args() {
|
||||||
|
std::vector<std::string> args;
|
||||||
|
for (const auto& probe : kNamespaceProbes) {
|
||||||
|
bool supported = kernel_supports_namespace(probe.clone_flag);
|
||||||
|
spdlog::debug("namespace {}: {}", probe.name, supported ? "supported" : "not supported");
|
||||||
|
if (supported) {
|
||||||
|
args.push_back(probe.bwrap_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (C) 2026 Viorel Munteanu
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Probes the running kernel for which Linux namespace types can actually be
|
||||||
|
// unshared and returns the corresponding bwrap --unshare-xxx flags for the
|
||||||
|
// ones that are supported. Intended for kernels with partial namespace
|
||||||
|
// support (e.g. stock Android kernels), where blindly passing every
|
||||||
|
// --unshare-xxx flag to bwrap would make it fail outright.
|
||||||
|
std::vector<std::string> detect_bwrap_unshare_args();
|
||||||
+7
-1
@@ -27,6 +27,7 @@
|
|||||||
#include <spdlog/cfg/env.h>
|
#include <spdlog/cfg/env.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include "bwrap.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "containers_storage.h"
|
#include "containers_storage.h"
|
||||||
#include "oci_image.h"
|
#include "oci_image.h"
|
||||||
@@ -90,7 +91,12 @@ bool apply_log_level(std::string_view name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_tests() { return 0; }
|
int run_tests() {
|
||||||
|
for (const auto& arg : detect_bwrap_unshare_args()) {
|
||||||
|
fmt::print("{}\n", arg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_executable_file(const std::filesystem::path& path) {
|
bool is_executable_file(const std::filesystem::path& path) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
|||||||
Reference in New Issue
Block a user