Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface newtypes #879

Merged
merged 27 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9ceeae1
Implement newtypes for UserId, GroupId, ProcessId and DeviceId
van-sprundel Oct 13, 2024
4d09d20
Fix breaking changes in test env
van-sprundel Oct 13, 2024
479ee49
Return docs
van-sprundel Oct 13, 2024
41b0e08
Formatting
van-sprundel Oct 13, 2024
99adc61
Don't use newtypes for groups_buffer
van-sprundel Oct 13, 2024
037f45a
Format
van-sprundel Oct 13, 2024
74a329d
Don't dereference pointer when type is not equal
van-sprundel Oct 13, 2024
fcdf3f1
Merge branch 'main' into interface-newtypes
van-sprundel Oct 14, 2024
845991d
Fix merge
van-sprundel Oct 14, 2024
673acda
Replace impl `const fn new` with `OnceCell`
van-sprundel Oct 14, 2024
82765a0
Formatting
van-sprundel Oct 14, 2024
d1eee33
Use static TEST_USER_ID with OnceLock
van-sprundel Oct 14, 2024
29ebf01
Merge branch 'main' into interface-newtypes
van-sprundel Oct 15, 2024
7780bd6
Make pid() return `ProcessId`
van-sprundel Oct 15, 2024
ffa3f46
Remove redundant get() call
van-sprundel Oct 15, 2024
10a45ed
Add UserId::ROOT const
van-sprundel Oct 15, 2024
e2ca69e
keep id structs the same size as their field
van-sprundel Oct 15, 2024
1a3fd1b
Use ROOT const on more places
van-sprundel Oct 16, 2024
458efe7
Use transparent struct on GroupId, remove transparent on UserId, Proc…
van-sprundel Oct 16, 2024
9633bab
Merge branch 'main' into interface-newtypes
van-sprundel Oct 16, 2024
513f276
Merge branch 'main' into interface-newtypes
van-sprundel Oct 22, 2024
f62cc4e
Add `is_valid` for ProcessId
van-sprundel Oct 22, 2024
8eff83f
Use `UserId::ROOT`
van-sprundel Oct 22, 2024
fd07c7e
Remove more get calls
van-sprundel Oct 22, 2024
86afd0a
Rename get to inner
van-sprundel Oct 22, 2024
55902f4
Merge branch 'main' into interface-newtypes
van-sprundel Oct 22, 2024
552c440
Fix branch rebase
van-sprundel Oct 22, 2024
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
7 changes: 5 additions & 2 deletions src/common/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ impl Context {

#[cfg(test)]
mod tests {
use crate::{sudo::SudoAction, system::Hostname};
use crate::{
sudo::SudoAction,
system::{interface::UserId, Hostname},
};
use std::collections::HashMap;

use super::Context;
Expand All @@ -121,6 +124,6 @@ mod tests {
}
assert_eq!(context.command.arguments, ["hello"]);
assert_eq!(context.hostname, Hostname::resolve());
assert_eq!(context.target_user.uid, 0);
assert_eq!(context.target_user.uid, UserId::ROOT);
}
}
6 changes: 4 additions & 2 deletions src/exec/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::io::{self, ErrorKind};
use std::path::PathBuf;

use crate::common::SudoPath;
use crate::system::interface::ProcessId;
use crate::{
common::{context::LaunchType, Context},
system::{Group, User},
Expand All @@ -16,7 +17,8 @@ pub trait RunOptions {
fn user(&self) -> &User;
fn requesting_user(&self) -> &User;
fn group(&self) -> &Group;
fn pid(&self) -> i32;
fn pid(&self) -> ProcessId;

fn use_pty(&self) -> bool;
}

Expand Down Expand Up @@ -57,7 +59,7 @@ impl RunOptions for Context {
&self.target_group
}

fn pid(&self) -> i32 {
fn pid(&self) -> ProcessId {
self.process.pid
}

Expand Down
2 changes: 1 addition & 1 deletion src/exec/no_pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl ExecClosure {
/// - is the same PID of the command, or
/// - is in the process group of the command and either sudo or the command is the leader.
fn is_self_terminating(&self, signaler_pid: ProcessId) -> bool {
if signaler_pid != 0 {
if signaler_pid.get() != 0 {
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
if Some(signaler_pid) == self.command_pid {
return true;
}
Expand Down
5 changes: 3 additions & 2 deletions src/exec/use_pty/backchannel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl ParentMessage {
Self::CMD_STAT_EXIT => Self::CommandStatus(CommandStatus::Exit(data)),
Self::CMD_STAT_TERM => Self::CommandStatus(CommandStatus::Term(data)),
Self::CMD_STAT_STOP => Self::CommandStatus(CommandStatus::Stop(data)),
Self::CMD_PID => Self::CommandPid(data),
Self::CMD_PID => Self::CommandPid(ProcessId::new(data)),
Self::SHORT_READ => Self::ShortRead,
_ => unreachable!(),
}
Expand All @@ -90,7 +90,8 @@ impl ParentMessage {
};

let data = match self {
ParentMessage::IoError(data) | ParentMessage::CommandPid(data) => *data,
ParentMessage::IoError(data) => *data,
ParentMessage::CommandPid(data) => data.get(),
ParentMessage::CommandStatus(status) => match status {
CommandStatus::Exit(data)
| CommandStatus::Term(data)
Expand Down
6 changes: 3 additions & 3 deletions src/exec/use_pty/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ fn exec_command(
original_set: Option<SignalSet>,
) -> io::Error {
// FIXME (ogsudo): Do any additional configuration that needs to be run after `fork` but before `exec`
let command_pid = std::process::id() as ProcessId;
let command_pid = ProcessId::new(std::process::id() as i32);

setpgid(0, command_pid).ok();
setpgid(ProcessId::new(0), command_pid).ok();

// Wait for the monitor to set us as the foreground group for the pty if we are in the
// foreground.
Expand Down Expand Up @@ -414,7 +414,7 @@ fn is_self_terminating(
command_pid: ProcessId,
command_pgrp: ProcessId,
) -> bool {
if signaler_pid != 0 {
if signaler_pid.get() != 0 {
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
if signaler_pid == command_pid {
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/exec/use_pty/parent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ impl ParentClosure {
/// - is the same PID of the command, or
/// - is in the process group of the command and either sudo or the command is the leader.
fn is_self_terminating(&self, signaler_pid: ProcessId) -> bool {
if signaler_pid != 0 {
if signaler_pid.get() != 0 {
if Some(signaler_pid) == self.command_pid {
return true;
}
Expand Down
9 changes: 6 additions & 3 deletions src/su/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ use std::{
path::{Path, PathBuf},
};

use crate::common::{error::Error, resolve::CurrentUser, Environment};
use crate::common::{resolve::is_valid_executable, SudoPath};
use crate::exec::RunOptions;
use crate::log::user_warn;
use crate::system::{Group, Process, User};
use crate::{
common::{error::Error, resolve::CurrentUser, Environment},
system::interface::ProcessId,
};

use super::cli::SuRunOptions;

Expand Down Expand Up @@ -79,7 +82,7 @@ impl SuContext {
.ok_or_else(|| Error::UserNotFound(options.user.clone().into()))?;

// check the current user is root
let is_current_root = User::real_uid() == 0;
let is_current_root = User::real_uid().get() == 0;
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
let is_target_root = options.user == "root";

// only root can set a (additional) group
Expand Down Expand Up @@ -237,7 +240,7 @@ impl RunOptions for SuContext {
&self.group
}

fn pid(&self) -> i32 {
fn pid(&self) -> ProcessId {
self.process.pid
}

Expand Down
13 changes: 7 additions & 6 deletions src/sudo/env/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::sudo::{
cli::{SudoAction, SudoRunOptions},
env::environment::get_target_environment,
};
use crate::system::interface::{GroupId, UserId};
use crate::system::{Group, Hostname, Process, User};
use std::collections::{HashMap, HashSet};

Expand Down Expand Up @@ -82,8 +83,8 @@ fn create_test_context(sudo_options: &SudoRunOptions) -> Context {
CommandAndArguments::build_from_args(None, sudo_options.positional_args.clone(), &path);

let current_user = CurrentUser::fake(User {
uid: 1000,
gid: 1000,
uid: UserId::new(1000),
gid: GroupId::new(1000),

name: "test".into(),
gecos: String::new(),
Expand All @@ -94,13 +95,13 @@ fn create_test_context(sudo_options: &SudoRunOptions) -> Context {
});

let current_group = Group {
gid: 1000,
gid: GroupId::new(1000),
name: "test".to_string(),
};

let root_user = User {
uid: 0,
gid: 0,
uid: UserId::ROOT,
gid: GroupId::new(0),
name: "root".into(),
gecos: String::new(),
home: "/root".into(),
Expand All @@ -110,7 +111,7 @@ fn create_test_context(sudo_options: &SudoRunOptions) -> Context {
};

let root_group = Group {
gid: 0,
gid: GroupId::new(0),
name: "root".to_string(),
};

Expand Down
5 changes: 2 additions & 3 deletions src/sudo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::common::resolve::CurrentUser;
use crate::common::{Context, Error};
use crate::log::dev_info;
use crate::system::interface::UserId;
use crate::system::kernel::kernel_check;
use crate::system::timestamp::RecordScope;
use crate::system::User;
Expand Down Expand Up @@ -143,10 +144,8 @@ fn sudo_process() -> Result<(), Error> {
}

fn self_check() -> Result<(), Error> {
const ROOT: u32 = 0;

let euid = User::effective_uid();
if euid == ROOT {
if euid == UserId::ROOT {
Ok(())
} else {
Err(Error::SelfCheck)
Expand Down
4 changes: 2 additions & 2 deletions src/sudo/pipeline/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
pam::CLIConverser,
sudo::{cli::SudoListOptions, pam::PamAuthenticator, SudoersPolicy},
sudoers::{Authorization, ListRequest, Policy, Request, Sudoers},
system::User,
system::{interface::UserId, User},
};

use super::{Pipeline, PolicyPlugin};
Expand Down Expand Up @@ -87,7 +87,7 @@ impl Pipeline<SudoersPolicy, PamAuthenticator<CLIConverser>> {
}

Authorization::Forbidden => {
if context.current_user.uid == 0 {
if context.current_user.uid == UserId::ROOT {
if original_command.is_some() {
return Err(Error::Silent);
}
Expand Down
8 changes: 4 additions & 4 deletions src/sudoers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::{io, mem};

use crate::common::resolve::resolve_path;
use crate::log::auth_warn;
use crate::system::interface::{UnixGroup, UnixUser};
use crate::system::interface::{GroupId, UnixGroup, UnixUser, UserId};
use crate::system::{self, can_execute};
use ast::*;
use tokens::*;
Expand Down Expand Up @@ -432,7 +432,7 @@ fn match_user(user: &impl UnixUser) -> impl Fn(&UserSpecifier) -> bool + '_ {
move |spec| match spec {
UserSpecifier::User(id) => match_identifier(user, id),
UserSpecifier::Group(Identifier::Name(name)) => user.in_group_by_name(name.as_cstr()),
UserSpecifier::Group(Identifier::ID(num)) => user.in_group_by_gid(*num),
UserSpecifier::Group(Identifier::ID(num)) => user.in_group_by_gid(GroupId::new(*num)),
_ => todo!(), // nonunix-groups, netgroups, etc.
}
}
Expand All @@ -443,7 +443,7 @@ fn in_group(user: &impl UnixUser, group: &impl UnixGroup) -> bool {

fn match_group(group: &impl UnixGroup) -> impl Fn(&Identifier) -> bool + '_ {
move |id| match id {
Identifier::ID(num) => group.as_gid() == *num,
Identifier::ID(num) => group.as_gid().get() == *num,
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
Identifier::Name(name) => group.try_as_name().map_or(false, |s| name == s),
}
}
Expand Down Expand Up @@ -508,7 +508,7 @@ where
fn match_identifier(user: &impl UnixUser, ident: &ast::Identifier) -> bool {
match ident {
Identifier::Name(name) => user.has_name(name),
Identifier::ID(num) => user.has_uid(*num),
Identifier::ID(num) => user.has_uid(UserId::new(*num)),
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/sudoers/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ impl UnixUser for Named {
self.0 == name
}

fn has_uid(&self, uid: u32) -> bool {
dummy_cksum(self.0) == uid
fn has_uid(&self, uid: UserId) -> bool {
dummy_cksum(self.0) == uid.get()
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
}

fn in_group_by_name(&self, name: &CStr) -> bool {
self.has_name(name.to_str().unwrap())
}

fn in_group_by_gid(&self, gid: u32) -> bool {
dummy_cksum(self.0) == gid
fn in_group_by_gid(&self, gid: GroupId) -> bool {
dummy_cksum(self.0) == gid.get()
}

fn is_root(&self) -> bool {
Expand All @@ -39,7 +39,7 @@ impl UnixUser for Named {

impl UnixGroup for Named {
fn as_gid(&self) -> crate::system::interface::GroupId {
dummy_cksum(self.0)
GroupId::new(dummy_cksum(self.0))
}
fn try_as_name(&self) -> Option<&str> {
Some(self.0)
Expand Down Expand Up @@ -175,7 +175,7 @@ fn permission_test() {
pass!(["user ALL=(ALL:ALL) /bin/foo"], "user" => request! { user, user }, "server"; "/bin/foo" => [authenticate: Authenticate::Nopasswd]);
pass!(["user ALL=(ALL:ALL) /bin/foo"], "user" => request! { user, root }, "server"; "/bin/foo" => [authenticate: Authenticate::None]);

assert_eq!(Named("user").as_gid(), 1466);
assert_eq!(Named("user").as_gid().get(), 1466);
van-sprundel marked this conversation as resolved.
Show resolved Hide resolved
pass!(["#1466 server=(ALL:ALL) ALL"], "user" => root(), "server"; "/bin/hello");
pass!(["%#1466 server=(ALL:ALL) ALL"], "user" => root(), "server"; "/bin/hello");
FAIL!(["#1466 server=(ALL:ALL) ALL"], "root" => root(), "server"; "/bin/hello");
Expand Down
2 changes: 1 addition & 1 deletion src/system/file/chown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ impl Chown for File {

// SAFETY: `fchown` is passed a proper file descriptor; and even if the user/group id
// is invalid, it will not cause UB.
cerr(unsafe { libc::fchown(fd, owner, group) }).map(|_| ())
cerr(unsafe { libc::fchown(fd, owner.get(), group.get()) }).map(|_| ())
}
}
Loading
Loading