Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions cmake/FindSystemd.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ IF (NOT WIN32)
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE SYSTEMD_USER_UNIT_INSTALL_DIR)

execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
--variable=systemd_user_preset_dir systemd
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE SYSTEMD_USER_PRESET_INSTALL_DIR)

execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
--variable=systemd_system_unit_dir systemd
OUTPUT_STRIP_TRAILING_WHITESPACE
Expand All @@ -36,7 +31,6 @@ IF (NOT WIN32)

mark_as_advanced(
SYSTEMD_USER_UNIT_INSTALL_DIR
SYSTEMD_USER_PRESET_INSTALL_DIR
SYSTEMD_SYSTEM_UNIT_INSTALL_DIR
SYSTEMD_MODULES_LOAD_DIR
)
Expand Down
8 changes: 0 additions & 8 deletions cmake/packaging/linux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ if(${SUNSHINE_BUILD_APPIMAGE} OR ${SUNSHINE_BUILD_FLATPAK})
DESTINATION "${SUNSHINE_ASSETS_DIR}/modules-load.d")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/app-${PROJECT_FQDN}.service"
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-app-${PROJECT_FQDN}.preset"
DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user-preset")
else()
find_package(Systemd)
find_package(Udev)
Expand All @@ -33,10 +29,6 @@ else()
if(SYSTEMD_FOUND)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/app-${PROJECT_FQDN}.service"
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service"
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-app-${PROJECT_FQDN}.preset"
DESTINATION "${SYSTEMD_USER_PRESET_INSTALL_DIR}")
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.conf"
DESTINATION "${SYSTEMD_MODULES_LOAD_DIR}")
endif()
Expand Down
2 changes: 0 additions & 2 deletions cmake/prep/special_package_configuration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ elseif(UNIX)

# configure service
configure_file(packaging/linux/app-${PROJECT_FQDN}.service.in app-${PROJECT_FQDN}.service @ONLY)
configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY)
configure_file(packaging/linux/00-app-${PROJECT_FQDN}.preset.in 00-app-${PROJECT_FQDN}.preset @ONLY)

# configure the arch linux pkgbuild
if(${SUNSHINE_CONFIGURE_PKGBUILD})
Expand Down
15 changes: 7 additions & 8 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,21 +447,20 @@ After adding yourself to the group, log out and log back in for the changes to t

#### Services

> [!NOTE]
> Two service unit files are available. Pick "app-dev.lizardbyte.app.Sunshine" for unprivileged XDG Portal
> or X11 capture, otherwise pick "sunshine" for privileged KMS capture.

**Start once**
```bash
systemctl --user start sunshine
systemctl --user start app-dev.lizardbyte.app.Sunshine
```

**Start on boot (privileged; swap names for unprivileged XDG capture)**
**Start on boot**
```bash
systemctl --user --now disable app-dev.lizardbyte.app.Sunshine
systemctl --user --now enable sunshine
systemctl --user --now enable app-dev.lizardbyte.app.Sunshine
```

> [!NOTE]
> The service has been renamed to "app-dev.lizardbyte.app.Sunshine" in order to increase compatibility with
> XDG Desktop Portal, but it is also aliased to "sunshine.service" for convenience.

### macOS
The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone.

Expand Down
17 changes: 10 additions & 7 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,21 @@ sudo usermod -aG input $USER
```

### KMS Streaming fails
If screencasting fails with KMS, you may be using the unprivileged app-dev.lizardbyte.app.Sunshine service unit.
Switch to the privileged sunshine service:
KMS screencasting requires elevated privileges which are not allowed for Flatpak or AppImage packages.
This means that you must install Sunshine using the native package format of your distribution, if available.
KMS capture will soon be phased out in favour of XDG Portal Capture (which works with all package types).

### KMS Streaming; some windows flicker/disappear on KDE Plasma 6.5+
KWin's overlay support interferes with KMS capture. As of KWin 6.5 this is not yet set by default, but
for future versions that enables this by default, you may be able to disable again via a special
[environment variable](https://invent.kde.org/plasma/kwin/-/wikis/Environment-Variables#kwin_use_overlays):

```bash
systemctl --user --now disable app-dev.lizardbyte.app.Sunshine
systemctl --user --now enable sunshine
export KWIN_USE_OVERLAYS=0
```

> [!NOTE]
> The above commands will not work with the AppImage or Flatpak packages, as KMS screencasting
> requires elevated privileges which are not allowed by their respective packaging security policies.
> As an alternative, XDG Portal capture is recommended.
> Disabling overlays will reduce KWin's rendering efficiency. Consider using XDG Portal Capture instead.

### KMS streaming fails on Nvidia GPUs
If KMS screen capture results in a black screen being streamed, you may need to
Expand Down
4 changes: 0 additions & 4 deletions packaging/linux/00-app-dev.lizardbyte.app.Sunshine.preset.in

This file was deleted.

3 changes: 1 addition & 2 deletions packaging/linux/app-dev.lizardbyte.app.Sunshine.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Description=@PROJECT_DESCRIPTION@
StartLimitIntervalSec=500
StartLimitBurst=5
Conflicts=sunshine.service
After=graphical-session.target xdg-desktop-autostart.target xdg-desktop-portal.service

[Service]
Expand All @@ -12,7 +11,7 @@ ExecStartPre=/bin/sleep 5
@SUNSHINE_SERVICE_STOP_COMMAND@
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true

[Install]
WantedBy=graphical-session.target
Alias=sunshine.service
3 changes: 1 addition & 2 deletions packaging/linux/copr/Sunshine.spec
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,8 @@ fi
%caps(cap_sys_admin+p) %{_bindir}/sunshine
%caps(cap_sys_admin+p) %{_bindir}/sunshine-*

# Systemd unit/preset files for user services
# Systemd unit files for user services
%{_userunitdir}/*.service
%{_userpresetdir}/*.preset

# Udev rules
%{_udevrulesdir}/*-sunshine.rules
Expand Down
17 changes: 0 additions & 17 deletions packaging/linux/sunshine.service.in

This file was deleted.

11 changes: 0 additions & 11 deletions src/platform/linux/kmsgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1684,17 +1684,6 @@ namespace platf {
#if defined(SUNSHINE_BUILD_FLATPAK) || defined(SUNSHINE_BUILD_APPIMAGE)
BOOST_LOG((config::video.capture == "kms") ? fatal : error)
<< "AppImage and Flatpak do not support KMS capture. Use another capture method."sv;
#else
{
const std::string kms_msg =
"You must use the 'sunshine' service instead of the 'app-" +
std::string(PROJECT_FQDN) +
"' service for KMS capture.\n"
"Please refer to the official documentation:\n"
" stable: https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html#linux-1\n"
" beta: https://docs.lizardbyte.dev/projects/sunshine/master/md_docs_2getting__started.html#linux-1";
BOOST_LOG((config::video.capture == "kms") ? fatal : error) << kms_msg;
}
#endif
break;
}
Expand Down
37 changes: 37 additions & 0 deletions src/platform/linux/portalgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
#include "vaapi.h"
#include "wayland.h"

#if !defined(__FreeBSD__)
// platform includes
#include <sys/capability.h>
#include <sys/prctl.h>
#endif

namespace {
// Buffer and limit constants
constexpr int SPA_POD_BUFFER_SIZE = 4096;
Expand Down Expand Up @@ -223,12 +229,43 @@ namespace portal {
return 0;
}

void finalize_portal_security() {
#if !defined(__FreeBSD__)
BOOST_LOG(debug) << "Finalizing Portal security: dropping CAP_SYS_ADMIN and resetting dumpable"sv;

cap_t caps = cap_get_proc();
if (!caps) {
BOOST_LOG(error) << "Failed to get process capabilities"sv;
return;
}

std::array<cap_value_t, 1> remove_list {CAP_SYS_ADMIN};

cap_set_flag(caps, CAP_PERMITTED, remove_list.size(), remove_list.data(), CAP_CLEAR);
cap_set_flag(caps, CAP_EFFECTIVE, remove_list.size(), remove_list.data(), CAP_CLEAR);

if (cap_set_proc(caps) != 0) {
BOOST_LOG(error) << "Failed to prune capabilities: "sv << std::strerror(errno);
}
cap_free(caps);

// Reset dumpable AFTER the caps have been pruned to ensure the Portal can
// access /proc/pid/root.
if (prctl(PR_SET_DUMPABLE, 1) != 0) {
BOOST_LOG(error) << "Failed to set PR_SET_DUMPABLE: "sv << std::strerror(errno);
}
#endif
}

int connect_to_portal() {
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, FALSE);
g_autofree gchar *session_path = nullptr;
g_autofree gchar *session_token = nullptr;
create_session_path(conn, nullptr, &session_token);

// Drop CAP_SYS_ADMIN and set DUMPABLE flag to allow XDG /root access
finalize_portal_security();

// Try combined RemoteDesktop + ScreenCast session first
bool use_screencast_only = !try_remote_desktop_session(loop, &session_path, session_token);

Expand Down
Loading