diff --git a/.deny.toml b/.deny.toml new file mode 100644 index 0000000..dc2c309 --- /dev/null +++ b/.deny.toml @@ -0,0 +1,103 @@ +[graph] +# targets = [] # Disables all not explicitly listed targets +# exclude = [] # Also removes dependencies of package if not otherwise connected +all-features = true +no-default-features = false +# features = [] # We use all-features +exclude-dev = false + +[output] +feature-depth = 1 + +[advisories] +version = 2 +# db-path = "$CARGO_HOME/advisory-dbs" +# db-urls = ["https://github.com/rustsec/advisory-db"] +# ignore = [] +git-fetch-with-cli = false # False = use build in git library +yanked = "deny" + +[licenses] +version = 2 +allow = [ + "Apache-2.0", # https://tldrlegal.com/license/apache-license-2.0-(apache-2.0) + "BSD-2-Clause", # https://tldrlegal.com/license/bsd-2-clause-license-(freebsd) + "BSD-3-Clause", # https://tldrlegal.com/license/bsd-3-clause-license-(revised) + "CC0-1.0", # https://creativecommons.org/publicdomain/zero/1.0/ + "ISC", # https://tldrlegal.com/license/-isc-license + "LicenseRef-UFL-1.0", # https://tldrlegal.com/license/ubuntu-font-license,-1.0 + "MIT", # https://tldrlegal.com/license/mit-license + "OFL-1.1", # https://spdx.org/licenses/OFL-1.1.html + "Unicode-DFS-2016", # https://spdx.org/licenses/Unicode-DFS-2016.html + "Zlib", # https://tldrlegal.com/license/zlib-libpng-license-(zlib) + "MIT-0", + "0BSD", +] +confidence-threshold = 0.93 +# exceptions = [] +include-dev = true +unused-allowed-license = "warn" + +[bans] +multiple-versions = "deny" +multiple-versions-include-dev = false +wildcards = "deny" +highlight = "all" +workspace-default-features = "allow" +external-default-features = "allow" +# allow = [] # Whitelist if one or more entries +# deny = [] +skip = [ + { crate = "regex-automata@0.1.10", reason = "Old version used by other dependency" }, + { crate = "regex-syntax@0.6.29", reason = "Old version used by other dependency" }, + { crate = "tracing-log@0.1.4", reason = "Old version used by other dependency" }, + { crate = "bitflags@1.3.2", reason = "Old version used by other dependency" }, + { crate = "event-listener@2.5.3", reason = "Old version used by other dependency" }, + { crate = "event-listener@4.0.3", reason = "Old version used by other dependency" }, + { crate = "event-listener-strategy@0.4.0", reason = "Old version used by other dependency" }, + { crate = "libloading@0.7.4", reason = "Old version used by other dependency" }, + { crate = "objc-sys@0.2.0-beta.2", reason = "Old version used by other dependency" }, + { crate = "objc2@0.3.0-beta.3.patch-leaks.3", reason = "Old version used by other dependency" }, + { crate = "objc2-encode@2.0.0-pre.2", reason = "Old version used by other dependency" }, + { crate = "redox_syscall@0.3.5", reason = "Old version used by other dependency" }, + { crate = "syn@1.0.109", reason = "Old version used by other dependency" }, + { crate = "windows@0.48.0", reason = "Old version used by other dependency" }, + { crate = "windows@0.52.0", reason = "Old version used by other dependency" }, + { crate = "windows@0.54.0", reason = "Old version used by other dependency" }, + { crate = "windows-core@0.52.0", reason = "Old version used by other dependency" }, + { crate = "windows-core@0.54.0", reason = "Old version used by other dependency" }, + { crate = "windows-sys@0.45.0", reason = "Old version used by other dependency" }, + { crate = "windows-sys@0.48.0", reason = "Old version used by other dependency" }, + { crate = "windows-targets@0.42.2 ", reason = "Old version used by other dependency" }, + { crate = "windows-targets@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_aarch64_gnullvm@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_aarch64_gnullvm@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_aarch64_msvc@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_aarch64_msvc@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_i686_gnu@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_i686_gnu@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_i686_msvc@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_i686_msvc@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_gnu@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_gnu@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_gnullvm@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_gnullvm@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_msvc@0.42.2", reason = "Old version used by other dependency" }, + { crate = "windows_x86_64_msvc@0.48.5", reason = "Old version used by other dependency" }, + { crate = "windows-implement@0.48.0", reason = "Old version used by other dependency" }, + { crate = "windows-interface@0.48.0", reason = "Old version used by other dependency" }, +] # Only for duplicate detection +# skip-tree = [] + +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = [] +required-git-spec = "rev" +# private = [] + +# [sources.allow-org] +# github = [] +# gitlab = [] +# bitbucket = [] diff --git a/.vscode/settings.json b/.vscode/settings.json index 0da816a..9496386 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ + "egui", "getresuid", "landlock", "Lockdown", @@ -10,4 +11,4 @@ "setresuid", "unistd" ] -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0240176..09582ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Currently nothing +## [0.2.0] - 2024-04-25 + +### Added + +- egui integration + +### Changed + +- status now via combined struct + ## [0.1.0] - 2024-04-21 ### Added diff --git a/Cargo.toml b/Cargo.toml index 5206438..7289257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "bevy_mod_lockdown" description = "bevy_mod_lockdown is a library to reduce the attack surface your application offers." categories = ["game-development"] keywords = ["bevy", "gamedev"] -version = "0.1.0" +version = "0.2.0" license = "MIT OR Apache-2.0" authors = ["Frederik Terstappen "] repository = "https://github.com/FrTerstappen/bevy_mod_lockdown" @@ -28,9 +28,11 @@ privilege = [ "nix?/user", ] system_call = [] +egui = ["dep:egui"] [dependencies] bevy = { version = "0.13.2", default-features = false } +egui = { version = "0.27.2", default-features = false, optional = true } [target.'cfg(target_os = "android")'.dependencies] @@ -47,8 +49,20 @@ nix = { version = "0.28.0", optional = true } [target.'cfg(target_family = "wasm")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies] -# To avoid duplication, limited by usage of sysinfo in bevy -windows = { version = "0.52.0", optional = true } +windows = { version = "0.56.0", optional = true } + +[dev-dependencies] +bevy = { version = "0.13.2", default-features = true } +bevy_egui = { version = "0.27.0", default-features = false, features = [ + "default_fonts", + "render", +] } + +[[example]] +name = "egui" +path = "examples/egui.rs" +required-features = ["egui"] + [lints] # Rust diff --git a/README.md b/README.md index c7631eb..f69e88d 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ See this [chapter](#status-resources) for more information. ### Status resources -The features each add a resource `FeatureNameAdjustment` that can be used to check the current status of the adjustment. -These resources are enums with variants describing the current status. -They start with a value of `Unknown`. +The resource `LockdownAdjustments` can be used to check the status of the adjustments. +The features each add a field to the resource that matches the feature name. +These fields are enums with variants describing the current status. ## Features @@ -41,7 +41,19 @@ You can see the availability of features and their inclusion in full_speed in th > [!NOTE] > By default only the feature `feature_warning` is enabled which logs a warning when no other feature is enabled. -### Platform support +### Platform independent features + +The features described here are independent of the used platform. + +#### Feature: `egui` + +Adds a convenience method to display the `LockdownAdjustments` with egui. +See the `egui` example for usage. + +Run the example with `cargo run --example egui --features="egui"`. +Include other features to see something beside the warning. + +### Platform dependent features Feature support on different platform: @@ -63,7 +75,7 @@ __Legend:__ [^1]: Beside a log entry in some cases. -### Feature: `filesystem` +#### Feature: `filesystem` Restricts access to the filesystem, blocking access to all not explicitly allowed paths. @@ -78,11 +90,11 @@ This happens in `Startup` which means that full access to the file system is sti Currently only implemented on linux. Where it uses landlock and requires a kernel with support for it. -### Feature: `network` +#### Feature: `network` Not yet implemented for any platform. -### Feature: `privilege` +#### Feature: `privilege` Reduces the privilege granted to the application. @@ -91,7 +103,7 @@ Reduces the privilege granted to the application. This happens in `PostStartup` which means that elevated privileges are still available in `PreStartup`, `Startup` and partly in `PostStartup`. -### Feature: `system_call` +#### Feature: `system_call` Not yet implemented for any platform. @@ -142,4 +154,4 @@ All code in this repository is dual-licensed under either: | bevy | bevy_mod_lockdown | | -----: | ----------------: | -| 0.13.1 | 0.1.0 | +| 0.13.1 | 0.1.0 - 0.2.0 | diff --git a/deny.toml b/deny.toml deleted file mode 100644 index f733031..0000000 --- a/deny.toml +++ /dev/null @@ -1,61 +0,0 @@ -[graph] -# targets = [] # Disables all not explicitly listed targets -# exclude = [] # Also removes dependencies of package if not otherwise connected -all-features = true -no-default-features = false -# features = [] # We use all-features -exclude-dev = false - -[output] -feature-depth = 1 - -[advisories] -version = 2 -# db-path = "$CARGO_HOME/advisory-dbs" -# db-urls = ["https://github.com/rustsec/advisory-db"] -# ignore = [] -git-fetch-with-cli = false # False = use build in git library -yanked = "deny" - -[licenses] -version = 2 -allow = [ - "Apache-2.0", # https://tldrlegal.com/license/apache-license-2.0-(apache-2.0) - "BSD-2-Clause", # https://tldrlegal.com/license/bsd-2-clause-license-(freebsd) - "MIT", # https://tldrlegal.com/license/mit-license - "Unicode-DFS-2016", # https://spdx.org/licenses/Unicode-DFS-2016.html - "Zlib", # https://tldrlegal.com/license/zlib-libpng-license-(zlib) -] -confidence-threshold = 0.93 -# exceptions = [] -include-dev = true -unused-allowed-license = "warn" - -[bans] -multiple-versions = "deny" -multiple-versions-include-dev = true -wildcards = "deny" -highlight = "all" -workspace-default-features = "allow" -external-default-features = "allow" -# allow = [] # Whitelist if one or more entries -# deny = [] -skip = [ - { crate = "regex-automata@0.1.10", reason = "Old version used by other dependency" }, - { crate = "regex-syntax@0.6.29", reason = "Old version used by other dependency" }, - { crate = "tracing-log@0.1.4", reason = "Old version used by other dependency" }, -] # Only for duplicate detection -# skip-tree = [] - -[sources] -unknown-registry = "deny" -unknown-git = "deny" -allow-registry = ["https://github.com/rust-lang/crates.io-index"] -allow-git = [] -required-git-spec = "rev" -# private = [] - -# [sources.allow-org] -# github = [] -# gitlab = [] -# bitbucket = [] diff --git a/examples/egui.rs b/examples/egui.rs new file mode 100644 index 0000000..650d5cf --- /dev/null +++ b/examples/egui.rs @@ -0,0 +1,28 @@ +use bevy::{ + prelude::*, + window::PrimaryWindow, +}; +use bevy_egui::{ + egui, + EguiContext, + EguiPlugin, +}; +use bevy_mod_lockdown::LockdownAdjustments; + +fn main() { + let mut app = App::new(); + app.add_plugins(DefaultPlugins); + app.add_plugins(EguiPlugin); + app.add_plugins(bevy_mod_lockdown::LockdownPlugin); + app.add_systems(Update, display_adjustment_status); + app.run(); +} + +fn display_adjustment_status( + mut egui_ctx: Query<&mut EguiContext, With>, + lockdown_adjustments: Res<'_, LockdownAdjustments>, +) { + egui::Window::new("Example window").show(egui_ctx.single_mut().get_mut(), |ui| { + bevy_mod_lockdown::egui::ui_for_adjustment(ui, &lockdown_adjustments, true); + }); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..ba227ca --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,31 @@ +[toolchain] +channel = "nightly" +components = [ + "rustc", + "cargo", + "rustfmt", + "rust-std", + "clippy", + "miri", + "rust-src", +] +targets = [ + # WASM + "wasm32-unknown-unknown", + + # Linux + "x86_64-unknown-linux-gnu", + + # Mac + "aarch64-apple-darwin", + + # iOS + "aarch64-apple-ios", + + # Windows + "x86_64-pc-windows-gnu", + + # Android + "aarch64-linux-android", +] +profile = "default" diff --git a/src/egui.rs b/src/egui.rs new file mode 100644 index 0000000..205973f --- /dev/null +++ b/src/egui.rs @@ -0,0 +1,45 @@ +use crate::LockdownAdjustments; + +pub fn ui_for_adjustment( + ui: &mut egui::Ui, + _lockdown_adjustments: &LockdownAdjustments, + open_by_default: bool, +) { + egui::CollapsingHeader::new("Lockdown adjustments").default_open(open_by_default).show(ui, |ui| { + #[cfg(feature = "feature_warning")] + if std::mem::size_of::() == 0 { + ui.label("No features activated for bevy_mod_lockdown."); + ui.label("This plugin does offer most functionality behind feature flags."); + ui.label("See README for more information and a list of available features."); + ui.label( + "Enable a feature other than 'feature_warning' to remove this warning (or disable the default features)." + ); + } + + ui.columns(2, |_columns| { + #[cfg(feature = "filesystem")] + { + _columns[0].label("Filesystem"); + _columns[1].label(format!("{:?}", _lockdown_adjustments.filesystem)); + } + + #[cfg(feature = "network")] + { + _columns[0].label("Network"); + _columns[1].label(format!("{:?}", _lockdown_adjustments.network)); + } + + #[cfg(feature = "privilege")] + { + _columns[0].label("Privilege"); + _columns[1].label(format!("{:?}", _lockdown_adjustments.privilege)); + } + + #[cfg(feature = "system_call")] + { + _columns[0].label("System call"); + _columns[1].label(format!("{:?}", _lockdown_adjustments.system_call)); + } + }); + }); +} diff --git a/src/filesystem.rs b/src/filesystem.rs index 01169af..53a3c22 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -5,7 +5,10 @@ use std::path::{ use bevy::prelude::*; -use crate::LockdownSet; +use crate::{ + LockdownAdjustments, + LockdownSet, +}; #[derive(Debug, Default, Resource, Reflect)] #[reflect(Resource)] @@ -17,7 +20,7 @@ pub enum FilesystemAdjustment { Failed, } -#[derive(Debug, Default, Resource, Reflect)] +#[derive(Debug, Resource, Reflect)] #[reflect(Resource)] pub struct AllowedFilesystemAccess { pub(crate) read_only: Vec, @@ -25,6 +28,12 @@ pub struct AllowedFilesystemAccess { pub(crate) read_write: Vec, } impl AllowedFilesystemAccess { + pub fn new_empty() -> Self { + Self { + read_only: Vec::new(), write_only: Vec::new(), read_write: Vec::new() + } + } + pub fn new_with_required() -> Self { let mut read_only = Vec::new(); let write_only = Vec::new(); @@ -83,6 +92,10 @@ impl AllowedFilesystemAccess { } } +impl Default for AllowedFilesystemAccess { + fn default() -> Self { Self::new_with_required() } +} + #[derive(Debug)] pub struct FilesystemPlugin; @@ -91,15 +104,9 @@ impl Plugin for FilesystemPlugin { &self, app: &mut App, ) { - app.register_type::(); - app.insert_resource(FilesystemAdjustment::Unknown); - // Add allowed filesystem access only if it is not already added app.register_type::(); - if !app.world.contains_resource::() { - let directory_access = AllowedFilesystemAccess::new_with_required(); - app.insert_resource(directory_access); - } + app.init_resource::(); // This does nothing if already added #[cfg(target_os = "linux")] { @@ -111,7 +118,7 @@ impl Plugin for FilesystemPlugin { #[cfg(target_os = "linux")] fn try_restricting_file_access_linux( allowed_filesystem_access: Res<'_, AllowedFilesystemAccess>, - mut filesystem_adjustment: ResMut<'_, FilesystemAdjustment>, + mut adjustments: ResMut<'_, LockdownAdjustments>, ) { use landlock::{ path_beneath_rules, @@ -124,8 +131,6 @@ fn try_restricting_file_access_linux( ABI, }; - *filesystem_adjustment = FilesystemAdjustment::Failed; - let abi = ABI::V3; let read_only = AccessFs::from_read(abi); let write_only = AccessFs::from_write(abi); @@ -134,10 +139,12 @@ fn try_restricting_file_access_linux( let rule_set = Ruleset::default(); let Ok(rule_set) = rule_set.handle_access(read_write) else { warn!("Unable to add base rule"); + adjustments.filesystem = FilesystemAdjustment::Failed; return; }; let Ok(rule_set) = rule_set.create() else { warn!("Unable to create ruleset"); + adjustments.filesystem = FilesystemAdjustment::Failed; return; }; @@ -145,6 +152,7 @@ fn try_restricting_file_access_linux( let read_only_rules = path_beneath_rules(&allowed_filesystem_access.read_only, read_only); let Ok(rule_set) = rule_set.add_rules(read_only_rules) else { warn!("Unable to add ready only rules"); + adjustments.filesystem = FilesystemAdjustment::Failed; return; }; @@ -152,6 +160,7 @@ fn try_restricting_file_access_linux( let write_only_rules = path_beneath_rules(&allowed_filesystem_access.write_only, write_only); let Ok(rule_set) = rule_set.add_rules(write_only_rules) else { warn!("Unable to add write only rules"); + adjustments.filesystem = FilesystemAdjustment::Failed; return; }; @@ -159,6 +168,7 @@ fn try_restricting_file_access_linux( let read_write_rules = path_beneath_rules(&allowed_filesystem_access.read_write, read_write); let Ok(rule_set) = rule_set.add_rules(read_write_rules) else { warn!("Unable to add ready write rules"); + adjustments.filesystem = FilesystemAdjustment::Failed; return; }; @@ -168,18 +178,20 @@ fn try_restricting_file_access_linux( Ok(status) => match status.ruleset { RulesetStatus::FullyEnforced => { info!("Sandboxing with landlock fully enforced"); - *filesystem_adjustment = FilesystemAdjustment::Completed; + adjustments.filesystem = FilesystemAdjustment::Completed; }, RulesetStatus::PartiallyEnforced => { warn!("Sandboxing with landlock partially enforced"); - *filesystem_adjustment = FilesystemAdjustment::CompletedPartial; + adjustments.filesystem = FilesystemAdjustment::CompletedPartial; }, RulesetStatus::NotEnforced => { warn!("Sandboxing with landlock not enforced. Kernel with landlock support needed"); + adjustments.filesystem = FilesystemAdjustment::Failed; }, }, Err(e) => { warn!("Error while trying to restrict self with landlock: {e}"); + adjustments.filesystem = FilesystemAdjustment::Failed; }, } } diff --git a/src/lib.rs b/src/lib.rs index 9a4503d..a4ed508 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "egui")] +pub mod egui; + #[cfg(feature = "filesystem")] pub mod filesystem; @@ -19,16 +22,32 @@ pub enum LockdownSet { PostStartup, } +#[derive(Debug, Default, Resource, Reflect)] +#[reflect(Resource)] +pub struct LockdownAdjustments { + #[cfg(feature = "filesystem")] + filesystem: filesystem::FilesystemAdjustment, + #[cfg(feature = "network")] + network: network::NetworkAdjustment, + #[cfg(feature = "privilege")] + privilege: privilege::PrivilegeAdjustment, + #[cfg(feature = "system_call")] + system_call: system_call::SystemCallAdjustment, +} + #[derive(Debug)] pub struct LockdownPlugin; impl Plugin for LockdownPlugin { fn build( &self, - _app: &mut App, + app: &mut App, ) { + app.register_type::(); + app.init_resource::(); + #[cfg(feature = "feature_warning")] - if env!("HAS_FEATURES") == "false" { + if std::mem::size_of::() == 0 { warn!("No features activated for bevy_mod_lockdown."); warn!("This plugin does offer most functionality behind feature flags."); warn!("See README for more information and a list of available features."); @@ -38,15 +57,15 @@ impl Plugin for LockdownPlugin { } #[cfg(feature = "filesystem")] - _app.add_plugins(filesystem::FilesystemPlugin); + app.add_plugins(filesystem::FilesystemPlugin); #[cfg(feature = "network")] - _app.add_plugins(network::NetworkPlugin); + app.add_plugins(network::NetworkPlugin); #[cfg(feature = "privilege")] - _app.add_plugins(privilege::PrivilegePlugin); + app.add_plugins(privilege::PrivilegePlugin); #[cfg(feature = "system_call")] - _app.add_plugins(system_call::SystemCallPlugin); + app.add_plugins(system_call::SystemCallPlugin); } } diff --git a/src/network.rs b/src/network.rs index 1b57f63..cc6bd43 100644 --- a/src/network.rs +++ b/src/network.rs @@ -4,7 +4,7 @@ use bevy::prelude::*; #[reflect(Resource)] pub enum NetworkAdjustment { #[default] - Unknown, + NotImplemented, } #[derive(Debug)] @@ -13,9 +13,7 @@ pub struct NetworkPlugin; impl Plugin for NetworkPlugin { fn build( &self, - app: &mut App, + _app: &mut App, ) { - app.register_type::(); - app.insert_resource(NetworkAdjustment::Unknown); } } diff --git a/src/privilege.rs b/src/privilege.rs index 4a8d906..00dbb8d 100644 --- a/src/privilege.rs +++ b/src/privilege.rs @@ -1,15 +1,19 @@ use bevy::prelude::*; -use crate::LockdownSet; +use crate::{ + LockdownAdjustments, + LockdownSet, +}; #[derive(Debug, Default, Resource, Reflect)] #[reflect(Resource)] pub enum PrivilegeAdjustment { #[default] - Unknown, + NotImplemented, Completed, Failed, NotNeeded, + Unknown, } #[derive(Debug)] @@ -20,26 +24,21 @@ impl Plugin for PrivilegePlugin { &self, app: &mut App, ) { - app.register_type::(); - app.insert_resource(PrivilegeAdjustment::Unknown); - #[cfg(target_os = "windows")] { - app.add_systems(PostStartup, try_adjusting_privilege_windows.in_set(LockdownSet::PostStartup)); + app.add_systems(PostStartup, adjust_privilege_windows.in_set(LockdownSet::PostStartup)); } // TODO: we use nix for this, this means theoretical this runs on Android, iOS, Linux and MacOs #[cfg(target_os = "linux")] { - app.add_systems(PostStartup, try_dropping_root_nix.chain().in_set(LockdownSet::PostStartup)); + app.add_systems(PostStartup, try_dropping_root_nix.in_set(LockdownSet::PostStartup)); } } } #[cfg(target_os = "linux")] -fn try_dropping_root_nix(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustment>) { - *privilege_adjustment = PrivilegeAdjustment::Failed; - +fn try_dropping_root_nix(mut adjustments: ResMut<'_, LockdownAdjustments>) { // Check if running as root match nix::unistd::getresuid() { Ok(uid) => { @@ -47,7 +46,7 @@ fn try_dropping_root_nix(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustmen warn!("User is root. Trying to drop root"); } else { info!("Did not run as root. No adjustment needed"); - *privilege_adjustment = PrivilegeAdjustment::NotNeeded; + adjustments.privilege = PrivilegeAdjustment::NotNeeded; return; } }, @@ -59,10 +58,12 @@ fn try_dropping_root_nix(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustmen // Get user id (from caller of sudo) let Ok(user_id) = std::env::var("SUDO_UID") else { warn!("Unable to get user id of calling user. Unable to adjust"); + adjustments.privilege = PrivilegeAdjustment::Failed; return; }; let Ok(user_id) = user_id.parse() else { warn!("Unable to parse user id. Unable to adjust"); + adjustments.privilege = PrivilegeAdjustment::Failed; return; }; let user_id = nix::unistd::Uid::from_raw(user_id); @@ -70,10 +71,12 @@ fn try_dropping_root_nix(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustmen // Get group id (from caller of sudo) let Ok(group_id) = std::env::var("SUDO_GID") else { warn!("Unable to get group id of calling user. Unable to adjust"); + adjustments.privilege = PrivilegeAdjustment::Failed; return; }; let Ok(group_id) = group_id.parse() else { warn!("Unable to parse group id. Unable to adjust"); + adjustments.privilege = PrivilegeAdjustment::Failed; return; }; let group_id = nix::unistd::Gid::from_raw(group_id); @@ -95,21 +98,22 @@ fn try_dropping_root_nix(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustmen Ok(uid) => { if uid.real.is_root() || uid.effective.is_root() || uid.saved.is_root() { warn!("User is root after changing"); + adjustments.privilege = PrivilegeAdjustment::Failed; } else { info!("Adjustment successful. No longer running as root"); - *privilege_adjustment = PrivilegeAdjustment::Completed; + adjustments.privilege = PrivilegeAdjustment::Completed; } }, Err(e) => { warn!("Unable to get uid: {e}"); - *privilege_adjustment = PrivilegeAdjustment::Unknown; + adjustments.privilege = PrivilegeAdjustment::Unknown; }, } } #[cfg(target_os = "windows")] #[allow(unsafe_code)] -fn try_adjusting_privilege_windows(mut privilege_adjustment: ResMut<'_, PrivilegeAdjustment>) { +fn adjust_privilege_windows(mut adjustments: ResMut<'_, LockdownAdjustments>) { use windows::Win32::{ Foundation, Foundation::{ @@ -128,8 +132,6 @@ fn try_adjusting_privilege_windows(mut privilege_adjustment: ResMut<'_, Privileg }, }; - *privilege_adjustment = PrivilegeAdjustment::Failed; - // Get a handle to the current process's primary token let process = unsafe { GetCurrentProcess() }; let mut token = HANDLE::default(); @@ -137,6 +139,7 @@ fn try_adjusting_privilege_windows(mut privilege_adjustment: ResMut<'_, Privileg let result = unsafe { OpenProcessToken(process, desired_access, &mut token) }; if let Err(e) = result { warn!("Unable to open process token: {e}"); + adjustments.privilege = PrivilegeAdjustment::Failed; return; } @@ -151,8 +154,9 @@ fn try_adjusting_privilege_windows(mut privilege_adjustment: ResMut<'_, Privileg }; if let Err(e) = result { warn!("Unable to adjust token privilege: {e}"); + adjustments.privilege = PrivilegeAdjustment::Failed; } else { - *privilege_adjustment = PrivilegeAdjustment::Completed; + adjustments.privilege = PrivilegeAdjustment::Completed; } // Cleanup diff --git a/src/system_call.rs b/src/system_call.rs index 6648215..8f5d6d0 100644 --- a/src/system_call.rs +++ b/src/system_call.rs @@ -4,7 +4,7 @@ use bevy::prelude::*; #[reflect(Resource)] pub enum SystemCallAdjustment { #[default] - Unknown, + NotImplemented, } #[derive(Debug)] @@ -13,11 +13,8 @@ pub struct SystemCallPlugin; impl Plugin for SystemCallPlugin { fn build( &self, - app: &mut App, + _app: &mut App, ) { - app.register_type::(); - app.insert_resource(SystemCallAdjustment::Unknown); - // TODO maybe use extrasafe, contains more than just system_calls } }