Adapt sudo and getty to new namespace management, and enforce strict namespace at login.

This commit is contained in:
Ibuki Omatsu
2026-01-21 03:58:27 +00:00
committed by Jeremy Soller
parent 8ccf37d74a
commit 3bdd1d9a6e
4 changed files with 275 additions and 21 deletions
Generated
+138 -10
View File
@@ -108,6 +108,12 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "extra"
version = "0.1.0"
@@ -116,7 +122,7 @@ source = "git+https://gitlab.redox-os.org/redox-os/libextra.git#cf213969493db866
[[package]]
name = "generic-rt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/relibc#250f072973b96ee2d2ab921b7c2114b5178ec4d1"
source = "git+https://gitlab.redox-os.org/redox-os/relibc#3a8f64aa143184dc11fe1927a4f9e55c33ae3052"
[[package]]
name = "getrandom"
@@ -140,6 +146,12 @@ dependencies = [
"scroll",
]
[[package]]
name = "hashbrown"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@@ -149,6 +161,26 @@ dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "ioslice"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e571352c8a3b89074d12e3ee5173ffe162159105352aaaf1fc5764da747e31b"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "itertools"
version = "0.13.0"
@@ -172,11 +204,12 @@ checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "libredox"
version = "0.1.11"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50"
checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
dependencies = [
"bitflags 2.9.4",
"ioslice",
"libc",
"redox_syscall",
]
@@ -244,11 +277,12 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
[[package]]
name = "redox-rt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/relibc#250f072973b96ee2d2ab921b7c2114b5178ec4d1"
source = "git+https://gitlab.redox-os.org/redox-os/relibc#3a8f64aa143184dc11fe1927a4f9e55c33ae3052"
dependencies = [
"bitflags 2.9.4",
"generic-rt",
"goblin",
"ioslice",
"plain",
"redox-path",
"redox_syscall",
@@ -256,9 +290,9 @@ dependencies = [
[[package]]
name = "redox-scheme"
version = "0.8.3"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cea2668a5932f878a4298a1d7f8950249bbbb77120fb263da252c589152f5ea"
checksum = "5eb0cee524a5c6e4db180250f699e101ee25f3f79ad2618527e539e028cb6722"
dependencies = [
"libredox",
"redox_syscall",
@@ -266,9 +300,9 @@ dependencies = [
[[package]]
name = "redox_event"
version = "0.4.1"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69609faa5d5992247a4ef379917bb3e39be281405d6a0ccd4f942429400b956f"
checksum = "c30b73c93693667b5a8e6f54bddcc5a57449ef17c99f4b55c12d5bae4ab79e82"
dependencies = [
"bitflags 2.9.4",
"libredox",
@@ -289,8 +323,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.6.0"
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#2d11366fd160ec1dd3918164fa324275e1bab070"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27"
dependencies = [
"bitflags 2.9.4",
]
@@ -369,6 +404,45 @@ dependencies = [
"version-compare",
]
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "strip-ansi-escapes"
version = "0.2.1"
@@ -436,6 +510,47 @@ dependencies = [
"syn",
]
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "unicode-ident"
version = "1.0.19"
@@ -454,6 +569,8 @@ version = "0.1.0"
dependencies = [
"clap",
"extra",
"ioslice",
"libc",
"libredox",
"orbclient",
"plain",
@@ -464,7 +581,9 @@ dependencies = [
"redox_syscall",
"redox_termios",
"redox_users",
"serde",
"termion",
"toml",
]
[[package]]
@@ -516,6 +635,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winnow"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
[[package]]
name = "zeroize"
version = "1.8.2"
+8 -7
View File
@@ -57,19 +57,20 @@ extra = { git = "https://gitlab.redox-os.org/redox-os/libextra.git" }
orbclient = "0.3.47"
plain = "0.2.3"
redox_liner = "0.5.2"
libredox = "0.1.3"
libredox = { version = "0.1.12", features = ["mkns"] }
redox_termios = "0.1.3"
redox_event = "0.4"
redox-scheme = "0.8.3"
redox_syscall = "0.6"
redox_event = "0.4.3"
redox-scheme = "0.9.0"
redox_syscall = "0.7.0"
redox_users = "0.4.6"
termion = "4"
libc = "0.2"
serde = { version = "1.0.203", features = ["derive"] }
toml = "0.8.11"
ioslice = "0.6"
[target.'cfg(target_os = "redox")'.dependencies]
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc", default-features = false }
[patch.crates-io]
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
[profile.release]
lto = true
+97 -1
View File
@@ -1,12 +1,13 @@
#[macro_use]
extern crate clap;
use libredox::error::Result;
use std::fs::File;
use std::io::{self, Write};
use std::str;
use extra::option::OptionalExt;
use redox_users::{All, AllUsers, Config};
use redox_users::{All, AllUsers, Config, User};
use termion::input::TermRead;
use userutils::spawn_shell;
@@ -33,6 +34,89 @@ AUTHOR
const ISSUE_FILE: &'static str = "/etc/issue";
const MOTD_FILE: &'static str = "/etc/motd";
// TODO: Move to redox_users once the definition solidifies.
const DEFAULT_SCHEMES: [&'static str; 26] = [
// Kernel schemes
"debug",
"event",
"memory",
"pipe",
"serio",
"irq",
"time",
"sys",
// Base schemes
"rand",
"null",
"zero",
"log",
// Network schemes
"ip",
"icmp",
"tcp",
"udp",
// IPC schemes
"shm",
"chan",
"uds_stream",
"uds_dgram",
// File schemes
"file",
// Display schemes
"display.vesa",
"display*",
// Other schemes
"pty",
"sudo",
"audio",
];
pub fn apply_login_schemes(
user: &User<redox_users::auth::Full>,
default_schemes: &[&str],
) -> Result<libredox::Fd> {
let schemes = match load_config_schemes(user) {
Some(s) => s,
_ => default_schemes.iter().map(|s| s.to_string()).collect(),
};
let mut names: Vec<ioslice::IoSlice> = Vec::with_capacity(schemes.len());
for scheme in schemes.iter() {
names.push(ioslice::IoSlice::new(scheme.as_bytes()));
}
let ns_fd = libredox::call::mkns(&names)?;
let before_ns_fd = libredox::Fd::new(libredox::call::setns(ns_fd)?);
Ok(before_ns_fd)
}
fn load_config_schemes(user: &User<redox_users::auth::Full>) -> Option<Vec<String>> {
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fs;
const LOGIN_SCHEMES_FILE: &'static str = "/etc/login_schemes.toml";
#[derive(Debug, Clone, Serialize, Deserialize)]
struct UserSchemeConfig {
pub schemes: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct LoginConfig {
#[serde(rename = "user_schemes")]
pub user_schemes: BTreeMap<String, UserSchemeConfig>,
}
let config_str = fs::read_to_string(LOGIN_SCHEMES_FILE).ok()?;
let config: LoginConfig = toml::from_str(&config_str).ok()?;
config
.user_schemes
.get(&user.user)
.map(|cfg| cfg.schemes.clone())
}
pub fn main() {
let mut stdout = io::stdout();
let mut stderr = io::stderr();
@@ -76,7 +160,19 @@ pub fn main() {
stdout.flush().r#try(&mut stderr);
}
let before_ns_fd =
apply_login_schemes(user, &DEFAULT_SCHEMES).unwrap_or_exit(1);
let _ = syscall::fcntl(
before_ns_fd.raw(),
syscall::F_SETFD,
syscall::O_CLOEXEC,
);
spawn_shell(user).unwrap_or_exit(1);
let _ = syscall::fcntl(before_ns_fd.raw(), syscall::F_SETFD, 0);
let _ = libredox::call::close(
libredox::call::setns(before_ns_fd.into_raw()).unwrap_or_exit(1),
);
break;
}
+32 -3
View File
@@ -9,7 +9,7 @@ use extra::option::OptionalExt;
use libredox::flag::O_CLOEXEC;
use redox_rt::protocol::ProcCall;
use redox_rt::sys::proc_call;
use redox_scheme::scheme::SchemeSync;
use redox_scheme::scheme::{SchemeSync, register_sync_scheme};
use redox_scheme::{
CallerCtx, OpenResult, RequestKind, Response, SendFdRequest, SignalBehavior, Socket,
};
@@ -157,10 +157,31 @@ enum Handle {
AwaitingNewPassword { uid: u32 },
Placeholder,
SchemeRoot,
}
impl SchemeSync for Scheme {
fn open(&mut self, path: &str, _flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
fn scheme_root(&mut self) -> Result<usize> {
let fd = self.next_fd;
self.next_fd = self.next_fd.checked_add(1).ok_or(Error::new(EMFILE))?;
self.handles.insert(fd, Handle::SchemeRoot);
Ok(fd)
}
fn openat(
&mut self,
dirfd: usize,
path: &str,
_flags: usize,
_fcntl_flags: u32,
ctx: &CallerCtx,
) -> Result<OpenResult> {
if !matches!(
self.handles.get(&dirfd).ok_or(Error::new(EBADF))?,
Handle::SchemeRoot
) {
return Err(Error::new(EACCES));
}
let fd = self.next_fd;
self.next_fd = self.next_fd.checked_add(1).ok_or(Error::new(EMFILE))?;
let handle = match path {
@@ -261,6 +282,11 @@ impl SchemeSync for Scheme {
eprintln!("sudo: found placeholder handle with ID {id}");
return Err(Error::new(EBADFD));
}
Handle::SchemeRoot => {
eprintln!("sudo: found Scheme root handle with ID {id}");
return Err(Error::new(EBADFD));
}
}
Ok(buf.len())
}
@@ -309,13 +335,16 @@ impl Scheme {
fn daemon_main() -> ! {
// TODO: Linux kernel audit-like logging?
let socket = Socket::create("sudo").expect("failed to open scheme socket");
let socket = Socket::create().expect("failed to open scheme socket");
let mut scheme = Scheme {
next_fd: 1,
handles: HashMap::new(),
};
register_sync_scheme(&socket, "sudo", &mut scheme)
.expect("failed to register sudo scheme to namespace");
loop {
let Some(req) = socket
.next_request(SignalBehavior::Restart)