Skip to content

Commit

Permalink
Architecture independent code, mkdir* hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
noproto committed Jul 28, 2021
1 parent 892e3f8 commit f5807c1
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 138 deletions.
2 changes: 1 addition & 1 deletion src/application/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ glob = { version = "0.3" }
goblin = { version = "0.4" }
# Cryptographic dependencies
sha3 = { version = "0.9" }
blake3 = { version = "0.3" }
blake3 = { version = "1.0" }
argon2 = { version = "0.2" }
crypto_box = { version = "0.6" }

Expand Down
8 changes: 0 additions & 8 deletions src/application/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,6 @@ fn run_add(class: &OsStr, path: &OsStr, value: Option<&OsStr>) -> Result<(), Box
||lib.contains("ld-linux")))
.map(|lib| String::from(lib))
.collect();
let all_library_names: Vec<String> = all_library_paths.iter()
.filter_map(|lib| std::path::Path::new(lib).file_name())
.filter_map(|filename| filename.to_str())
.map(|filename_str| String::from(filename_str))
.collect();
for lib_name in all_library_names.iter() {
added_whitelist_entries.push((String::from("Filesystem/Path/Library"), path_string.clone(), String::from(lib_name)));
}
for lib_path in all_library_paths.iter() {
added_whitelist_entries.push((String::from("Filesystem/Path/Library"), path_string.clone(), String::from(lib_path)));
}
Expand Down
8 changes: 8 additions & 0 deletions src/installer/common/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ use std::{error::Error,
fn db_init() -> Result<(), Box<dyn Error>> {
db_load("Schema")?;
db_load("Default")?;
let bin_target_path: PathBuf = PathBuf::from(format!("{}/target/release/whitebeam", env!("PWD")));
let mut child = Command::new(bin_target_path).args(&["--setting", "SystemArchitecture", std::env::consts::ARCH]).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn()?;
// TODO: _output, debugging information follows:
let output = child.wait_with_output()?;
print!("stdout: {}", std::str::from_utf8(&output.stdout).unwrap());
if output.stderr.len() > 0 {
eprint!("stderr: {}", std::str::from_utf8(&output.stderr).unwrap());
}
Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions src/installer/platforms/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub fn run_install() {
chmod 4555 /opt/WhiteBeam/libwhitebeam.so;
whitebeam --load Schema;
whitebeam --load Default;
whitebeam --setting SystemArchitecture `arch`;
whitebeam --load Essential;
/etc/init.d/whitebeam start;
echo '/lib/libwhitebeam.so' | tee -a /etc/ld.so.preload")
Expand Down
2 changes: 1 addition & 1 deletion src/library/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ automod = { version = "1.0" }
glob = { version = "0.3" }
# Cryptographic dependencies
sha3 = { version = "0.9" }
blake3 = { version = "0.3" }
blake3 = { version = "1.0" }
argon2 = { version = "0.2" }

[features]
Expand Down
17 changes: 9 additions & 8 deletions src/library/common/action/actions/add_flags.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
#[macro_use]
build_action! { AddFlags (_src_prog, hook, _arg_id, args, do_return, return_value) {
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
let num_args = args.len();
let flags = match (library, symbol) {
let flags = match (library_basename, symbol) {
// Filesystem
("/lib/x86_64-linux-gnu/libc.so.6", "creat") |
("/lib/x86_64-linux-gnu/libc.so.6", "creat64") => {
("libc.so.6", "creat") |
("libc.so.6", "creat64") => {
libc::O_WRONLY | libc::O_CREAT | libc::O_TRUNC
},
("/lib/x86_64-linux-gnu/libc.so.6", "lchown") => {
("libc.so.6", "lchown") => {
libc::AT_SYMLINK_NOFOLLOW
},
("/lib/x86_64-linux-gnu/libc.so.6", "rmdir") => {
("libc.so.6", "rmdir") => {
libc::AT_REMOVEDIR
},
_ => 0
} as usize;
let position = match (library, symbol) {
let position = match (library_basename, symbol) {
// Filesystem
("/lib/x86_64-linux-gnu/libc.so.6", "creat") |
("/lib/x86_64-linux-gnu/libc.so.6", "creat64") => {
("libc.so.6", "creat") |
("libc.so.6", "creat64") => {
if num_args == 3 {
2
} else {
Expand Down
7 changes: 4 additions & 3 deletions src/library/common/action/actions/canonicalize_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
build_action! { CanonicalizePath (_src_prog, hook, arg_id, args, do_return, return_value) {
// TODO: Don't fatal if the Path cannot be canonicalized (return -1/0). NULL handling for dlopen?
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
let file_index = args.iter().position(|arg| arg.id == arg_id).expect("WhiteBeam: Lost track of environment");
let file_argument: crate::common::db::ArgumentRow = args[file_index].clone();
let file_value = file_argument.real as *const libc::c_char;
let new_file_value: std::ffi::OsString = match (library, symbol) {
("/lib/x86_64-linux-gnu/libdl.so.2", "dlopen") |
("/lib/x86_64-linux-gnu/libdl.so.2", "dlmopen") => {
let new_file_value: std::ffi::OsString = match (library_basename, symbol) {
("libdl.so.2", "dlopen") |
("libdl.so.2", "dlmopen") => {
// TODO: Remove dependency on procfs here
let fd: libc::c_int = unsafe { libc::open(file_value, libc::O_PATH) };
if fd == -1 {
Expand Down
29 changes: 15 additions & 14 deletions src/library/common/action/actions/consume_variadic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ build_action! { ConsumeVariadic (_src_prog, hook, arg_id, args, do_return, retur
let variadic_start = args.iter().position(|arg| arg.id == arg_id).expect("WhiteBeam: Lost track of environment");
let variadic_start_id: i64 = args[variadic_start].id;
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
let va_arg_iter: Vec<&crate::common::db::ArgumentRow> = args.iter().filter(|arg| arg.variadic && (arg.id == variadic_start_id)).collect();
let va_arg_iter_len = va_arg_iter.len();
match (library, symbol) {
("/lib/x86_64-linux-gnu/libc.so.6", "execl") |
("/lib/x86_64-linux-gnu/libc.so.6", "execle") |
("/lib/x86_64-linux-gnu/libc.so.6", "execlp") => {
match (library_basename, symbol) {
("libc.so.6", "execl") |
("libc.so.6", "execle") |
("libc.so.6", "execlp") => {
assert!(va_arg_iter_len > 0, "WhiteBeam: Insufficient arguments to ConsumeVariadic action");
let mut argv_vec: Vec<*const libc::c_char> = Vec::new();
for arg in va_arg_iter {
Expand All @@ -22,16 +23,16 @@ build_action! { ConsumeVariadic (_src_prog, hook, arg_id, args, do_return, retur
args.retain(|arg| !(arg.variadic && (arg.id == variadic_start_id)));
// TODO: Update the position of the following arguments
},
("/lib/x86_64-linux-gnu/libc.so.6", "open") |
("/lib/x86_64-linux-gnu/libc.so.6", "open64") |
("/lib/x86_64-linux-gnu/libc.so.6", "openat") |
("/lib/x86_64-linux-gnu/libc.so.6", "openat64") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open_2") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open64") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open64_2") |
("/lib/x86_64-linux-gnu/libc.so.6", "__openat_2") |
("/lib/x86_64-linux-gnu/libc.so.6", "__openat64_2") => {
("libc.so.6", "open") |
("libc.so.6", "open64") |
("libc.so.6", "openat") |
("libc.so.6", "openat64") |
("libc.so.6", "__open") |
("libc.so.6", "__open_2") |
("libc.so.6", "__open64") |
("libc.so.6", "__open64_2") |
("libc.so.6", "__openat_2") |
("libc.so.6", "__openat64_2") => {
assert!(va_arg_iter_len > 0, "WhiteBeam: Insufficient arguments to ConsumeVariadic action");
let flags = args[variadic_start-1].real as libc::c_int;
let has_variadic_arg: bool = (flags & (libc::O_CREAT | libc::O_TMPFILE)) > 0;
Expand Down
15 changes: 8 additions & 7 deletions src/library/common/action/actions/filter_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ build_action! { FilterEnvironment (_src_prog, hook, arg_id, args, do_return, ret
// Enforce LD_AUDIT, LD_BIND_NOT, WB_PROG
// TODO: Avoid leaking memory (NB: this action is often called before execve on Linux)
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
let envp_index: usize = {
// Non-positional functions
match (library, symbol) {
("/lib/x86_64-linux-gnu/libc.so.6", "execl") |
("/lib/x86_64-linux-gnu/libc.so.6", "execlp") |
("/lib/x86_64-linux-gnu/libc.so.6", "execv") |
("/lib/x86_64-linux-gnu/libc.so.6", "execvp") => {
match (library_basename, symbol) {
("libc.so.6", "execl") |
("libc.so.6", "execlp") |
("libc.so.6", "execv") |
("libc.so.6", "execvp") => {
args.iter().position(|arg| arg.id == -1).expect("WhiteBeam: Lost track of environment")
}
_ => {
Expand Down Expand Up @@ -89,8 +90,8 @@ build_action! { FilterEnvironment (_src_prog, hook, arg_id, args, do_return, ret
}
};
let mut env_vec: Vec<*const libc::c_char> = Vec::new();
let program_path: std::ffi::OsString = match (library, symbol) {
("/lib/x86_64-linux-gnu/libc.so.6", "fexecve") => platform::canonicalize_fd(args[0].real as i32).expect("WhiteBeam: Lost track of environment").into_os_string(),
let program_path: std::ffi::OsString = match (library_basename, symbol) {
("libc.so.6", "fexecve") => platform::canonicalize_fd(args[0].real as i32).expect("WhiteBeam: Lost track of environment").into_os_string(),
_ => unsafe { crate::common::convert::c_char_to_osstring(args[0].real as *const libc::c_char) }
};
if update_ld_audit {
Expand Down
33 changes: 17 additions & 16 deletions src/library/common/action/actions/open_file_descriptor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
fn fail(library: &str, symbol: &str) -> isize {
match (library, symbol) {
("/lib/x86_64-linux-gnu/libc.so.6", "fopen") |
("/lib/x86_64-linux-gnu/libc.so.6", "fopen64") => 0,
fn fail(library_basename: &str, symbol: &str) -> isize {
match (library_basename, symbol) {
("libc.so.6", "fopen") |
("libc.so.6", "fopen64") => 0,
_ => -1
}
}
Expand All @@ -11,14 +11,15 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
// TODO: Refactor
// TODO: No O_CLOEXEC leads to inherited fd's in children
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
let file_index = args.iter().position(|arg| arg.id == arg_id).expect("WhiteBeam: Lost track of environment");
let file_argument: crate::common::db::ArgumentRow = args[file_index].clone();
let file_value = file_argument.real as *const libc::c_char;
let flags: i32 = match (library, symbol) {
let flags: i32 = match (library_basename, symbol) {
// Filesystem
("/lib/x86_64-linux-gnu/libc.so.6", "fopen") |
("/lib/x86_64-linux-gnu/libc.so.6", "fopen64") => {
("libc.so.6", "fopen") |
("libc.so.6", "fopen64") => {
let mode_osstring: std::ffi::OsString = unsafe { crate::common::convert::c_char_to_osstring(args[file_index+1].clone().real as *const libc::c_char) };
let mode_string = mode_osstring.into_string().expect("WhiteBeam: Unexpected null reference");
// Ignore ",ccs=?"
Expand All @@ -44,8 +45,8 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
};
regular_flags | glibc_extensions
},
("/lib/x86_64-linux-gnu/libc.so.6", "truncate") |
("/lib/x86_64-linux-gnu/libc.so.6", "truncate64") => {
("libc.so.6", "truncate") |
("libc.so.6", "truncate64") => {
let length: i64 = args[file_index+1].clone().real as i64;
match length {
0 => libc::O_WRONLY | libc::O_TRUNC,
Expand Down Expand Up @@ -86,7 +87,7 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
return (hook, args, do_return, return_value);
}
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
let any = String::from("ANY");
Expand All @@ -107,15 +108,15 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
return (hook, args, do_return, return_value);
}
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
// NB: Do not dereference paths here
let canonical_path = match platform::canonicalize_fd(dirfd as i32) {
Some(p) => p,
None => {
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
};
Expand All @@ -136,7 +137,7 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
return (hook, args, do_return, return_value);
}
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
// Permit whitelisted directories
Expand All @@ -151,7 +152,7 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
return (hook, args, do_return, return_value);
}
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
// Permit authorized writes
Expand All @@ -169,12 +170,12 @@ build_action! { OpenFileDescriptor (src_prog, hook, arg_id, args, do_return, ret
return (hook, args, do_return, return_value);
}
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
return (hook, args, do_return, return_value);
}
// Deny by default
event::send_log_event(event::LogClass::Warn as i64, format!("Prevention: Blocked {} from writing to {} (OpenFileDescriptor)", &src_prog, &target_directory));
eprintln!("WhiteBeam: {}: Permission denied", &full_path);
do_return = true;
return_value = fail(library, symbol);
return_value = fail(library_basename, symbol);
}}
62 changes: 33 additions & 29 deletions src/library/common/action/actions/redirect_function.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,66 @@
#[macro_use]
build_action! { RedirectFunction (_src_prog, hook, _arg_id, args, do_return, return_value) {
let library: &str = &hook.library;
let library_basename: &str = library.rsplit('/').next().unwrap_or(library);
let symbol: &str = &hook.symbol;
hook.symbol = match (library, symbol) {
hook.symbol = match (library_basename, symbol) {
// Execution
("/lib/x86_64-linux-gnu/libc.so.6", "execl") |
("/lib/x86_64-linux-gnu/libc.so.6", "execle") |
("/lib/x86_64-linux-gnu/libc.so.6", "execlp") |
("/lib/x86_64-linux-gnu/libc.so.6", "execv") |
("/lib/x86_64-linux-gnu/libc.so.6", "execvp") |
("/lib/x86_64-linux-gnu/libc.so.6", "execvpe") => {
("libc.so.6", "execl") |
("libc.so.6", "execle") |
("libc.so.6", "execlp") |
("libc.so.6", "execv") |
("libc.so.6", "execvp") |
("libc.so.6", "execvpe") => {
String::from("execve")
},
// Filesystem
("/lib/x86_64-linux-gnu/libc.so.6", "truncate") |
("/lib/x86_64-linux-gnu/libc.so.6", "truncate64") => {
("libc.so.6", "truncate") |
("libc.so.6", "truncate64") => {
String::from("ftruncate")
},
("/lib/x86_64-linux-gnu/libc.so.6", "fopen") |
("/lib/x86_64-linux-gnu/libc.so.6", "fopen64") => {
("libc.so.6", "fopen") |
("libc.so.6", "fopen64") => {
String::from("fdopen")
},
("/lib/x86_64-linux-gnu/libc.so.6", "symlink") => {
("libc.so.6", "symlink") => {
String::from("symlinkat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "unlink") |
("/lib/x86_64-linux-gnu/libc.so.6", "rmdir") => {
("libc.so.6", "mkdir") => {
String::from("mkdirat")
},
("libc.so.6", "unlink") |
("libc.so.6", "rmdir") => {
String::from("unlinkat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "link") => {
("libc.so.6", "link") => {
String::from("linkat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "rename") => {
("libc.so.6", "rename") => {
String::from("renameat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "chown") |
("/lib/x86_64-linux-gnu/libc.so.6", "lchown") => {
("libc.so.6", "chown") |
("libc.so.6", "lchown") => {
String::from("fchownat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "chmod") => {
("libc.so.6", "chmod") => {
String::from("fchmodat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "creat") |
("/lib/x86_64-linux-gnu/libc.so.6", "open") |
("/lib/x86_64-linux-gnu/libc.so.6", "creat64") |
("/lib/x86_64-linux-gnu/libc.so.6", "open64") => {
("libc.so.6", "creat") |
("libc.so.6", "open") |
("libc.so.6", "creat64") |
("libc.so.6", "open64") => {
String::from("openat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "mknod") => {
("libc.so.6", "mknod") => {
String::from("mknodat")
},
("/lib/x86_64-linux-gnu/libc.so.6", "__open") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open_2") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open64") |
("/lib/x86_64-linux-gnu/libc.so.6", "__open64_2") => {
("libc.so.6", "__open") |
("libc.so.6", "__open_2") |
("libc.so.6", "__open64") |
("libc.so.6", "__open64_2") => {
String::from("__openat_2")
},
("/lib/x86_64-linux-gnu/libc.so.6", "__xmknod") => {
("libc.so.6", "__xmknod") => {
String::from("__xmknodat")
},
_ => { unimplemented!("WhiteBeam: The '{}' symbol (from {}) is not supported by the RedirectFunction action", symbol, library) }
Expand Down
Loading

0 comments on commit f5807c1

Please sign in to comment.