From daa9de19a2dbc9a837aefbb78e231db7946a8ac5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 25 Dec 2022 12:48:59 +0100 Subject: [PATCH] [WIP] Use landlock --- .github/workflows/main.yml | 1 + build_system/Cargo.lock | 95 ++++++++++++++++++++++++++++++++++++++ build_system/Cargo.toml | 2 + build_system/landlock.rs | 75 ++++++++++++++++++++++++++++++ build_system/main.rs | 17 ++++++- build_system/rustc_info.rs | 19 ++++++++ 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 build_system/landlock.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ee94146c..a71a70b48 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -121,6 +121,7 @@ jobs: mkdir wine_shims rustc patches/bcryptprimitives.rs -Copt-level=3 -Clto=fat --out-dir wine_shims --target x86_64-pc-windows-gnu echo "WINEPATH=$(pwd)/wine_shims" >> $GITHUB_ENV + wine echo || true # create ~/.wine to ensure wine works even when the build system is restricted using landlock - name: Build run: ./y.sh build --sysroot none diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index 86268e191..79705d360 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -2,6 +2,101 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "landlock" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dafb8a4afee64f167eb2b52d32f0eea002e41a7a6450e68c799c8ec3a81a634c" +dependencies = [ + "enumflags2", + "libc", + "thiserror", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "y" version = "0.1.0" +dependencies = [ + "landlock", +] diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml index feed2b6ea..60d2a635b 100644 --- a/build_system/Cargo.toml +++ b/build_system/Cargo.toml @@ -11,6 +11,8 @@ path = "main.rs" unstable-features = [] # for rust-analyzer # Do not add any dependencies +[target.'cfg(target_os = "linux")'.dependencies] +landlock = "0.4" [profile.dev] debug = 1 diff --git a/build_system/landlock.rs b/build_system/landlock.rs new file mode 100644 index 000000000..f95460bec --- /dev/null +++ b/build_system/landlock.rs @@ -0,0 +1,75 @@ +use std::env; +use std::path::Path; + +use landlock::{ + path_beneath_rules, Access, AccessFs, CompatLevel, Compatible, RulesetAttr, RulesetCreated, + RulesetCreatedAttr, ABI, +}; + +use crate::rustc_info::get_cargo_home; + +/// Base landlock ruleset +/// +/// This allows access to various essential system locations. +pub(super) fn base_ruleset() -> RulesetCreated { + let abi = ABI::V2; + let access_all = AccessFs::from_all(abi); + let access_read = AccessFs::from_read(abi); + landlock::Ruleset::default() + .set_compatibility(CompatLevel::SoftRequirement) + .handle_access(AccessFs::Refer) + .unwrap() + .set_compatibility(CompatLevel::BestEffort) + .handle_access(access_all) + .unwrap() + .create() + .unwrap() + .add_rules(path_beneath_rules(&["/"], access_read)) + .unwrap() + .add_rules(path_beneath_rules(&["/tmp", "/dev/null"], access_all)) + .unwrap() +} + +pub(super) fn lock_fetch() { + let abi = ABI::V2; + let access_all = AccessFs::from_all(abi); + base_ruleset() + .add_rules(path_beneath_rules([env::current_dir().unwrap().join("download")], access_all)) + .unwrap() + .restrict_self() + .unwrap(); +} + +pub(super) fn lock_build(cargo: &Path, frozen: bool) { + let abi = ABI::V2; + let access_all = AccessFs::from_all(abi); + + let ruleset = base_ruleset() + .add_rules(path_beneath_rules( + &[env::current_dir().unwrap().join("build"), env::current_dir().unwrap().join("dist")], + access_all, + )) + .unwrap() + .add_rules(path_beneath_rules( + &[ + #[allow(deprecated)] + &std::env::home_dir().unwrap().join(".wine"), + Path::new("/run/user/"), + ], + access_all, + )) + .unwrap(); + + let ruleset = if frozen { + ruleset + } else { + ruleset + .add_rules(path_beneath_rules( + &[get_cargo_home(cargo).join("git"), get_cargo_home(cargo).join("registry")], + access_all, + )) + .unwrap() + }; + + ruleset.restrict_self().unwrap(); +} diff --git a/build_system/main.rs b/build_system/main.rs index 99e614665..56eddd858 100644 --- a/build_system/main.rs +++ b/build_system/main.rs @@ -12,6 +12,8 @@ mod bench; mod build_backend; mod build_sysroot; mod config; +#[cfg(target_os = "linux")] +mod landlock; mod path; mod prepare; mod rustc_info; @@ -130,7 +132,7 @@ fn main() { out_dir = current_dir.join(out_dir); if command == Command::Prepare { - prepare::prepare(&path::Dirs { + let dirs = path::Dirs { source_dir: current_dir.clone(), download_dir: download_dir .map(|dir| current_dir.join(dir)) @@ -138,7 +140,14 @@ fn main() { build_dir: PathBuf::from("dummy_do_not_use"), dist_dir: PathBuf::from("dummy_do_not_use"), frozen, - }); + }; + + std::fs::create_dir_all(&dirs.download_dir).unwrap(); + + #[cfg(target_os = "linux")] + landlock::lock_fetch(); + + prepare::prepare(&dirs); process::exit(0); } @@ -186,6 +195,10 @@ fn main() { }; std::fs::create_dir_all(&dirs.build_dir).unwrap(); + std::fs::create_dir_all(&dirs.dist_dir).unwrap(); + + #[cfg(target_os = "linux")] + landlock::lock_build(&bootstrap_host_compiler.cargo, frozen); { // Make sure we always explicitly specify the target dir diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index 5b71504e9..513f0bc34 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -27,6 +27,25 @@ pub(crate) fn get_toolchain_name() -> String { String::from_utf8(active_toolchain).unwrap().trim().split_once(' ').unwrap().0.to_owned() } +#[cfg(target_os = "linux")] +pub(crate) fn get_cargo_home(cargo: &Path) -> PathBuf { + let cargo_home = Command::new(cargo) + .stderr(Stdio::inherit()) + .args(&["-Zunstable-options", "config", "get", "--format=json-value", "home"]) + .output() + .unwrap() + .stdout; + PathBuf::from( + String::from_utf8(cargo_home) + .unwrap() + .trim() + .strip_prefix('"') + .unwrap() + .strip_suffix('"') + .unwrap(), + ) +} + pub(crate) fn get_cargo_path() -> PathBuf { if let Ok(cargo) = std::env::var("CARGO") { return PathBuf::from(cargo);