mirror of
https://github.com/girlbossceo/hardened_malloc-rs.git
synced 2025-04-29 14:19:25 -04:00
initial implementation of dynamic and static linking
Signed-off-by: strawberry <strawberry@pupbrain.dev>
This commit is contained in:
parent
24ba28ca8c
commit
ce3e95770e
2 changed files with 142 additions and 31 deletions
31
Cargo.toml
31
Cargo.toml
|
@ -1,24 +1,43 @@
|
||||||
[package]
|
[package]
|
||||||
name = "hardened_malloc-rs"
|
name = "hardened_malloc-rs"
|
||||||
description = "hardened_malloc rust wrapper"
|
description = "hardened_malloc rust wrapper"
|
||||||
authors = ["strawberry <strawberry@pupbrain.dev>"]
|
authors = ["strawberry <strawberry@puppygock.gay>"]
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "Apache-2.0 and MIT"
|
license = "Apache-2.0 and MIT"
|
||||||
repository = "https://github.com/girlbossceo/hardened_malloc"
|
repository = "https://github.com/girlbossceo/hardened_malloc-rs"
|
||||||
|
keywords = ["hardened_malloc", "malloc", "hardened memory allocator", "security", "bindings", "ffi"]
|
||||||
categories = ["api-bindings", "memory-management"]
|
categories = ["api-bindings", "memory-management"]
|
||||||
keywords = ["hardened_malloc", "malloc", "hardened memory allocator", "security"]
|
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
|
# everything after the '+' is the latest GrapheneOS hardened_malloc repo tag
|
||||||
|
version = "0.1.0+12"
|
||||||
|
|
||||||
|
# https://github.com/GrapheneOS/hardened_malloc?tab=readme-ov-file#dependencies
|
||||||
|
# Debian stable (currently Debian 12) determines the most ancient set of supported dependencies
|
||||||
|
#
|
||||||
|
# (Debian 12 has Rust 1.63.0)
|
||||||
|
rust-version = "1.63.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["light", "clang"]
|
default = ["light", "gcc", "static"]
|
||||||
|
|
||||||
## compiler
|
## compiler
|
||||||
clang = []
|
clang = []
|
||||||
gcc = []
|
gcc = []
|
||||||
|
|
||||||
## hardened_malloc config
|
## linking method
|
||||||
|
dynamic = []
|
||||||
|
|
||||||
|
|
||||||
|
# todo: remove this warning
|
||||||
|
# https://github.com/girlbossceo/hardened_malloc-rs/issues/5
|
||||||
|
# IF USING CLANG:
|
||||||
|
#
|
||||||
|
# REQUIRES BUILDING YOUR CRATE WITH `RUSTFLAGS='-Clink-arg=-fuse-ld=lld'`
|
||||||
|
# REQUIRES llvm, llvm-ar, lld, clang, libclang, AND llvm-libs
|
||||||
|
static = []
|
||||||
|
|
||||||
|
## hardened_malloc config
|
||||||
light = []
|
light = []
|
||||||
# "standard" feature is "default.mk" config in hardened_malloc
|
# "standard" feature is "default.mk" config in hardened_malloc
|
||||||
standard = []
|
standard = []
|
142
build.rs
142
build.rs
|
@ -26,28 +26,59 @@ fn update_submodules() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_compiler(compiler: &'static str) -> &'static str {
|
fn check_compiler_and_linker(compiler: &'static str, linker: &'static str) -> (&'static str, &'static str) {
|
||||||
let args = "-v";
|
println!("checking if compiler {compiler} exists");
|
||||||
|
|
||||||
println!("checking if compiler {} exists", compiler);
|
let compiler_ret = Command::new(compiler).arg("--version").status();
|
||||||
|
|
||||||
let ret = Command::new(compiler).arg(args).status();
|
match compiler_ret.map(|status| (status.success(), status.code())) {
|
||||||
|
|
||||||
match ret.map(|status| (status.success(), status.code())) {
|
|
||||||
Ok((true, _)) => println!("compiler check exited successfully"),
|
Ok((true, _)) => println!("compiler check exited successfully"),
|
||||||
Ok((false, Some(exit_code))) => panic!("compiler check failed with error code {}", exit_code),
|
Ok((false, Some(exit_code))) => panic!("compiler check failed with error code {exit_code}"),
|
||||||
Ok((false, None)) => panic!("compiler check exited with no error code, possibly killed by system"),
|
Ok((false, None)) => panic!("compiler check exited with no error code, possibly killed by system"),
|
||||||
Err(e) => panic!("compiler check failed with error: {}", e),
|
Err(e) => panic!("compiler check failed with error: {e}"),
|
||||||
}
|
}
|
||||||
compiler
|
|
||||||
|
println!("checking if linker {linker} exists");
|
||||||
|
|
||||||
|
let linker_ret = Command::new(linker).arg("--version").status();
|
||||||
|
|
||||||
|
match linker_ret.map(|status| (status.success(), status.code())) {
|
||||||
|
Ok((true, _)) => println!("linker check exited successfully"),
|
||||||
|
Ok((false, Some(exit_code))) => {
|
||||||
|
if exit_code == 1 {
|
||||||
|
println!("linker check exited with exit code 1, assuming it's available");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ok((false, None)) => panic!("linker check exited with no error code, possibly killed by system"),
|
||||||
|
Err(e) => panic!("linker check failed with error: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if linker.contains("lld") {
|
||||||
|
println!("checking if llvm-ar exists as lld is being used (static build)");
|
||||||
|
|
||||||
|
let llvm_ar_ret = Command::new("llvm-ar").arg("--version").status();
|
||||||
|
|
||||||
|
match llvm_ar_ret.map(|status| (status.success(), status.code())) {
|
||||||
|
Ok((true, _)) => println!("llvm-ar check exited successfully"),
|
||||||
|
Ok((false, Some(exit_code))) => panic!("llvm-ar check failed with error code {exit_code}"),
|
||||||
|
Ok((false, None)) => panic!("llvm-ar check exited with no error code, possibly killed by system"),
|
||||||
|
Err(e) => panic!("llvm-ar check failed with error: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(compiler, linker)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(all(feature = "gcc", feature = "clang"))]
|
#[cfg(all(feature = "gcc", feature = "clang"))]
|
||||||
compile_error!("gcc OR clang must be enabled, not both.");
|
compile_error!("gcc OR clang must be enabled, not both.");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "static", feature = "dynamic"))]
|
||||||
|
compile_error!("static OR dynamic must be enabled, not both.");
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rerun-if-changed=src/hardened_malloc/");
|
println!("cargo:rerun-if-changed=src/hardened_malloc/");
|
||||||
|
println!("cargo:rerun-if-changed=src/hardened_malloc/LICENSE");
|
||||||
println!("cargo:rerun-if-changed=src/hardened_malloc/.git");
|
println!("cargo:rerun-if-changed=src/hardened_malloc/.git");
|
||||||
println!("cargo:rerun-if-changed=src/hardened_malloc/.git/HEAD");
|
println!("cargo:rerun-if-changed=src/hardened_malloc/.git/HEAD");
|
||||||
println!("cargo:rerun-if-changed=src/hardened_malloc/.git/index");
|
println!("cargo:rerun-if-changed=src/hardened_malloc/.git/index");
|
||||||
|
@ -60,37 +91,42 @@ fn main() {
|
||||||
update_submodules();
|
update_submodules();
|
||||||
}
|
}
|
||||||
|
|
||||||
let compiler = if cfg!(feature = "gcc") {
|
let (compiler, linker) = if cfg!(feature = "gcc") && cfg!(feature = "dynamic") {
|
||||||
check_compiler("gcc")
|
check_compiler_and_linker("gcc", "ld")
|
||||||
|
} else if cfg!(feature = "gcc") && cfg!(feature = "static") {
|
||||||
|
check_compiler_and_linker("gcc", "gcc-ar")
|
||||||
|
} else if cfg!(feature = "clang") && cfg!(feature = "dynamic") {
|
||||||
|
check_compiler_and_linker("clang", "ld")
|
||||||
} else {
|
} else {
|
||||||
check_compiler("clang")
|
check_compiler_and_linker("clang", "ld.lld")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// "default" is hardened_malloc's default.mk. this crate's feature uses
|
||||||
|
// "standard" for "default"
|
||||||
let variant = if cfg!(feature = "light") {
|
let variant = if cfg!(feature = "light") {
|
||||||
"light"
|
"light"
|
||||||
} else {
|
} else {
|
||||||
"default" // "default" is hardened_malloc's default.mk. this crate's feature
|
"default"
|
||||||
// uses "standard" for "default"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let build_args = [
|
let build_args: Vec<String> = vec![
|
||||||
format!("VARIANT={}", variant),
|
format!("VARIANT={}", variant),
|
||||||
format!("V={}", "1"),
|
format!("V={}", "1"), // verbose (?)
|
||||||
format!("OUT={}", &out_dir),
|
format!("OUT={}", &out_dir),
|
||||||
format!("CC={}", compiler),
|
format!("CC={}", compiler),
|
||||||
];
|
];
|
||||||
|
|
||||||
//TODO: handle support for explicit make flags like N_ARENA=1 and such
|
// TODO: handle support for explicit make flags like N_ARENA=1 and such
|
||||||
let mut make_command = Command::new("make");
|
let mut make_command = Command::new("make");
|
||||||
|
|
||||||
println!("running {:?} with args {:?}", make_command, build_args);
|
println!("running {:?} with args {:?}", make_command, build_args);
|
||||||
|
|
||||||
let make_output = make_command
|
let make_output = make_command
|
||||||
.current_dir("src/hardened_malloc/")
|
.current_dir("src/hardened_malloc/")
|
||||||
.args(build_args)
|
.args(build_args.clone())
|
||||||
.output()
|
.output()
|
||||||
.unwrap_or_else(|error| {
|
.unwrap_or_else(|error| {
|
||||||
panic!("failed to run 'make {}': ", error);
|
panic!("failed to run 'make {build_args:?}': {error}");
|
||||||
});
|
});
|
||||||
|
|
||||||
if !make_output.status.success() {
|
if !make_output.status.success() {
|
||||||
|
@ -102,11 +138,67 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg!(feature = "light") {
|
if cfg!(feature = "static") {
|
||||||
println!("cargo:rustc-link-lib=dylib=hardened_malloc-light");
|
let ar_lib_output = if cfg!(feature = "light") {
|
||||||
println!("cargo:rustc-link-search={}", out_dir);
|
out_dir.clone() + "/libhardened_malloc-light.a"
|
||||||
} else {
|
} else {
|
||||||
println!("cargo:rustc-link-lib=dylib=hardened_malloc");
|
out_dir.clone() + "/libhardened_malloc.a"
|
||||||
println!("cargo:rustc-link-search={}", out_dir);
|
};
|
||||||
|
|
||||||
|
let ar_args = [
|
||||||
|
"rcs".to_owned(),
|
||||||
|
ar_lib_output,
|
||||||
|
out_dir.clone() + "/chacha.o",
|
||||||
|
out_dir.clone() + "/h_malloc.o",
|
||||||
|
out_dir.clone() + "/memory.o",
|
||||||
|
out_dir.clone() + "/new.o",
|
||||||
|
out_dir.clone() + "/pages.o",
|
||||||
|
out_dir.clone() + "/random.o",
|
||||||
|
out_dir.clone() + "/util.o",
|
||||||
|
out_dir.clone() + "/new.o",
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut ar_command = Command::new("llvm-ar");
|
||||||
|
|
||||||
|
println!("running {:?} with args {:?}", ar_command, ar_args);
|
||||||
|
|
||||||
|
let ar_output = ar_command.args(ar_args).output().unwrap_or_else(|error| {
|
||||||
|
panic!("Failed to run '{ar_command:?}': {error}");
|
||||||
|
});
|
||||||
|
|
||||||
|
if !ar_output.status.success() {
|
||||||
|
panic!(
|
||||||
|
"creating static lib of hardened_malloc failed:\n{:?}\n{}\n{}",
|
||||||
|
ar_command,
|
||||||
|
String::from_utf8_lossy(&ar_output.stdout),
|
||||||
|
String::from_utf8_lossy(&ar_output.stderr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(feature = "light") {
|
||||||
|
println!("cargo:rustc-link-search={}", out_dir);
|
||||||
|
println!("cargo:rustc-link-lib=static=hardened_malloc-light");
|
||||||
|
} else {
|
||||||
|
println!("cargo:rustc-link-search={}", out_dir);
|
||||||
|
println!("cargo:rustc-link-lib=static=hardened_malloc");
|
||||||
|
}
|
||||||
|
} else if cfg!(feature = "dynamic") {
|
||||||
|
// TODO: is this needed?
|
||||||
|
let target = env::var("TARGET").unwrap();
|
||||||
|
if target.contains("apple") || target.contains("freebsd") || target.contains("openbsd") {
|
||||||
|
println!("cargo:rustc-link-lib=dylib=c++");
|
||||||
|
} else if target.contains("linux") {
|
||||||
|
println!("cargo:rustc-link-lib=dylib=stdc++");
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(feature = "light") {
|
||||||
|
println!("cargo:rustc-link-lib=dylib=hardened_malloc-light");
|
||||||
|
println!("cargo:rustc-link-search={}", out_dir);
|
||||||
|
} else {
|
||||||
|
println!("cargo:rustc-link-lib=dylib=hardened_malloc");
|
||||||
|
println!("cargo:rustc-link-search={}", out_dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("cargo:out_dir={}", out_dir);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue