From b3f1ba196c384e3d96f84862a1e6cf21311a9cef Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Mar 2026 04:40:30 -0500 Subject: Check CAP_SYS_ADMIN at runtime before negotiating FUSE passthrough Negotiating passthrough without the capability caused Wine/Proton DLL loading failures (SKSE plugins returning error 0x36). Now checks the process's effective capability set via libcap before telling the kernel we want passthrough. Also adds qt.conf for AT_SECURE compatibility. Co-Authored-By: Claude Opus 4.6 --- src/src/CMakeLists.txt | 3 +++ src/src/vfs/mo2filesystem.cpp | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/src/CMakeLists.txt b/src/src/CMakeLists.txt index d7a7642..fa5d658 100644 --- a/src/src/CMakeLists.txt +++ b/src/src/CMakeLists.txt @@ -10,6 +10,7 @@ find_package(Boost CONFIG REQUIRED COMPONENTS find_package(spdlog CONFIG REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(FUSE3 REQUIRED IMPORTED_TARGET fuse3) +pkg_check_modules(LIBCAP REQUIRED IMPORTED_TARGET libcap) find_package(Threads REQUIRED) qt_standard_project_setup() @@ -110,6 +111,8 @@ target_link_libraries(organizer PRIVATE spdlog::spdlog_header_only # FUSE3 (low-level API) PkgConfig::FUSE3 + # libcap (runtime capability check for passthrough) + PkgConfig::LIBCAP # Linux system libs dl) diff --git a/src/src/vfs/mo2filesystem.cpp b/src/src/vfs/mo2filesystem.cpp index 6c8cb87..908c5bb 100644 --- a/src/src/vfs/mo2filesystem.cpp +++ b/src/src/vfs/mo2filesystem.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -573,11 +574,29 @@ void mo2_init(void* userdata, struct fuse_conn_info* conn) // Requires: kernel 6.9+, libfuse 3.16+, CAP_SYS_ADMIN on the binary. ctx->passthrough_active = false; if constexpr (FUSE_CAP_PASSTHROUGH != 0) { - if (ctx->passthrough_requested && + // Check if the process actually has CAP_SYS_ADMIN in its effective set. + // Without it, fuse_passthrough_open will fail with EPERM, and negotiating + // passthrough at the kernel level can break Wine/Proton DLL loading. + bool hasCap = false; + { + cap_t caps = cap_get_proc(); + if (caps) { + cap_flag_value_t val = CAP_CLEAR; + cap_get_flag(caps, CAP_SYS_ADMIN, CAP_EFFECTIVE, &val); + hasCap = (val == CAP_SET); + cap_free(caps); + } + } + + if (ctx->passthrough_requested && hasCap && (conn->capable & FUSE_CAP_PASSTHROUGH)) { conn->want |= FUSE_CAP_PASSTHROUGH; ctx->passthrough_active = true; std::fprintf(stderr, "[VFS] FUSE passthrough enabled (kernel supports it)\n"); + } else if (ctx->passthrough_requested && !hasCap) { + std::fprintf(stderr, + "[VFS] FUSE passthrough requested but process lacks " + "CAP_SYS_ADMIN. Falling back to userspace I/O.\n"); } else if (ctx->passthrough_requested) { std::fprintf(stderr, "[VFS] FUSE passthrough requested but NOT supported by kernel " -- cgit v1.3.1