Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ set(linyaps-box_CPM_LOCAL_PACKAGES_ONLY

# ==============================================================================

if (linyaps-box_HARDENING)
if(linyaps-box_HARDENING)
message(STATUS "applying harden settings")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -Wl,-z,relro -Wl,-z,now")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -pie -Wl,-z,relro -Wl,-z,now")
add_compile_options(-fstack-protector-strong)

if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
Expand Down Expand Up @@ -160,43 +161,62 @@ set(linyaps-box_LIBRARY_SOURCE
src/linyaps_box/impl/table_printer.h
src/linyaps_box/interface.cpp
src/linyaps_box/interface.h
src/linyaps_box/io/epoll.cpp
src/linyaps_box/io/epoll.h
src/linyaps_box/io/forwarder.cpp
src/linyaps_box/io/forwarder.h
src/linyaps_box/printer.cpp
src/linyaps_box/printer.h
src/linyaps_box/runtime.cpp
src/linyaps_box/runtime.h
src/linyaps_box/status_directory.cpp
src/linyaps_box/status_directory.h
src/linyaps_box/terminal.cpp
src/linyaps_box/terminal.h
src/linyaps_box/unixsocket.cpp
src/linyaps_box/unixsocket.h
src/linyaps_box/utils/atomic_write.cpp
src/linyaps_box/utils/atomic_write.h
src/linyaps_box/utils/cgroups.cpp
src/linyaps_box/utils/cgroups.h
src/linyaps_box/utils/close_range.cpp
src/linyaps_box/utils/close_range.h
src/linyaps_box/utils/defer.h
src/linyaps_box/utils/epoll.cpp
src/linyaps_box/utils/epoll.h
src/linyaps_box/utils/file.cpp
src/linyaps_box/utils/file_describer.cpp
src/linyaps_box/utils/file_describer.h
src/linyaps_box/utils/fstat.cpp
src/linyaps_box/utils/fstat.h
src/linyaps_box/utils/file.h
src/linyaps_box/utils/inspect.cpp
src/linyaps_box/utils/inspect.h
src/linyaps_box/utils/ioctl.h
src/linyaps_box/utils/log.cpp
src/linyaps_box/utils/log.h
src/linyaps_box/utils/mkdir.cpp
src/linyaps_box/utils/mkdir.h
src/linyaps_box/utils/mknod.cpp
src/linyaps_box/utils/mknod.h
src/linyaps_box/utils/open_file.cpp
src/linyaps_box/utils/open_file.h
src/linyaps_box/utils/platform.cpp
src/linyaps_box/utils/platform.h
src/linyaps_box/utils/process.cpp
src/linyaps_box/utils/process.h
src/linyaps_box/utils/ringbuffer.cpp
src/linyaps_box/utils/ringbuffer.h
src/linyaps_box/utils/semver.cpp
src/linyaps_box/utils/semver.h
src/linyaps_box/utils/socketpair.cpp
src/linyaps_box/utils/socketpair.h
src/linyaps_box/utils/session.cpp
src/linyaps_box/utils/session.h
src/linyaps_box/utils/signal.cpp
src/linyaps_box/utils/signal.h
src/linyaps_box/utils/socket.cpp
src/linyaps_box/utils/socket.h
src/linyaps_box/utils/span.h
src/linyaps_box/utils/symlink.cpp
src/linyaps_box/utils/symlink.h
src/linyaps_box/utils/touch.cpp
src/linyaps_box/utils/touch.h)
src/linyaps_box/utils/terminal.cpp
src/linyaps_box/utils/terminal.h
src/linyaps_box/utils/utils.h)

set(LINYAPS_BOX_VERSION ${PROJECT_VERSION})

Expand Down Expand Up @@ -240,7 +260,7 @@ if(linyaps-box_ENABLE_CPM)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(CPM)

if (linyaps-box_CPM_LOCAL_PACKAGES_ONLY)
if(linyaps-box_CPM_LOCAL_PACKAGES_ONLY)
set(CPM_USE_LOCAL_PACKAGES ON)
endif()

Expand Down
50 changes: 19 additions & 31 deletions src/linyaps_box/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,12 @@

#include "linyaps_box/command/exec.h"
#include "linyaps_box/command/kill.h"
#include "linyaps_box/command/list.h"

Check warning on line 9 in src/linyaps_box/app.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/command/list.h" not found.
#include "linyaps_box/command/run.h"

Check warning on line 10 in src/linyaps_box/app.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/command/run.h" not found.
#include "linyaps_box/utils/log.h"

Check warning on line 11 in src/linyaps_box/app.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/utils/log.h" not found.
#include "linyaps_box/utils/utils.h"

Check warning on line 12 in src/linyaps_box/app.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/utils/utils.h" not found.
#include "utils/log.h"

namespace {

template<typename... T>
struct subCommand : T...
{
using T::operator()...;
};

template<typename... T>
subCommand(T...) -> subCommand<T...>;

} // namespace

namespace linyaps_box {

// The main function of the ll-box,
Expand Down Expand Up @@ -56,24 +44,24 @@
return opts.global.return_code;
}

return std::visit(subCommand{ [](const command::list_options &options) {
command::list(options);
return 0;
},
[](const command::exec_options &options) -> int {
command::exec(options);
__builtin_unreachable();
},
[](const command::kill_options &options) {
command::kill(options);
return 0;
},
[](const command::run_options &options) {
return command::run(options);
},
[](const std::monostate &) {
return 0;
} },
return std::visit(utils::Overload{ [](const command::list_options &options) {
command::list(options);
return 0;
},
[](const command::exec_options &options) -> int {
command::exec(options);
__builtin_unreachable();
},
[](const command::kill_options &options) {
command::kill(options);
return 0;
},
[](const command::run_options &options) {
return command::run(options);
},
[](const std::monostate &) {
return 0;
} },
opts.subcommand_opt);
} catch (const std::exception &e) {
LINYAPS_BOX_ERR() << "Error: " << e.what();
Expand Down
25 changes: 12 additions & 13 deletions src/linyaps_box/command/exec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,18 @@ void linyaps_box::command::exec(const struct exec_options &options)
if (options.caps) {
const auto &caps = options.caps.value();
auto transform_cap = [&caps](std::vector<cap_value_t> &cap_set) {
std::transform(caps.cbegin(),
caps.cend(),
std::back_inserter(cap_set),
[](const std::string &cap) {
cap_value_t val{ 0 };
if (cap_from_name(cap.c_str(), &val) < 0) {
throw std::system_error(errno,
std::generic_category(),
"cap_from_name");
}

return val;
});
std::transform(
caps.cbegin(),
caps.cend(),
std::back_inserter(cap_set),
[](const std::string &cap) {
cap_value_t val{ 0 };
if (cap_from_name(cap.c_str(), &val) < 0) {
throw std::system_error(errno, std::system_category(), "cap_from_name");
}

return val;
});
};

transform_cap(proc.capabilities.effective);
Expand Down
28 changes: 28 additions & 0 deletions src/linyaps_box/command/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "linyaps_box/command/options.h"

Check warning on line 5 in src/linyaps_box/command/options.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/command/options.h" not found.

#include "linyaps_box/config.h"

Check warning on line 7 in src/linyaps_box/command/options.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/config.h" not found.
#include "linyaps_box/utils/file.h"

Check warning on line 8 in src/linyaps_box/command/options.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/utils/file.h" not found.
#include "linyaps_box/version.h"

Check warning on line 9 in src/linyaps_box/command/options.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "linyaps_box/version.h" not found.

#include <CLI/CLI.hpp>

Check warning on line 11 in src/linyaps_box/command/options.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <CLI/CLI.hpp> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <unistd.h>

Expand Down Expand Up @@ -66,6 +67,26 @@
"Pass N additional file descriptors to the container")
->default_val(0);

auto socket_check = [](const std::string &str) {
try {
auto ret = utils::lstat(str);
if (!utils::is_type(ret.st_mode, std::filesystem::file_type::socket)) {
return "console-socket must be a socket";
}
} catch (const std::system_error &e) {
return e.what();
}

return "";
};

cmd_run->add_option("--console-socket",
run_opt.console_socket,
"Path to an unix socket that will receive the master end of the console's "
"pseudoterminal")
->type_name("SOCKET")
->check(socket_check);

exec_options exec_opt{ options.global };
auto *cmd_exec = app.add_subcommand("exec", "Exec a command in a running container")
->positionals_at_end();
Expand All @@ -86,6 +107,13 @@
return "";
},
"env_check");
cmd_exec->add_option("--console-socket",
exec_opt.console_socket,
"Path to an unix socket that will receive the master end of the console's "
"pseudoterminal")
->type_name("SOCKET")
->check(socket_check);
cmd_exec->add_flag("--tty", exec_opt.tty, "Allocate a pseudo-TTY")->default_val(false);
// TODO: enable capabilities and no_new_privs support after rewrite exec,
// cmd_exec->add_option("-c,--cap", options.exec.caps, "Set capabilities")
// ->check(
Expand Down
5 changes: 4 additions & 1 deletion src/linyaps_box/command/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ struct exec_options
}

bool no_new_privs;
bool tty;
std::reference_wrapper<global_options> global_;
std::vector<std::string> command;
std::string user;
std::optional<std::vector<std::string>> caps;
std::string ID;
std::optional<std::string> cwd;
std::optional<std::vector<std::string>> envs;
std::optional<std::string> console_socket;
};

struct run_options
Expand All @@ -62,7 +64,8 @@ struct run_options
std::string ID;
std::string bundle;
std::string config;
int preserve_fds;
std::string console_socket;
int preserve_fds{};
};

struct kill_options
Expand Down
12 changes: 9 additions & 3 deletions src/linyaps_box/command/run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ auto linyaps_box::command::run(const struct run_options &options) -> int
std::make_unique<impl::status_directory>(options.global_.get().root);
runtime_t runtime(std::move(dir));
const create_container_options_t create_container_options{ options.global_.get().manager,
options.preserve_fds,
options.ID,
options.bundle,
options.config };

auto container = runtime.create_container(create_container_options);
return container.run(container.get_config().process);

run_container_options_t run_options;
run_options.preserve_fds = options.preserve_fds;

if (container.get_config().process.terminal && !options.console_socket.empty()) {
run_options.console_socket = unixSocketClient::connect(options.console_socket);
}

return container.run(std::move(run_options));
}
61 changes: 45 additions & 16 deletions src/linyaps_box/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ namespace {

// This function is used to parse the mount options from the config file and it only will be called
// once.
auto parse_mount_options(const std::vector<std::string> &options)
-> std::tuple<unsigned long, unsigned long, std::uint8_t, std::string>
auto parse_mount_options(const std::vector<std::string> &options) -> std::
tuple<unsigned long, unsigned long, linyaps_box::config::mount_t::extension, std::string>
{
const std::unordered_map<std::string_view, unsigned long> propagation_flags_map{
{ "rprivate", MS_PRIVATE | MS_REC }, { "private", MS_PRIVATE },
Expand Down Expand Up @@ -62,12 +62,15 @@ auto parse_mount_options(const std::vector<std::string> &options)
{ "symfollow", LINGYAPS_MS_NOSYMFOLLOW },
};

const std::unordered_map<std::string_view, std::uint8_t> extra_flags_map{
{ "copy-symlink", linyaps_box::config::mount_t::COPY_SYMLINK }
};
const std::unordered_map<std::string_view, linyaps_box::config::mount_t::extension>
extra_flags_map{ { "copy-symlink",
linyaps_box::config::mount_t::extension::COPY_SYMLINK } };

unsigned long flags = 0;
std::uint8_t extra_flags = 0;
linyaps_box::config::mount_t::extension extra_flags{
linyaps_box::config::mount_t::extension::NONE
};

unsigned long propagation_flags = 0;
std::stringstream data;

Expand Down Expand Up @@ -209,19 +212,19 @@ auto parse_linux(const nlohmann::json &obj, const nlohmann::json::json_pointer &
linyaps_box::config::linux_t::namespace_t n;
auto type = json["type"].get<std::string>();
if (type == "pid") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::PID;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::PID;
} else if (type == "network") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::NET;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::NET;
} else if (type == "ipc") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::IPC;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::IPC;
} else if (type == "uts") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::UTS;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::UTS;
} else if (type == "mount") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::MOUNT;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::MOUNT;
} else if (type == "user") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::USER;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::USER;
} else if (type == "cgroup") {
n.type = linyaps_box::config::linux_t::namespace_t::type_t::CGROUP;
n.type_ = linyaps_box::config::linux_t::namespace_t::type::CGROUP;
} else {
throw std::runtime_error("unsupported namespace type: " + type);
}
Expand Down Expand Up @@ -300,8 +303,10 @@ auto parse_1_2_0(const nlohmann::json &j) -> linyaps_box::config

// https://github.com/opencontainers/runtime-spec/blob/09fcb39bb7185b46dfb206bc8f3fea914c674779/config.md?plain=1#L245
if (cfg.process.terminal && j.contains(ptr / "process" / "consoleSize")) {
cfg.process.console.height = j[ptr / "process" / "consoleSize" / "height"].get<uint>();
cfg.process.console.width = j[ptr / "process" / "consoleSize" / "width"].get<uint>();
cfg.process.console_size = linyaps_box::config::process_t::console_size_t{
j[ptr / "process" / "consoleSize" / "height"].get<unsigned short>(),
j[ptr / "process" / "consoleSize" / "width"].get<unsigned short>()
};
}

cfg.process.cwd = j[ptr / "process" / "cwd"].get<std::string>();
Expand Down Expand Up @@ -427,7 +432,7 @@ auto parse_1_2_0(const nlohmann::json &j) -> linyaps_box::config
const auto it = m.find("options");
if (it != m.end()) {
auto options = it->get<std::vector<std::string>>();
std::tie(mount.flags, mount.propagation_flags, mount.extra_flags, mount.data) =
std::tie(mount.flags, mount.propagation_flags, mount.extension_flags, mount.data) =
parse_mount_options(options);
}

Expand Down Expand Up @@ -465,3 +470,27 @@ linyaps_box::config linyaps_box::config::parse(std::istream &is)
auto j = nlohmann::json::parse(is);
return parse_1_2_0(j);
}

std::string linyaps_box::to_string(linyaps_box::config::linux_t::namespace_t::type type) noexcept
{
switch (type) {
case config::linux_t::namespace_t::type::NONE:
return "none";
case config::linux_t::namespace_t::type::IPC:
return "ipc";
case config::linux_t::namespace_t::type::UTS:
return "uts";
case config::linux_t::namespace_t::type::MOUNT:
return "mount";
case config::linux_t::namespace_t::type::PID:
return "pid";
case config::linux_t::namespace_t::type::NET:
return "net";
case config::linux_t::namespace_t::type::USER:
return "user";
case config::linux_t::namespace_t::type::CGROUP:
return "cgroup";
}

__builtin_unreachable();
}
Loading