mirror of
https://github.com/Jovian-Experiments/Jovian-NixOS.git
synced 2025-10-06 00:22:54 +02:00
jovian-greeter: just bring our own setuid wrapper
No need for pkexec, also remove fallback path that basically never works
This commit is contained in:
@@ -134,21 +134,12 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
environment = {
|
||||
systemPackages = [ pkgs.jovian-greeter.helper ];
|
||||
pathsToLink = [ "lib/jovian-greeter" ];
|
||||
security.wrappers.jovian-consume-session = {
|
||||
source = "${pkgs.jovian-greeter.helper}/bin/consume-session";
|
||||
owner = cfg.user;
|
||||
group = "users";
|
||||
setuid = true;
|
||||
};
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (
|
||||
action.id == "org.freedesktop.policykit.exec" &&
|
||||
action.lookup("program") == "/run/current-system/sw/lib/jovian-greeter/consume-session" &&
|
||||
subject.user == "jovian-greeter"
|
||||
) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
xdg.portal.configPackages = mkDefault [ pkgs.gamescope-session ];
|
||||
})
|
||||
|
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$#" != "1" ]]; then
|
||||
>&2 echo "Usage: $0 <user>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
user="$1"
|
||||
uid=$(id -u "$user")
|
||||
if [[ "$uid" -lt "1000" ]]; then
|
||||
>&2 echo "UID $uid is too low"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
home=$(eval echo ~"$user")
|
||||
if ! [[ "$home" == /* ]]; then
|
||||
>&2 echo "Invalid home directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
session_file="$home/.local/state/steamos-session-select"
|
||||
if [[ -e "$session_file" ]]; then
|
||||
cat "$session_file"
|
||||
rm "$session_file"
|
||||
fi
|
46
pkgs/jovian-greeter/consume-session/Cargo.lock
generated
Normal file
46
pkgs/jovian-greeter/consume-session/Cargo.lock
generated
Normal file
@@ -0,0 +1,46 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "consume-session"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
7
pkgs/jovian-greeter/consume-session/Cargo.toml
Normal file
7
pkgs/jovian-greeter/consume-session/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "consume-session"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
nix = { version = "*", features = ["user"] }
|
23
pkgs/jovian-greeter/consume-session/src/main.rs
Normal file
23
pkgs/jovian-greeter/consume-session/src/main.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use nix::unistd::{Uid, User};
|
||||
use std::{fs, io};
|
||||
|
||||
fn main() {
|
||||
let uid = Uid::effective();
|
||||
let user = User::from_uid(uid)
|
||||
.expect("Unable to get current user info")
|
||||
.expect("Current user does not exist");
|
||||
let mut path = user.dir;
|
||||
path.push(".local/state/steamos-session-select");
|
||||
|
||||
let session = fs::read_to_string(&path);
|
||||
match session {
|
||||
Ok(s) => {
|
||||
print!("{}", s);
|
||||
fs::remove_file(&path).expect("Failed to remove session file");
|
||||
},
|
||||
Err(e) => match e.kind() {
|
||||
io::ErrorKind::NotFound => {}
|
||||
_ => eprintln!("Error when reading session file: {:?}", e),
|
||||
},
|
||||
}
|
||||
}
|
@@ -1,10 +1,8 @@
|
||||
{ lib, stdenv, python3, plymouth, shellcheck, nodePackages }:
|
||||
{ lib, stdenv, python3, plymouth, shellcheck, nodePackages, rustPlatform }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "jovian-greeter";
|
||||
|
||||
outputs = [ "out" "helper" ];
|
||||
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = [ python3.pkgs.wrapPython ];
|
||||
@@ -19,7 +17,6 @@ stdenv.mkDerivation {
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
|
||||
shellcheck ./consume-session
|
||||
pyright *.py
|
||||
|
||||
runHook postCheck
|
||||
@@ -31,8 +28,18 @@ stdenv.mkDerivation {
|
||||
install -Dm555 greeter.py $out/bin/jovian-greeter
|
||||
wrapPythonPrograms --prefix PATH : ${lib.makeBinPath [ plymouth ]}
|
||||
|
||||
install -Dm555 ./consume-session $helper/lib/jovian-greeter/consume-session
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru.helper = rustPlatform.buildRustPackage {
|
||||
pname = "jovian-consume-session";
|
||||
version = "0.0.1";
|
||||
|
||||
src = ./consume-session;
|
||||
|
||||
cargoLock.lockFile = ./consume-session/Cargo.lock;
|
||||
|
||||
# avoid a second rebuild
|
||||
doCheck = false;
|
||||
};
|
||||
}
|
||||
|
@@ -17,7 +17,6 @@ from typing import cast, override
|
||||
from systemd.journal import JournalHandler
|
||||
|
||||
DEFAULT_SESSION = 'gamescope-wayland'
|
||||
HELPER_PREFIX = Path('/run/current-system/sw/lib/jovian-greeter')
|
||||
|
||||
class Session:
|
||||
TYPE: str = 'tty'
|
||||
@@ -86,15 +85,20 @@ class GreetdClient:
|
||||
|
||||
raise RuntimeError('Bad response', response)
|
||||
|
||||
def start_session(self, command: list[str], environment: list[str]):
|
||||
def start_session(self, session: Session):
|
||||
try:
|
||||
_ = subprocess.check_call(["plymouth", "quit", "--retain-splash", "--wait"])
|
||||
except Exception as ex:
|
||||
logging.debug("Failed to stop Plymouth", exc_info=ex)
|
||||
|
||||
command = [ 'systemd-cat', '--identifier=jovian-session', '--' ] + command
|
||||
session_command = session.get_command()
|
||||
if not session_command:
|
||||
raise RuntimeError('Session does not have a command')
|
||||
|
||||
logging.info("Starting session '%s'", DEFAULT_SESSION)
|
||||
command = [ 'systemd-cat', '--identifier=jovian-session', '--' ] + session_command
|
||||
environment = session.get_environment()
|
||||
|
||||
logging.info("Starting session '%s'", session.name)
|
||||
logging.info("Command: %s", command)
|
||||
logging.info("Environment: %s", environment)
|
||||
self._send({
|
||||
@@ -124,9 +128,8 @@ class GreetdClient:
|
||||
return cast(dict[str, str], json.loads(payload))
|
||||
|
||||
class Context:
|
||||
def __init__(self, user: str, home: Path):
|
||||
def __init__(self, user: str):
|
||||
self.user: str = user
|
||||
self.home: Path = home
|
||||
self.xdg_data_dirs: list[str] = os.environ.get('XDG_DATA_DIRS', '').split(':')
|
||||
|
||||
def next_session(self) -> Session | None:
|
||||
@@ -138,31 +141,14 @@ class Context:
|
||||
return self._find_sessions(sessions)
|
||||
|
||||
def _consume_session(self) -> str | None:
|
||||
helper = HELPER_PREFIX.joinpath('consume-session')
|
||||
if helper.exists():
|
||||
logging.debug('Using pkexec helper')
|
||||
res = subprocess.run(
|
||||
['/run/wrappers/bin/pkexec', helper, self.user],
|
||||
stdin=subprocess.DEVNULL,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
env={'SHELL': '/bin/sh'}
|
||||
)
|
||||
next_session = res.stdout.decode('utf-8').strip()
|
||||
|
||||
if not next_session:
|
||||
return None
|
||||
|
||||
return next_session
|
||||
|
||||
next_session_file = self.home.joinpath(".local/state/steamos-session-select")
|
||||
if not next_session_file.exists():
|
||||
return None
|
||||
|
||||
with open(next_session_file, 'r') as f:
|
||||
next_session = f.read().strip()
|
||||
|
||||
next_session_file.unlink()
|
||||
res = subprocess.run(
|
||||
['/run/wrappers/bin/jovian-consume-session'],
|
||||
stdin=subprocess.DEVNULL,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
env={},
|
||||
)
|
||||
next_session = res.stdout.decode('utf-8').strip()
|
||||
|
||||
if not next_session:
|
||||
return None
|
||||
@@ -206,18 +192,13 @@ if __name__ == '__main__':
|
||||
sys.exit(1)
|
||||
|
||||
user = sys.argv[1]
|
||||
home = os.path.expanduser(f'~{user}/')
|
||||
socket_path = os.environ.get('GREETD_SOCK')
|
||||
|
||||
if not home:
|
||||
logging.error(f'Home directory for {user} not found')
|
||||
sys.exit(1)
|
||||
|
||||
if not socket_path:
|
||||
logging.error("GREETD_SOCK must be set")
|
||||
sys.exit(1)
|
||||
|
||||
ctx = Context(user, Path(home))
|
||||
ctx = Context(user)
|
||||
|
||||
client = GreetdClient(Path(socket_path))
|
||||
client.create_session(user)
|
||||
@@ -235,4 +216,4 @@ if __name__ == '__main__':
|
||||
logging.error(".desktop file doesn't contain Exec=")
|
||||
sys.exit(1)
|
||||
|
||||
client.start_session(command, environment)
|
||||
client.start_session(session)
|
||||
|
Reference in New Issue
Block a user