kmsgrab: Only gain effective CAP_SYS_ADMIN when needed

This commit is contained in:
David Rosca 2021-09-04 11:45:57 +02:00
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() endif()
if(${SUNSHINE_ENABLE_DRM}) if(${SUNSHINE_ENABLE_DRM})
find_package(LIBDRM) find_package(LIBDRM)
find_package(LIBCAP)
else() else()
set(LIBDRM_FOUND OFF) set(LIBDRM_FOUND OFF)
set(LIBCAP_FOUND OFF)
endif() endif()
if(${SUNSHINE_ENABLE_WAYLAND}) if(${SUNSHINE_ENABLE_WAYLAND})
find_package(Wayland) find_package(Wayland)
@ -129,10 +131,10 @@ else()
include_directories(${X11_INCLUDE_DIR}) include_directories(${X11_INCLUDE_DIR})
list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/x11grab.cpp) list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/x11grab.cpp)
endif() endif()
if(LIBDRM_FOUND) if(LIBDRM_FOUND AND LIBCAP_FOUND)
add_compile_definitions(SUNSHINE_BUILD_DRM) add_compile_definitions(SUNSHINE_BUILD_DRM)
include_directories(${LIBDRM_INCLUDE_DIRS}) include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS})
list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES}) list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES} ${LIBCAP_LIBRARIES})
list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/kmsgrab.cpp) list(APPEND PLATFORM_TARGET_FILES sunshine/platform/linux/kmsgrab.cpp)
list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1) list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1)
endif() 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 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: ### Compilation:
@ -72,7 +72,7 @@ sunshine needs access to uinput to create mouse and gamepad events:
#### Additional Setup for KMS: #### 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. 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 It's necessary to allow Sunshine to use KMS
- `sudo setcap cap_sys_admin+ep sunshine` - `sudo setcap cap_sys_admin+p sunshine`
### Trouleshooting: ### Trouleshooting:
- If you get "Could not create Sunshine Gamepad: Permission Denied", ensure you are part of the group "input": - 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: install:
- sh: sudo apt update --ignore-missing - 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" - 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: 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 Maintainer: @loki
Priority: optional Priority: optional
Version: 0.10.2 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 Description: Gamestream host for Moonlight
EOF EOF
@ -92,8 +92,8 @@ fi
# Ensure Sunshine can grab images from KMS # Ensure Sunshine can grab images from KMS
path_to_setcap=$(which setcap) path_to_setcap=$(which setcap)
if [ -x "$path_to_setcap" ] ; then if [ -x "$path_to_setcap" ] ; then
echo "$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+ep /usr/bin/sunshine $path_to_setcap cap_sys_admin+p /usr/bin/sunshine
fi fi
EOF EOF

View file

@ -4,6 +4,7 @@
#include <unistd.h> #include <unistd.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <sys/capability.h>
#include <filesystem> #include <filesystem>
@ -25,6 +26,27 @@ namespace platf {
namespace kms { 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 { class wrapper_fb {
public: public:
wrapper_fb(drmModeFB *fb) wrapper_fb(drmModeFB *fb)
@ -200,6 +222,7 @@ public:
using connector_interal_t = util::safe_ptr<drmModeConnector, drmModeFreeConnector>; using connector_interal_t = util::safe_ptr<drmModeConnector, drmModeFreeConnector>;
int init(const char *path) { int init(const char *path) {
cap_sys_admin admin;
fd.el = open(path, O_RDWR); fd.el = open(path, O_RDWR);
if(fd.el < 0) { if(fd.el < 0) {
@ -226,6 +249,7 @@ public:
} }
fb_t fb(plane_t::pointer plane) { fb_t fb(plane_t::pointer plane) {
cap_sys_admin admin;
auto fb = drmModeGetFB2(fd.el, plane->fb_id); auto fb = drmModeGetFB2(fd.el, plane->fb_id);
if(fb) { if(fb) {
return std::make_unique<wrapper_fb>(fb); return std::make_unique<wrapper_fb>(fb);
@ -451,7 +475,7 @@ public:
if(!fb->handles[0]) { if(!fb->handles[0]) {
BOOST_LOG(error) 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; return -1;
} }
@ -545,7 +569,7 @@ public:
if(!fb->handles[0]) { if(!fb->handles[0]) {
BOOST_LOG(error) 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; return capture_e::error;
} }
@ -967,7 +991,7 @@ std::vector<std::string> kms_display_names() {
if(!fb->handles[0]) { if(!fb->handles[0]) {
BOOST_LOG(error) 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; break;
} }