Skip to content

Commit

Permalink
Template hooks (2/2), Relicense
Browse files Browse the repository at this point in the history
  • Loading branch information
noproto committed Mar 9, 2020
1 parent 1b05225 commit 1369454
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 170 deletions.
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

7 changes: 7 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## License

Copyright (c) 2020 WhiteBeam Security, Inc.

This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

<a rel="license" href="http://creativecommons.org/licenses/by-nc/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc/4.0/88x31.png" /></a>
2 changes: 1 addition & 1 deletion src/application/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# General info
[package]
name = "whitebeam"
version = "0.1.1"
version = "0.1.2"
authors = ["WhiteBeam Security, Inc."]
edition = "2018"

Expand Down
2 changes: 1 addition & 1 deletion src/library/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# General info
[package]
name = "libwhitebeam"
version = "0.1.1"
version = "0.1.2"
authors = ["WhiteBeam Security, Inc."]
edition = "2018"

Expand Down
33 changes: 4 additions & 29 deletions src/library/platforms/linux/hooks/execv.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,9 @@
use libc::{c_char, c_int};
use std::ptr;
use crate::platforms::linux;
use crate::common::whitelist;
use crate::common::event;
use crate::common::hash;

#[macro_use]
/*
int execv(const char *path, char *const argv[]);
*/
#[no_mangle]
pub unsafe extern "C" fn execv(path: *const c_char, argv: *const *const c_char) -> c_int {
let envp: *const *const c_char = ptr::null();
let program = linux::c_char_to_osstring(path);
let env = linux::parse_env_collection(envp);
let hexdigest = hash::common_hash_file(&program);
let uid = linux::get_current_uid();
// Permit/deny execution
if whitelist::is_whitelisted(&program, &env, &hexdigest) {
event::send_exec_event(uid, &program, &hexdigest, true);
// Pass through
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next("execv\u{0}");
});
let execv_real: unsafe extern "C" fn(path: *const c_char, argv: *const *const c_char) -> c_int = std::mem::transmute(REAL);
execv_real(path, argv)
} else {
event::send_exec_event(uid, &program, &hexdigest, false);
*linux::errno_location() = libc::EACCES;
return -1
build_exec_hook! {
hook execv (program) {
// execv custom routines
}
}
59 changes: 18 additions & 41 deletions src/library/platforms/linux/hooks/execve.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,26 @@
use libc::{c_char, c_int};
use std::ffi::OsString;
use crate::platforms::linux;
use crate::common::whitelist;
use crate::common::event;
use crate::common::hash;

#[macro_use]
/*
int execve(const char *path, char *const argv[],
char *const envp[]);
*/
#[no_mangle]
pub unsafe extern "C" fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int {
let program = linux::c_char_to_osstring(path);
let env = linux::parse_env_collection(envp);
let hexdigest = hash::common_hash_file(&program);
let uid = linux::get_current_uid();
// Warn that legacy versions of man-db must disable seccomp
// TODO: Hook proper function
if program == "/usr/bin/man" {
let needle = OsString::from("MAN_DISABLE_SECCOMP");
let mut disable_defined = false;
for env_var in &env {
if env_var.0 == needle {
disable_defined = true;
break;
build_exec_hook! {
hook execve (program, envp) {
// execve custom routines
// Warn that legacy versions of man-db must disable seccomp
// TODO: Hook proper function
if program == "/usr/bin/man" {
let needle = std::ffi::OsString::from("MAN_DISABLE_SECCOMP");
let mut disable_defined = false;
let man_env = crate::platforms::linux::parse_env_collection(envp);
for env_var in man_env {
if env_var.0 == needle {
disable_defined = true;
break;
}
}
if !(disable_defined) {
eprintln!("WhiteBeam: Legacy man-db versions require MAN_DISABLE_SECCOMP=1")
}
}
if !(disable_defined) {
eprintln!("WhiteBeam: Legacy man-db versions require MAN_DISABLE_SECCOMP=1")
}
}
// Permit/deny execution
if whitelist::is_whitelisted(&program, &env, &hexdigest) {
event::send_exec_event(uid, &program, &hexdigest, true);
// Pass through
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next("execve\u{0}");
});
let execve_real: unsafe extern "C" fn(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int = std::mem::transmute(REAL);
execve_real(path, argv, envp)
} else {
event::send_exec_event(uid, &program, &hexdigest, false);
*linux::errno_location() = libc::EACCES;
return -1
}
}
48 changes: 12 additions & 36 deletions src/library/platforms/linux/hooks/execvp.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,17 @@
use libc::{c_char, c_int};
use std::ptr;
use crate::platforms::linux;
use crate::common::whitelist;
use crate::common::event;
use crate::common::hash;

#[macro_use]
/*
int execvp(const char *file, char *const argv[]);
*/
#[no_mangle]
pub unsafe extern "C" fn execvp(path: *const c_char, argv: *const *const c_char) -> c_int {
let envp: *const *const c_char = ptr::null();
let program = linux::c_char_to_osstring(path);
let env = linux::parse_env_collection(envp);
let which_abs_pathbuf = match linux::search_path(&program) {
Some(prog_path) => prog_path,
None => {
*linux::errno_location() = libc::ENOENT;
return -1 }
};
let abs_prog_str = which_abs_pathbuf.as_os_str();
let hexdigest = hash::common_hash_file(abs_prog_str);
let uid = linux::get_current_uid();
// Permit/deny execution
if whitelist::is_whitelisted(abs_prog_str, &env, &hexdigest) {
event::send_exec_event(uid, abs_prog_str, &hexdigest, true);
// Pass through
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next("execvp\u{0}");
});
let execvp_real: unsafe extern "C" fn(path: *const c_char, argv: *const *const c_char) -> c_int = std::mem::transmute(REAL);
execvp_real(path, argv)
} else {
event::send_exec_event(uid, abs_prog_str, &hexdigest, false);
*linux::errno_location() = libc::EACCES;
return -1
build_exec_hook! {
hook execvp (program) {
// execvp custom routines
// Repopulate program
let absolute_path = match crate::platforms::linux::search_path(&program) {
Some(abspath) => abspath,
None => {
*crate::platforms::linux::errno_location() = libc::ENOENT;
return -1 }
};
program = absolute_path.as_os_str().to_owned();
}
}
46 changes: 12 additions & 34 deletions src/library/platforms/linux/hooks/execvpe.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
use libc::{c_char, c_int};
use crate::platforms::linux;
use crate::common::whitelist;
use crate::common::event;
use crate::common::hash;

#[macro_use]
/*
int execvpe(const char *path, char *const argv[],
char *const envp[]);
*/
#[no_mangle]
pub unsafe extern "C" fn execvpe(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int {
let program = linux::c_char_to_osstring(path);
let env = linux::parse_env_collection(envp);
let which_abs_pathbuf = match linux::search_path(&program) {
Some(prog_path) => prog_path,
None => {
*linux::errno_location() = libc::ENOENT;
return -1 }
};
let abs_prog_str = which_abs_pathbuf.as_os_str();
let hexdigest = hash::common_hash_file(abs_prog_str);
let uid = linux::get_current_uid();
// Permit/deny execution
if whitelist::is_whitelisted(abs_prog_str, &env, &hexdigest) {
event::send_exec_event(uid, abs_prog_str, &hexdigest, true);
// Pass through
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next("execvpe\u{0}");
});
let execvpe_real: unsafe extern "C" fn(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int = std::mem::transmute(REAL);
execvpe_real(path, argv, envp)
} else {
event::send_exec_event(uid, abs_prog_str, &hexdigest, false);
*linux::errno_location() = libc::EACCES;
return -1
build_exec_hook! {
hook execvpe (program, envp) {
// execvpe custom routines
// Repopulate program
let absolute_path = match crate::platforms::linux::search_path(&program) {
Some(abspath) => abspath,
None => {
*crate::platforms::linux::errno_location() = libc::ENOENT;
return -1 }
};
program = absolute_path.as_os_str().to_owned();
}
}
82 changes: 75 additions & 7 deletions src/library/platforms/linux/hooks/template.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,89 @@
#[macro_export]
// TODO: Reduce duplication of code
// TODO: Add generic hook, fexecve

// TODO: Exec hook template
/*
// Exec hook template
macro_rules! build_exec_hook {
// Parameters for the hook template
(hook fn $func_name:ident ( $($v:ident : $t:ty),* ) -> $return_type:ty $body:block) => {
(hook $func_name:ident ($program: ident) $body:block) => {
// =====================================================================
// Generated code for the hook template
#[no_mangle]
pub unsafe extern "C" fn $func_name ( $($v : $t),* ) -> $return_type {
#[allow(unused_mut)]
pub unsafe extern "C" fn $func_name (mut path: *const libc::c_char, argv: *const *const libc::c_char) -> libc::c_int {
// Common hook code
let envp: *const *const libc::c_char = std::ptr::null();
let mut $program = crate::platforms::linux::c_char_to_osstring(path);
$body
let program_c_str = match crate::platforms::linux::osstr_to_cstring(&$program) {
Err(_why) => {
*crate::platforms::linux::errno_location() = libc::ENOENT;
return -1 },
Ok(res) => res
};
path = program_c_str.as_ptr() as *const libc::c_char;
let hexdigest = crate::common::hash::common_hash_file(&$program);
let env = crate::platforms::linux::parse_env_collection(envp);
let uid = crate::platforms::linux::get_current_uid();
// Permit/deny execution
if crate::common::whitelist::is_whitelisted(&$program, &env, &hexdigest) {
crate::common::event::send_exec_event(uid, &$program, &hexdigest, true);
// Call execve
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next(concat!(stringify!($func_name), "\0"));
});
let func_real: unsafe extern "C" fn(path: *const libc::c_char, argv: *const *const libc::c_char) -> libc::c_int = std::mem::transmute(REAL);
func_real(path, argv)
} else {
crate::common::event::send_exec_event(uid, &$program, &hexdigest, false);
*crate::platforms::linux::errno_location() = libc::EACCES;
return -1
}
}
// =====================================================================
};
(hook $func_name:ident ($program: ident, $envp:ident) $body:block) => {
// =====================================================================
// Generated code for the hook template
#[no_mangle]
#[allow(unused_assignments)]
#[allow(unused_mut)]
pub unsafe extern "C" fn $func_name (mut path: *const libc::c_char, argv: *const *const libc::c_char, $envp: *const *const libc::c_char) -> libc::c_int {
// Common hook code
let mut $program = crate::platforms::linux::c_char_to_osstring(path);
$body
let program_c_str = match crate::platforms::linux::osstr_to_cstring(&$program) {
Err(_why) => {
*crate::platforms::linux::errno_location() = libc::ENOENT;
return -1 },
Ok(res) => res
};
path = program_c_str.as_ptr() as *const libc::c_char;
let hexdigest = crate::common::hash::common_hash_file(&$program);
let env = crate::platforms::linux::parse_env_collection($envp);
let uid = crate::platforms::linux::get_current_uid();
// Permit/deny execution
if crate::common::whitelist::is_whitelisted(&$program, &env, &hexdigest) {
crate::common::event::send_exec_event(uid, &$program, &hexdigest, true);
// Call execve
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: ::std::sync::Once = ::std::sync::Once::new();
ONCE.call_once(|| {
REAL = crate::platforms::linux::dlsym_next(concat!(stringify!($func_name), "\0"));
});
let func_real: unsafe extern "C" fn(path: *const libc::c_char, argv: *const *const libc::c_char, envp: *const *const libc::c_char) -> libc::c_int = std::mem::transmute(REAL);
func_real(path, argv, $envp)
} else {
crate::common::event::send_exec_event(uid, &$program, &hexdigest, false);
*crate::platforms::linux::errno_location() = libc::EACCES;
return -1
}
}
// =====================================================================
}
};
}
*/

// Variadic exec hook template
macro_rules! build_variadic_exec_hook {
Expand Down Expand Up @@ -70,5 +138,5 @@ macro_rules! build_variadic_exec_hook {
}
}
// =====================================================================
}
};
}

0 comments on commit 1369454

Please sign in to comment.