kmsgrab: Only gain effective CAP_SYS_ADMIN when needed

This commit is contained in:
David Rosca 2021-09-04 11:45:57 +02:00
parent 302b61090b
commit 6309f478a2
No known key found for this signature in database
GPG Key ID: EBC3FC294452C6D8
6 changed files with 59 additions and 12 deletions

View File

@ -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()

View File

@ -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":

View File

@ -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:

21
cmake/FindLIBCAP.cmake Normal file
View File

@ -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)

View File

@ -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

View File

@ -4,6 +4,7 @@
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <sys/capability.h>
#include <filesystem>
@ -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<drmModeConnector, drmModeFreeConnector>;
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<wrapper_fb>(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<std::string> 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;
}