mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-17 16:36:03 +00:00
Check for status of tty1 during startup
This commit is contained in:
parent
77c3452bbb
commit
04bd88f179
3 changed files with 89 additions and 13 deletions
|
|
@ -499,7 +499,7 @@ As a result:
|
|||
* input devices may interact with the VT layer in unintended ways
|
||||
|
||||
When a graphical session is active, these issues do not occur:
|
||||
the compositor, via `systemd-logind`, owns a VT, switches it to `KD_GRAPHICS`, and the VT keyboard handler is disabled automatically.
|
||||
the compositor, via `systemd-logind`, owns a VT, switches it to `KD_GRAPHICS`, and the VT keyboard handler is **suppressed**.
|
||||
|
||||
The missing piece is a **well-defined fallback** for the “no graphical session” case.
|
||||
|
||||
|
|
@ -511,12 +511,12 @@ The missing piece is a **well-defined fallback** for the “no graphical session
|
|||
|
||||
It runs only when **no other graphical session is active** on the seat and exists solely to:
|
||||
|
||||
* open a regular logind session
|
||||
* open a regular logind session **of class `greeter**`
|
||||
* occupy the assigned VT
|
||||
* let logind switch the VT to `KD_GRAPHICS`
|
||||
* let logind switch the VT to `KD_GRAPHICS` **and mute the keyboard handler**
|
||||
|
||||
`fallbackdm` itself does **not** manipulate VTs, perform `KDSETMODE` ioctls, or access `/dev/tty` directly.
|
||||
All VT and seat handling is delegated to `systemd-logind`.
|
||||
All VT and seat handling is delegated to `systemd-logind` **via a standard PAM session**.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -524,15 +524,13 @@ All VT and seat handling is delegated to `systemd-logind`.
|
|||
|
||||
* `fallbackdm` starts as a normal session on the seat
|
||||
* while active:
|
||||
|
||||
* the VT is in `KD_GRAPHICS`
|
||||
* VT keyboard handling and `getty` input are suppressed
|
||||
* **the kernel VT keyboard handler is muted (equivalent to `K_OFF` or `KDSKBMUTE`)**
|
||||
* `getty` input is suppressed
|
||||
* when a real graphical session (greeter or compositor) starts:
|
||||
|
||||
* logind deactivates `fallbackdm`
|
||||
* VT ownership is transferred automatically
|
||||
* when the graphical session ends:
|
||||
|
||||
* `fallbackdm` may be restarted to reclaim the fallback role
|
||||
|
||||
`fallbackdm` is non-interactive by design but may display **minimal status information** in the future.
|
||||
|
|
@ -546,7 +544,6 @@ This design:
|
|||
* reuses existing, well-tested logind behavior
|
||||
* avoids duplicating VT and seat logic
|
||||
* guarantees compatibility with:
|
||||
|
||||
* Wayland compositors
|
||||
* graphical login managers
|
||||
* multi-seat setups
|
||||
|
|
@ -560,13 +557,10 @@ Conceptually, `fallbackdm` acts as a **headless placeholder graphical session**
|
|||
|
||||
* **Direct VT management (KDSETMODE, VT ioctls)**
|
||||
Rejected due to complexity, fragility, and duplication of logind functionality.
|
||||
|
||||
* **Filtering input at the evdev / uinput layer**
|
||||
Rejected as insufficient: it does not address VT keyboard handling or `getty` behavior.
|
||||
|
||||
* **Disabling gettys or VT switching globally**
|
||||
Rejected to preserve emergency local access and standard Linux behavior.
|
||||
|
||||
Rejected to preserve emergency local access and standard Linux behavior. **The logind-managed approach allows physical VT switching to remain functional for debugging.**
|
||||
* **Depending on a full display manager**
|
||||
Rejected, as this may require dummy display devices in headless configurations and adds unnecessary complexity.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@
|
|||
// distinguish between cleanup jobs that must not be cancelled and other jobs (especially background jobs)
|
||||
// naming: dev_path vs dev_node. I guess I mean the same.
|
||||
// Send warning, if udev monitor does not exist
|
||||
// Filter out Ctrl+Alt+Fx. "sysrq" keys or the low-level VT switching combos.
|
||||
|
||||
use ::cuse_lowlevel::*;
|
||||
use log::info;
|
||||
use std::ffi::CString;
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::raw::c_char;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::Mutex;
|
||||
|
|
@ -40,6 +43,7 @@ use crate::process_tools::*;
|
|||
pub mod actions;
|
||||
|
||||
pub mod jobs;
|
||||
pub mod vt_tools;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
|
|
@ -72,6 +76,12 @@ struct Args {
|
|||
help = "Path to /proc/<pid>/ns used as the namespace source (e.g. /proc/1234/ns or /proc/self/ns)"
|
||||
)]
|
||||
pub target_namespace: Option<String>,
|
||||
|
||||
#[arg(
|
||||
long = "vt-guard",
|
||||
help = "Prevent leakage of uinput to VT by, sending K_OFF to /dev/tty0"
|
||||
)]
|
||||
pub vt_guard: bool,
|
||||
}
|
||||
|
||||
fn validate_args(args: &Args) -> Result<(), String> {
|
||||
|
|
@ -132,7 +142,12 @@ fn main() -> std::io::Result<()> {
|
|||
std::process::exit(error_code);
|
||||
}
|
||||
|
||||
if args.vt_guard {
|
||||
vt_tools::mute_keyboard()?;
|
||||
}
|
||||
|
||||
check_permissions().expect("failed to read the capabilities of the vuinputd process");
|
||||
vt_tools::check_vt_status();
|
||||
|
||||
initialize_vuinput_state();
|
||||
VUINPUT_COUNTER.set(AtomicU64::new(3)).expect(
|
||||
|
|
|
|||
67
vuinputd/src/vt_tools.rs
Normal file
67
vuinputd/src/vt_tools.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use std::fs::OpenOptions;
|
||||
use std::io;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use log::{error, info, warn};
|
||||
|
||||
use libc::ioctl;
|
||||
|
||||
// see include/uapi/linux/kd.h
|
||||
const KDSKBMODE: u64 = 0x4B45; // sets current keyboard mode
|
||||
const KDGKBMODE: u64 = 0x4B44; // gets current keyboard mode
|
||||
|
||||
const K_OFF: u64 = 0x04;
|
||||
|
||||
pub fn check_vt_status() {
|
||||
match OpenOptions::new().read(true).open("/dev/tty1") {
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => {
|
||||
info!("/dev/tty1 not present — no VT-related input problem");
|
||||
}
|
||||
Err(err) => {
|
||||
error!("failed to open /dev/tty1: {}", err);
|
||||
}
|
||||
Ok(tty) => {
|
||||
let fd = tty.as_raw_fd();
|
||||
let mut mode: u64 = 0;
|
||||
|
||||
let rc = unsafe { ioctl(fd, KDGKBMODE, &mut mode) };
|
||||
if rc < 0 {
|
||||
error!(
|
||||
"KDGKBMODE ioctl failed: {}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if mode == K_OFF {
|
||||
info!("tty1 keyboard mode is K_OFF — VT input is disabled");
|
||||
} else {
|
||||
warn!(
|
||||
"tty1 keyboard mode is active (mode={}) — VT may consume input",
|
||||
mode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mute_keyboard() -> std::io::Result<()> {
|
||||
// 1. Open the TTY (usually TTY1 for a DM)
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/tty1")?;
|
||||
let fd = file.as_raw_fd();
|
||||
|
||||
// 2. Mute the keyboard
|
||||
unsafe {
|
||||
if libc::ioctl(fd, KDSKBMODE, K_OFF) < 0 {
|
||||
panic!("Failed to mute keyboard. Are you root?");
|
||||
}
|
||||
}
|
||||
println!("Keyboard muted.");
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue