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)
|
||||
|
||||
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('.'),
|
||||
dependencies : [fmt_dep, catch2_dep, yaml_dep, archive_dep, json_dep, spdlog_dep],
|
||||
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/spdlog.h>
|
||||
|
||||
#include "bwrap.h"
|
||||
#include "config.h"
|
||||
#include "containers_storage.h"
|
||||
#include "oci_image.h"
|
||||
@@ -90,7 +91,12 @@ bool apply_log_level(std::string_view name) {
|
||||
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) {
|
||||
std::error_code ec;
|
||||
|
||||
Reference in New Issue
Block a user