diff --git a/.clang-format b/.clang-format index 76d91cd6f..4704a0916 100644 --- a/.clang-format +++ b/.clang-format @@ -29,3 +29,4 @@ SpacesInParentheses: 'false' SpacesInSquareBrackets: 'false' Standard: Cpp11 UseTab: Never +SortIncludes: false \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d3fd1aad..f42989000 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,6 +226,11 @@ if(ANDROID) set(ANDROID_PLATFORM_SRC llarp/android/ifaddrs.c) endif() +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(ISOLATE_PROC_SRC llarp/linux/netns.cpp) +endif() + + set(LIB_PLATFORM_SRC # for outpug llarp/logger.cpp @@ -243,6 +248,8 @@ set(LIB_PLATFORM_SRC llarp/threadpool.cpp # for android shim ${ANDROID_PLATFORM_SRC} +# process isolation implementation + ${ISOLATE_PROC_SRC} # tun ${LIBTUNTAP_SRC} # win32 inline procs @@ -437,6 +444,9 @@ else() endif(NOT HAVE_CXX17_FILESYSTEM) add_library(llarpplatform-static STATIC ${LIB_PLATFORM_SRC}) target_link_libraries(llarpplatform-static ${THREAD_LIB}) + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + target_link_libraries(llarpplatform-static -lcap) + endif() if(NOT HAVE_CXX17_FILESYSTEM) target_link_libraries(${STATIC_LIB} ${LIBS} backport-static llarpplatform-static) else() diff --git a/llarp/ev.hpp b/llarp/ev.hpp index 08ece5704..52816242d 100644 --- a/llarp/ev.hpp +++ b/llarp/ev.hpp @@ -64,8 +64,8 @@ namespace llarp // discard entry return true; #else - // writefile - return false; + // writefile + return false; #endif }); /// reset errno diff --git a/llarp/ev_win32.hpp b/llarp/ev_win32.hpp index 0c8a18b96..1a6cf03c7 100644 --- a/llarp/ev_win32.hpp +++ b/llarp/ev_win32.hpp @@ -153,8 +153,8 @@ struct llarp_win32_loop : public llarp_ev_loop ++idx; } while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, ms)); - // tick_listeners inlined since win32 does not - // implement ev_tun + // tick_listeners inlined since win32 does not + // implement ev_tun for(auto& l : udp_listeners) { if(l->tick) diff --git a/llarp/fs.hpp b/llarp/fs.hpp index 9b0e71889..2328ec110 100644 --- a/llarp/fs.hpp +++ b/llarp/fs.hpp @@ -1,6 +1,6 @@ #ifndef LLARP_FS_HPP #define LLARP_FS_HPP - +#include #if defined(WIN32) || defined(_WIN32) #define PATH_SEP "\\" #else @@ -24,4 +24,37 @@ namespace fs = std::filesystem; namespace fs = cpp17::filesystem; #endif +namespace llarp +{ + namespace util + { + typedef std::function< bool(const fs::path &) > PathVisitor; + typedef std::function< void(const fs::path &, PathVisitor) > PathIter; +#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM) + static PathIter IterDir = [](const fs::path &path, PathVisitor visit) { + fs::directory_iterator i(path); + auto itr = fs::begin(i); + while(itr != fs::end(i)) + { + fs::path p = path / *itr; + if(!visit(p)) + return; + ++itr; + } + }; +#else + static PathIter IterDir = [](const fs::path &path, PathVisitor visit) { + fs::directory_iterator i(path); + auto itr = i.begin(); + while(itr != itr.end()) + { + fs::path p = path / *itr; + if(!visit(p)) + return; + ++itr; + } + }; +#endif + } // namespace util +} // namespace llarp #endif // end LLARP_FS_HPP diff --git a/llarp/ip.cpp b/llarp/ip.cpp index 7411515ce..b6485e015 100644 --- a/llarp/ip.cpp +++ b/llarp/ip.cpp @@ -17,7 +17,6 @@ namespace llarp #undef MIN #endif memcpy(buf, pkt.base, sz); - llarp::DumpBufferHex(pkt); return true; } diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index a94f0a9d2..50543fc23 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -184,20 +184,11 @@ struct llarp_nodedb loadSubdir(const fs::path &dir) { ssize_t sz = 0; - fs::directory_iterator i(dir); -#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM) - auto itr = fs::begin(i); - while(itr != fs::end(i)) -#else - auto itr = i.begin(); - while(itr != itr.end()) -#endif - { - if(fs::is_regular_file(itr->path()) && loadfile(*itr)) + llarp::util::IterDir(dir, [&](const fs::path &f) -> bool { + if(fs::is_regular_file(f) && loadfile(f)) sz++; - - ++itr; - } + return true; + }); return sz; } diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 37424e52f..6490f05ab 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -51,7 +51,7 @@ namespace llarp { llarp::LogInfo("isolating network to namespace ", m_NetNS); m_IsolatedWorker = llarp_init_isolated_net_threadpool( - m_Name.c_str(), &SetupIsolatedNetwork, &RunIsolatedMainLoop, this); + m_NetNS.c_str(), &SetupIsolatedNetwork, &RunIsolatedMainLoop, this); m_IsolatedLogic = llarp_init_single_process_logic(m_IsolatedWorker); return true; } diff --git a/llarp/threadpool.cpp b/llarp/threadpool.cpp index 75bd5a365..86b164e15 100644 --- a/llarp/threadpool.cpp +++ b/llarp/threadpool.cpp @@ -15,7 +15,7 @@ #endif #ifdef __linux__ -#include +#include #endif #ifdef _MSC_VER @@ -113,30 +113,23 @@ namespace llarp void IsolatedPool::Spawn(size_t workers, const char *name) { -#ifdef __linux__ IsolatedPool *self = this; - self->m_IsolatedName = name; + self->IsolatedName = name; self->m_IsolatedWorkers = workers; m_isolated = new std::thread([self] { - if(unshare(self->m_flags) == -1) + if(!self->IsolateCurrentProcess()) { - llarp::LogError("unshared failed: ", strerror(errno)); + llarp::LogError("isolation failed: ", strerror(errno)); self->Fail(); + return; } - else + llarp::LogInfo("spawning isolated environment"); + self->Pool::Spawn(self->m_IsolatedWorkers, self->IsolatedName); + if(self->Isolated()) { - llarp::LogInfo("spawning isolated environment"); - self->Pool::Spawn(self->m_IsolatedWorkers, self->m_IsolatedName); - if(self->Isolated()) - { - self->MainLoop(); - } + self->MainLoop(); } }); -#else - llarp::LogError("isolated processes not supported on your platform"); - Pool::Spawn(workers, name); -#endif } void @@ -151,27 +144,51 @@ namespace llarp } } -#ifdef __linux__ - NetIsolatedPool::NetIsolatedPool( + _NetIsolatedPool::_NetIsolatedPool( std::function< bool(void *, bool) > setupNet, std::function< void(void *) > runMain, void *user) - : IsolatedPool(CLONE_NEWNET) + : IsolatedPool(0) + { m_NetSetup = setupNet; m_RunMain = runMain; m_user = user; } -#else - NetIsolatedPool::NetIsolatedPool( - std::function< bool(void *, bool) > setupNet, - std::function< void(void *) > runMain, void *user) - : IsolatedPool(0) + +#ifdef __linux__ + struct LinuxNetNSIsolatedPool : public _NetIsolatedPool { - m_NetSetup = setupNet; - m_RunMain = runMain; - m_user = user; - } + LinuxNetNSIsolatedPool(std::function< bool(void *, bool) > setup, + std::function< void(void *) > run, void *user) + : _NetIsolatedPool(setup, run, user) + { + } + + bool + IsolateNetwork() + { + return llarp::linux::NetNSSwitch(IsolatedName); + } + }; + + typedef LinuxNetNSIsolatedPool NetIsolatedPool; +#define NET_ISOLATION_SUPPORTED #endif + +#if defined(__FreeBSD__) + struct FreeBSDJailedThreadPool : public _NetIsolatedPool + { + bool + IsolateNetwork() + { + // TODO: implement me + return false; + } + }; + typedef FreeBSDJailedThreadPool NetIsolatedPool; +#define NET_ISOLATION_SUPPORTED +#endif + } // namespace thread } // namespace llarp @@ -186,9 +203,17 @@ struct llarp_threadpool setup_net_func setup = nullptr, run_main_func runmain = nullptr, void *user = nullptr) { +#ifdef NET_ISOLATION_SUPPORTED if(isolate) impl = new llarp::thread::NetIsolatedPool(setup, runmain, user); else +#else + if(isolate) + { + llarp::LogError("network isolation not supported"); + return nullptr; + } +#endif impl = new llarp::thread::Pool(); impl->Spawn(workers, name); } diff --git a/llarp/threadpool.hpp b/llarp/threadpool.hpp index 00bf68042..72b5f8634 100644 --- a/llarp/threadpool.hpp +++ b/llarp/threadpool.hpp @@ -66,6 +66,17 @@ namespace llarp void Join(); + /// isolate current thread + /// return true for success + /// return false for failure + /// set errno on fail + /// override me in subclass + virtual bool + IsolateCurrentProcess() + { + return true; + } + // override me to do specific setups after isolation // return true for success virtual bool @@ -82,8 +93,8 @@ namespace llarp std::thread* m_isolated = nullptr; int m_flags; - int m_IsolatedWorkers = 0; - const char* m_IsolatedName = nullptr; + int m_IsolatedWorkers = 0; + const char* IsolatedName = nullptr; virtual void MainLoop() @@ -91,10 +102,20 @@ namespace llarp } }; - struct NetIsolatedPool : public IsolatedPool + struct _NetIsolatedPool : public IsolatedPool { - NetIsolatedPool(std::function< bool(void*, bool) > setupNet, - std::function< void(void*) > runMain, void* user); + _NetIsolatedPool(std::function< bool(void*, bool) > setupNet, + std::function< void(void*) > runMain, void* user); + + /// implement me per platform + virtual bool + IsolateNetwork() = 0; + + bool + IsolateCurrentProcess() + { + return IsolateNetwork(); + } bool Isolated()