diff --git a/CMakeLists.txt b/CMakeLists.txt index 17a57fa9..07bf8ea6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,8 +113,10 @@ else() endif() if(${SUNSHINE_ENABLE_DRM}) find_package(LIBDRM) + find_package(LIBCAP) else() set(LIBDRM_FOUND OFF) + set(LIBCAP_FOUND OFF) endif() if(${SUNSHINE_ENABLE_WAYLAND}) find_package(Wayland) @@ -129,10 +131,10 @@ else() include_directories(${X11_INCLUDE_DIR}) list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/x11grab.cpp) endif() - if(LIBDRM_FOUND) + if(LIBDRM_FOUND AND LIBCAP_FOUND) add_compile_definitions(SUNSHINE_BUILD_DRM) - include_directories(${LIBDRM_INCLUDE_DIRS}) - list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES}) + include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS}) + list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES} ${LIBCAP_LIBRARIES}) list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/kmsgrab.cpp) list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1) endif() diff --git a/README.md b/README.md index dea0e76f..539eef46 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ sudo apt install cmake gcc-10 g++-10 libssl-dev libavdevice-dev libboost-thread- KMS allows Sunshine to grab the monitor with lower latency then through X11 ``` -sudo apt install cmake gcc-10 g++-10 libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev +sudo apt install cmake gcc-10 g++-10 libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev ``` ### Compilation: @@ -72,7 +72,7 @@ sunshine needs access to uinput to create mouse and gamepad events: #### Additional Setup for KMS: Please note that `cap_sys_admin` may as well be root, except you don't need to be root to run it. It's necessary to allow Sunshine to use KMS -- `sudo setcap cap_sys_admin+ep sunshine` +- `sudo setcap cap_sys_admin+p sunshine` ### Trouleshooting: - If you get "Could not create Sunshine Gamepad: Permission Denied", ensure you are part of the group "input": diff --git a/appveyor.yml b/appveyor.yml index 02a93587..ce60cc59 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ environment: install: - sh: sudo apt update --ignore-missing - - sh: sudo apt install -y build-essential fakeroot gcc-10 g++-10 cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev + - sh: sudo apt install -y build-essential fakeroot gcc-10 g++-10 cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev - cmd: C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git yasm nasm diffutils make" before_build: diff --git a/cmake/FindLIBCAP.cmake b/cmake/FindLIBCAP.cmake new file mode 100644 index 00000000..80ef7409 --- /dev/null +++ b/cmake/FindLIBCAP.cmake @@ -0,0 +1,21 @@ +# - Try to find Libcap +# Once done this will define +# +# LIBCAP_FOUND - system has Libcap +# LIBCAP_INCLUDE_DIRS - the Libcap include directory +# LIBCAP_LIBRARIES - the libraries needed to use Libcap +# LIBCAP_DEFINITIONS - Compiler switches required for using Libcap + +# Use pkg-config to get the directories and then use these values +# in the find_path() and find_library() calls +find_package(PkgConfig) +pkg_check_modules(PC_LIBCAP libcap) + +set(LIBCAP_DEFINITIONS ${PC_LIBCAP_CFLAGS}) + +find_path(LIBCAP_INCLUDE_DIRS sys/capability.h PATHS ${PC_LIBCAP_INCLUDEDIR} ${PC_LIBCAP_INCLUDE_DIRS}) +find_library(LIBCAP_LIBRARIES NAMES libcap.so PATHS ${PC_LIBCAP_LIBDIR} ${PC_LIBCAP_LIBRARY_DIRS}) +mark_as_advanced(LIBCAP_INCLUDE_DIRS LIBCAP_LIBRARIES) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LIBCAP REQUIRED_VARS LIBCAP_LIBRARIES LIBCAP_INCLUDE_DIRS) diff --git a/gen-deb.in b/gen-deb.in index be81bcff..5d87ba0c 100755 --- a/gen-deb.in +++ b/gen-deb.in @@ -38,7 +38,7 @@ Architecture: amd64 Maintainer: @loki Priority: optional Version: 0.10.2 -Depends: libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0, libboost-log1.67.0 | libboost-log1.71.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2 +Depends: libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0, libboost-log1.67.0 | libboost-log1.71.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap Description: Gamestream host for Moonlight EOF @@ -92,8 +92,8 @@ fi # Ensure Sunshine can grab images from KMS path_to_setcap=$(which setcap) if [ -x "$path_to_setcap" ] ; then - echo "$path_to_setcap cap_sys_admin+ep /usr/bin/sunshine" - $path_to_setcap cap_sys_admin+ep /usr/bin/sunshine + echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine" + $path_to_setcap cap_sys_admin+p /usr/bin/sunshine fi EOF diff --git a/sunshine/platform/linux/kmsgrab.cpp b/sunshine/platform/linux/kmsgrab.cpp index fb3f0517..d0d2bdbb 100644 --- a/sunshine/platform/linux/kmsgrab.cpp +++ b/sunshine/platform/linux/kmsgrab.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -25,6 +26,27 @@ namespace platf { namespace kms { +class cap_sys_admin { +public: + cap_sys_admin() { + caps = cap_get_proc(); + cap_value_t sys_admin = CAP_SYS_ADMIN; + if(cap_set_flag(caps, CAP_EFFECTIVE, 1, &sys_admin, CAP_SET) || cap_set_proc(caps)) { + BOOST_LOG(error) << "Failed to gain CAP_SYS_ADMIN"; + } + } + + ~cap_sys_admin() { + cap_value_t sys_admin = CAP_SYS_ADMIN; + if(cap_set_flag(caps, CAP_EFFECTIVE, 1, &sys_admin, CAP_CLEAR) || cap_set_proc(caps)) { + BOOST_LOG(error) << "Failed to drop CAP_SYS_ADMIN"; + } + cap_free(caps); + } + + cap_t caps; +}; + class wrapper_fb { public: wrapper_fb(drmModeFB *fb) @@ -200,6 +222,7 @@ public: using connector_interal_t = util::safe_ptr; int init(const char *path) { + cap_sys_admin admin; fd.el = open(path, O_RDWR); if(fd.el < 0) { @@ -226,6 +249,7 @@ public: } fb_t fb(plane_t::pointer plane) { + cap_sys_admin admin; auto fb = drmModeGetFB2(fd.el, plane->fb_id); if(fb) { return std::make_unique(fb); @@ -451,7 +475,7 @@ public: if(!fb->handles[0]) { BOOST_LOG(error) - << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+ep sunshine]"sv; + << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+p sunshine]"sv; return -1; } @@ -545,7 +569,7 @@ public: if(!fb->handles[0]) { BOOST_LOG(error) - << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+ep sunshine]"sv; + << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+p sunshine]"sv; return capture_e::error; } @@ -967,7 +991,7 @@ std::vector kms_display_names() { if(!fb->handles[0]) { BOOST_LOG(error) - << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+ep sunshine]"sv; + << "Couldn't get handle for DRM Framebuffer ["sv << plane->fb_id << "]: Possibly not permitted: do [sudo setcap cap_sys_admin+p sunshine]"sv; break; }