Skip to content

Commit

Permalink
namespace mount tool
Browse files Browse the repository at this point in the history
  • Loading branch information
Hackerl committed Jul 19, 2023
1 parent f6dad5c commit c325504
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 61 deletions.
17 changes: 14 additions & 3 deletions rasp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ DEBUG_SYMBOLS ?= debug
LIB_OUTPUT ?= $(OUTPUT)/lib-$(VERSION)
VCPKG_OVERLAY_PORTS ?= $(abspath overlay-ports)

.PHONY: all help install clean set-version agent-plugin nsenter pangolin jattach JVMProbe python-probe python-loader go-probe go-probe-ebpf node-probe php-probe librasp rasp-server
.PHONY: all help install clean set-version agent-plugin nsenter pangolin jattach JVMProbe python-probe python-loader go-probe go-probe-ebpf node-probe php-probe librasp rasp-server NSMount

all: rasp-$(VERSION).tar.gz rasp-$(VERSION)-debug.tar.gz SHA256SUMS

Expand Down Expand Up @@ -75,6 +75,17 @@ else
endif


NSMount:
cd NSMount && \
mkdir -p build && \
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DSTATIC_BUILD=$(STATIC) \
-DCMAKE_TOOLCHAIN_FILE="$(VCPKG_INSTALLATION_ROOT)/scripts/buildsystems/vcpkg.cmake" \
-DVCPKG_TARGET_TRIPLET=x64-linux-release && \
$(MAKE) -C build


nsenter:
ifeq ($(STATIC), TRUE)
cd util-linux && \
Expand Down Expand Up @@ -396,10 +407,9 @@ else
endif


$(OUTPUT): set-version agent-plugin nsenter pangolin jattach JVMProbe python-probe python-loader go-probe go-probe-ebpf node-probe php-probe rasp-server librasp
$(OUTPUT): set-version agent-plugin nsenter pangolin jattach JVMProbe python-probe python-loader go-probe go-probe-ebpf node-probe php-probe rasp-server librasp NSMount
mkdir -p $(OUTPUT) $(LIB_OUTPUT) $(LIB_OUTPUT)/golang $(LIB_OUTPUT)/java $(LIB_OUTPUT)/node $(LIB_OUTPUT)/php $(LIB_OUTPUT)/python

cp mount_script $(OUTPUT)/mount_script
cp plugin/settings.toml $(OUTPUT)/settings.toml

ifeq ($(STATIC), TRUE)
Expand All @@ -414,6 +424,7 @@ else
cp util-linux/nsenter $(OUTPUT)/nsenter
endif

cp NSMount/bin/NSMount $(LIB_OUTPUT)/NSMount
cp pangolin/bin/pangolin $(LIB_OUTPUT)/pangolin

cp jvm/JVMProbe/output/SmithAgent.jar $(LIB_OUTPUT)/java/SmithAgent.jar
Expand Down
15 changes: 15 additions & 0 deletions rasp/NSMount/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.17)
project(NSMount)

set(CMAKE_CXX_STANDARD 17)

option(STATIC_BUILD "enable static build" OFF)

set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

find_package(Threads REQUIRED)
find_package(zero CONFIG REQUIRED)

add_executable(NSMount main.cpp)
target_link_libraries(NSMount PRIVATE zero::zero Threads::Threads $<$<BOOL:${STATIC_BUILD}>:-static-pie>)
93 changes: 93 additions & 0 deletions rasp/NSMount/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <zero/log.h>
#include <zero/cmdline.h>
#include <sys/mount.h>

int main(int argc, char *argv[]) {
INIT_CONSOLE_LOG(zero::INFO_LEVEL);

zero::Cmdline cmdline;

cmdline.add<int>("pid", "target process id");
cmdline.add<std::filesystem::path>("src", "source path");
cmdline.add<std::filesystem::path>("dst", "destination path");

cmdline.parse(argc, argv);

auto pid = cmdline.get<int>("pid");
auto src = cmdline.get<std::filesystem::path>("src");
auto dst = cmdline.get<std::filesystem::path>("dst");

std::error_code ec;

if (!std::filesystem::exists(src, ec)) {
LOG_ERROR("source path %s not exists[%s]", src.u8string().c_str(), ec.message().c_str());
return -1;
}

std::filesystem::path path = std::filesystem::path("/proc") / std::to_string(pid) / "mounts";
std::ifstream stream(path);

if (!stream.is_open()) {
LOG_ERROR("failed to open %s information[%d]", path.u8string().c_str(), stream.rdstate());
return -1;
}

std::string line;
std::optional<std::filesystem::path> workdir;

while (std::getline(stream, line)) {
std::vector<std::string> tokens = zero::strings::split(line, " ", 5);

if (tokens.size() != 6)
continue;

if (tokens[0] == "overlay" && tokens[1] == "/") {
tokens = zero::strings::split(tokens[3], ",");

auto it = std::find_if(tokens.begin(), tokens.end(), [](const auto &option) {
return zero::strings::startsWith(option, "workdir=");
});

if (it == tokens.end())
continue;

workdir = it->substr(8);
break;
}
}

if (!workdir) {
LOG_ERROR("failed to find workdir of overlay filesystem");
return -1;
}

LOG_INFO("workdir: %s", workdir->u8string().c_str());

std::filesystem::path merged = workdir->parent_path() / "merged";

if (!std::filesystem::exists(merged, ec)) {
LOG_ERROR("directory %s not exists[%s]", merged.u8string().c_str(), ec.message().c_str());
return -1;
}

dst = merged / dst.relative_path();

if (std::filesystem::exists(dst, ec)) {
LOG_WARNING("directory %s already exists", dst.u8string().c_str());
return -1;
}

LOG_INFO("bind %s -> %s", src.u8string().c_str(), dst.u8string().c_str());

if (!std::filesystem::create_directories(dst, ec)) {
LOG_ERROR("create directory %s failed[%s]", dst.u8string().c_str(), ec.message().c_str());
return -1;
}

if (mount(src.u8string().c_str(), dst.u8string().c_str(), "ext4", MS_BIND, nullptr) < 0) {
LOG_ERROR("bind failed[%s]", strerror(errno));
return -1;
}

return 0;
}
12 changes: 12 additions & 0 deletions rasp/NSMount/vcpkg-configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"registries": [
{
"kind": "git",
"repository": "https://github.com/Hackerl/vcpkg-registry",
"baseline": "891208f06ff08441853ffed299cb298f1df3c25e",
"packages": [
"zero"
]
}
]
}
11 changes: 11 additions & 0 deletions rasp/NSMount/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "ns-mount",
"version-string": "1.0.0",
"builtin-baseline": "69efe9cc2df0015f0bb2d37d55acde4a75c9a25b",
"dependencies": [
{
"name": "zero",
"version>=": "1.0.4"
}
]
}
2 changes: 1 addition & 1 deletion rasp/golang-ebpf/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ int main() {
return -1;
}

std::make_shared<aio::ev::Event>(context, bpf_map__fd(skeleton->maps.events))->onPersist(
zero::ptr::makeRef<aio::ev::Event>(context, bpf_map__fd(skeleton->maps.events))->onPersist(
EV_READ,
[=](short what) {
ring_buffer__consume(rb);
Expand Down
3 changes: 1 addition & 2 deletions rasp/librasp/src/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,7 @@ impl RASPComm for ThreadMode {

fn mount(pid: i32, from: &str, to: &str) -> AnyhowResult<()> {
let pid_str = pid.to_string();
let nsenter_str = settings::RASP_NS_ENTER_BIN();
let args = [pid_str.as_str(), from, to, nsenter_str.as_str()];
let args = [pid_str.as_str(), from, to];
return match run_async_process(
std::process::Command::new(settings::RASP_MOUNT_SCRIPT_BIN()).args(args),
) {
Expand Down
2 changes: 1 addition & 1 deletion rasp/librasp/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn RASP_NS_ENTER_BIN() -> String {
format!("{}{}", RASP_BASE_DIR(), "/nsenter")
}
pub fn RASP_MOUNT_SCRIPT_BIN() -> String {
format!("{}{}", RASP_BASE_DIR(), "/mount_script")
format!("{}{}", RASP_BASE_DIR(), "/NSMount")
}

pub fn RASP_LIB_DIR() -> String {
Expand Down
53 changes: 0 additions & 53 deletions rasp/mount_script

This file was deleted.

2 changes: 1 addition & 1 deletion rasp/plugin/README-zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ RASP 插件包含以下部件:
│ ├── python
│ └── rasp_server
├── nsenter
└── mount_script
└── NSMount
```

0 comments on commit c325504

Please sign in to comment.