Bug 522093 - KRDP no longer works after upgrading to 6.7.0
Summary: KRDP no longer works after upgrading to 6.7.0
Status: RESOLVED DUPLICATE of bug 521776
Alias: None
Product: KRdp
Classification: Plasma
Component: general (other bugs)
Version First Reported In: 6.7.0
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Unassigned bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-06-24 01:41 UTC by walterjbrame
Modified: 2026-07-08 22:02 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description walterjbrame 2026-06-24 01:41:29 UTC
# Bug report for bugs.kde.org

File at: https://bugs.kde.org/enter_bug.cgi?product=KRdp

- **Product:** KRdp
- **Component:** general
- **Version:** 6.7.0
- **Severity:** normal (regression)
- **OS:** Linux (reproducible on any distro; specifics below are Fedora 44)

---

## Summary

`NoNewPrivileges=true`, added to `app-org.kde.krdpserver.service` in commit `8e1de600a6ea4fcb1662508626da2cf0499f9734` ("Set NoNewPrivileges on the krdpserver systemd service"), breaks the `SystemUserEnabled=true` ("log in with your Linux account password") authentication path entirely. Every connection attempt fails PAM authentication regardless of whether the correct password is supplied, because the kernel-enforced `no_new_privs` flag prevents the setuid-root `unix_chkpwd` helper (which `pam_unix` depends on) from escalating privilege to read `/etc/shadow`.

This is a regression introduced between krdp 6.6.5 and 6.7.0. `SystemUserEnabled=true` worked correctly on 6.6.5 and has not changed; only the systemd unit changed.

## Environment

- krdp / krdp-libs: 6.7.0-1.fc44 (regression; 6.6.5-1.fc44 was the last known-working version)
- plasma-workspace: 6.7.0-1.fc44
- Distro: Fedora 44 (KDE Plasma 6.7.0 spin)
- systemd: 259.6-1.fc44
- pam: 1.7.2-1.fc44
- Desktop session: Wayland, KWin
- `/etc/shadow` permissions: `----------` (mode 000), owner root:root — standard Fedora default, not customized
- `/usr/bin/unix_chkpwd` permissions: `-rwsr-xr-x root root` — setuid-root, standard package default, not customized

## Steps to Reproduce

1. Install/upgrade to krdp 6.7.0 (e.g. via a routine `dnf upgrade` that pulls in plasma-workspace/krdp 6.7.0 together, as happens on Fedora).
2. In `~/.config/krdpserverrc`, set `SystemUserEnabled=true` under `[General]` (this is the "use my system account password" toggle, settable via the Remote Desktop KCM or directly).
3. Restart the server: `systemctl --user restart app-org.kde.krdpserver.service`.
4. From another machine, connect with an RDP client (tested with KDE's RDP client) using the correct username and the correct, current account password.
5. Observe the connection is rejected during authentication, every time, with the correct password.

## Observed Result

Every attempt fails identically. Relevant `journalctl --user -u app-org.kde.krdpserver.service` output for a single connection attempt:

```
New client connected:  Unspecified platform Unspecified version
unix_chkpwd[<pid>]: check pass; user unknown
unix_chkpwd[<pid>]: password check failed for user (james)
krdpserver[<pid>]: pam_unix(login:auth): authentication failure; logname=james uid=1000 euid=1000 tty= ruser= rhost=  user=james
krdpserver[<pid>]: pam_authenticate failure: Authentication failure
krdpserver[<pid>]: [ERROR][com.freerdp.api] - [rdp_peer_handle_state_active]: PostConnect for peer 0x... failed
krdpserver[<pid>]: [ERROR][com.freerdp.core.transport] - [transport_check_fds]: transport_check_fds: transport->ReceiveCallback() - STATE_RUN_FAILED [-1]
```

The `unix_chkpwd: check pass; user unknown` line is notable: the account (`james`) unquestionably exists (`getent passwd james` resolves it fine; the same account is simultaneously logged in locally and over SSH at the time of the failed RDP attempt). This message corresponds to the helper's early-exit path, not a genuine "no such user" condition.

We confirmed this is reproducible across 5 separate connection attempts spanning two reboots, with the identical failure signature every time, ruling out a transient/network issue.

## Expected Result

Connecting with the correct system account username and password should succeed and authenticate the RDP session, as it did on krdp 6.6.5 under the identical account/PAM/shadow configuration.

## Root Cause Analysis

1. `app-org.kde.krdpserver.service` runs as a **per-user** systemd unit (`systemctl --user`), so `krdpserver` always runs as the unprivileged user (UID 1000 here), never as root. (This is necessarily true given krdpserver's job: it has to run inside the user's own graphical session to capture/control it.)
2. `SystemUserEnabled=true` authenticates via PAM: `src/RdpConnection.cpp` calls `pam_start("login", ...)` → `pam_authenticate()`.
3. Because the calling process (`krdpserver`) is not root, `pam_unix` cannot read `/etc/shadow` (mode 000, root-only) directly. Its normal fallback is to fork/exec `/usr/bin/unix_chkpwd`, a small setuid-root helper whose only purpose is to perform this one check on behalf of unprivileged callers — this is standard, expected `pam_unix` behavior on every distro, not a configuration quirk.
4. `NoNewPrivileges=true` is a kernel-enforced flag (`prctl(PR_SET_NO_NEW_PRIVS)`) that is inherited by the unit's main process and **all of its children**, and it unconditionally prevents privilege gain via `execve()` — including via setuid/setgid bits — for the lifetime of that process tree. This is explicitly what the directive is documented to do (and is quoted, accurately, in the commit message that added it).
5. So when `krdpserver` execs `unix_chkpwd`, the kernel refuses to honor the setuid-root bit. The helper runs as plain UID 1000, can't open `/etc/shadow`, and fails — before ever reaching the actual password comparison. This produces the generic, deliberately non-specific denial message (`check pass; user unknown`) that `unix_chkpwd`/`pam_unix` use to avoid distinguishing "no such user" from "couldn't check" to an unprivileged caller.

We verified this mechanism by diffing the unit file directly between releases:

- `v6.6.5`: https://github.com/KDE/krdp/blob/v6.6.5/server/app-org.kde.krdpserver.service.in — no `NoNewPrivileges` line.
- `v6.7.0`: https://github.com/KDE/krdp/blob/v6.7.0/server/app-org.kde.krdpserver.service.in — adds `NoNewPrivileges=true`.
- Introduced by commit https://github.com/KDE/krdp/commit/8e1de600a6ea4fcb1662508626da2cf0499f9734 (2026-05-15, no associated BUG: tag), whose own message states the goal is specifically to block setuid-based privilege escalation (citing `su`/"Copy Fail"-style exploit chains as the motivating threat) in case of a future FreeRDP RCE.

The hardening goal is legitimate and well-reasoned on its own; it simply doesn't appear to have been checked against the `SystemUserEnabled=true` code path, which depends on exactly the privilege-escalation mechanism it now blocks.

### Isolated mechanism test (confirmed)

To isolate the `NoNewPrivileges` mechanism from krdp itself (no krdp process, no real account password, no config changes), we invoked the `unix_chkpwd` helper directly, twice, with an intentionally wrong test password, with and without `no_new_privs` applied via `setpriv`:

```
$ printf 'isolatedtestbadpassword\0' | /usr/bin/unix_chkpwd james nonull
exit code: 7   (PAM_AUTH_ERR — "Authentication failure")
journal:   unix_chkpwd[6350]: password check failed for user (james)

$ printf 'isolatedtestbadpassword\0' | /usr/bin/setpriv --no-new-privs -- /usr/bin/unix_chkpwd james nonull
exit code: 9   (PAM_AUTHINFO_UNAVAIL — "Underlying authentication service can not retrieve authentication information")
journal:   unix_chkpwd[6404]: check pass; user unknown
           unix_chkpwd[6404]: password check failed for user (james)
```

The `setpriv --no-new-privs` run reproduces the exact journal signature seen in the live krdp failure (`check pass; user unknown`), and the PAM return code changes from a genuine "wrong password" result (`PAM_AUTH_ERR`) to "couldn't even check" (`PAM_AUTHINFO_UNAVAIL`) — with the only variable changed being the `no_new_privs` flag, nothing krdp- or config-related. This confirms the mechanism in isolation, independent of krdp's own code or our local `SystemUserEnabled` setting.

### Confirmed local workaround

Adding a systemd user-unit drop-in overriding the directive restores the pre-6.7.0 behavior:

```ini
# ~/.config/systemd/user/app-org.kde.krdpserver.service.d/override.conf
[Service]
NoNewPrivileges=false
```
followed by `systemctl --user daemon-reload && systemctl --user restart app-org.kde.krdpserver.service`.

This is offered as supporting evidence of the mechanism, not as a request to simply revert the hardening — see "Why this matters" below for why we think this needs an upstream decision rather than a per-user workaround.

## Why this isn't just "use the other auth mode instead"

KRdp's other authentication mode — a dedicated RDP-only username/password, stored via QtKeychain (which in practice resolves to KWallet/`ksecretd` on most KDE systems) — is not a substitute for `SystemUserEnabled=true` on a headless/unattended/autologin machine, for a structural reason:

- KWallet requires an interactive GUI prompt to unlock a locked wallet. There is no `org.kde.KWallet` D-Bus method that accepts a password to unlock non-interactively — by design.
- On a machine configured for unattended startup (no password typed at boot — e.g. SDDM/plasmalogin autologin), nothing ever supplies that unlock, so the wallet stays locked after every reboot.
- Since RDP is the remote-GUI-access method being relied on, and the wallet can only be unlocked via a prompt rendered on the graphical session, this is circular: you cannot unlock the wallet without GUI access, and you cannot get GUI access (via RDP) without the wallet already unlocked. Only physical presence at the console breaks the loop.
- We also confirmed current KWallet (`kwalletwizardpage*.ui` in the KDE/kwallet repo) offers no "no encryption / no prompt" wallet option — only Blowfish-with-password or GPG-key-backed wallets — so there is no supported way to configure the credential-store path to avoid this either.

So as of 6.7.0, there is no KRdp configuration — system-user or RDP-only-credential — that supports "reboot the machine remotely, then reconnect via RDP with nobody physically present," which we believe was a supported, intentional use case prior to this regression (it's explicitly accommodated by KRdp's own README, which documents SDDM autologin specifically for this purpose).

## Suggested directions for a fix (for maintainers to evaluate, not prescriptive)

- Don't apply `NoNewPrivileges=true` when `SystemUserEnabled=true` is in effect (runtime-conditional sandboxing), if that's mechanically feasible given the directive is normally fixed at unit-definition time.
- Or, move the privileged PAM check out of the sandboxed `krdpserver` process entirely — e.g. a small separate root-owned helper/D-Bus service that performs the `pam_authenticate()` call on krdpserver's behalf, so the hardening on the main (network-facing, untrusted-input-parsing) process can stay fully intact.
- At minimum, document the incompatibility so users relying on `SystemUserEnabled=true` for unattended access know this combination is currently non-functional, rather than discovering it via silent, mysteristically-worded authentication failures.

## Additional notes

- This is reproducible purely from the unit file change and standard Linux/systemd/PAM semantics (`/etc/shadow` mode 000, setuid `unix_chkpwd`, `NoNewPrivileges` semantics per `systemd.exec(5)`: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#NoNewPrivileges=) — we'd expect it to reproduce identically on any distro, not just Fedora.
- The isolated `unix_chkpwd`/`setpriv` test above (separate from the full local workaround, which bundles `SystemUserEnabled=true` together with the systemd override) confirms the mechanism on its own; raw output available on request.
- Full `journalctl --user -u app-org.kde.krdpserver.service` output and `dnf history` showing the exact 6.6.5→6.7.0 transition timestamp are available on request.
Comment 1 walterjbrame 2026-06-24 01:52:44 UTC
# KRdp NoNewPrivileges workaround — applied 2026-06-23

Local workaround for the regression described in `krdp-nonewprivileges-bug-report.md` (filed upstream at bugs.kde.org, Product KRdp, corroborated by other reporters).

## Problem

krdp 6.7.0 added `NoNewPrivileges=true` to `app-org.kde.krdpserver.service`. This blocks the setuid-root `unix_chkpwd` helper that PAM needs to check a real Linux account password, so `SystemUserEnabled=true` RDP login fails on every attempt, even with the correct password.

## Changes made

1. `~/.config/krdpserverrc` — added `SystemUserEnabled=true` under `[General]`.
2. New file `~/.config/systemd/user/app-org.kde.krdpserver.service.d/override.conf`:
   ```ini
   [Service]
   NoNewPrivileges=false
   ```
3. `systemctl --user daemon-reload && systemctl --user restart app-org.kde.krdpserver.service`

Both changes are user-level config (`~/.config/...`), so they persist across reboots without further action.

## Verified

- `systemctl --user show app-org.kde.krdpserver.service -p NoNewPrivileges` → `NoNewPrivileges=no`
- Service active and running post-restart.

## Security tradeoff (accepted)

`NoNewPrivileges=true` was added as defense-in-depth against a *future* FreeRDP RCE being chained into a local privilege escalation via setuid binaries (e.g. `su`). Disabling it restores that specific theoretical escalation path. Accepted here because:

- This machine's RDP service is LAN-only, not exposed to the internet.
- The alternative (KRdp's RDP-only credential, stored via KWallet) doesn't work for unattended/autologin reboots — KWallet requires an interactive GUI unlock that autologin never triggers, and current KWallet has no blank-password/no-prompt option.

## Status

This is a local mitigation, not a fix. Tracking the upstream bug report for a real resolution (e.g. scoping the sandboxing so it doesn't apply when `SystemUserEnabled=true`, or moving the PAM check to a separate privileged helper outside the sandboxed process).
Comment 2 David Edmundson 2026-06-25 14:54:14 UTC

*** This bug has been marked as a duplicate of bug 521776 ***