Skip to content

Commit 36b5335

Browse files
committed
Allow openat to be allowed if specified in extra_allowed_syscalls
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 954be40 commit 36b5335

File tree

2 files changed

+68
-37
lines changed

2 files changed

+68
-37
lines changed

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ mod tests {
462462
#[test]
463463
#[cfg(target_os = "linux")]
464464
fn violate_seccomp_filters_openat() -> Result<()> {
465-
// Hostcall to call `openat`
465+
// Hostcall to call `openat`.
466466
fn make_openat_syscall() -> Result<i64> {
467467
use std::ffi::CString;
468468

@@ -478,43 +478,66 @@ mod tests {
478478
};
479479

480480
if fd_or_err == -1 {
481-
Ok(std::io::Error::last_os_error()
482-
.raw_os_error()
483-
.unwrap()
484-
.into())
481+
Ok((-std::io::Error::last_os_error().raw_os_error().unwrap()).into())
485482
} else {
486483
Ok(fd_or_err)
487484
}
488485
}
486+
{
487+
// First make sure a regular call to `openat` on /proc/sys/vm/overcommit_memory succeeds
488+
let ret = make_openat_syscall()?;
489+
assert!(
490+
ret >= 0,
491+
"Expected openat syscall to succeed, got: {:?}",
492+
ret
493+
);
489494

490-
// First make sure a regular call to `openat` on /proc/sys/vm/overcommit_memory succeeds
491-
let ret = make_openat_syscall()?;
492-
assert!(
493-
ret >= 0,
494-
"Expected openat syscall to succeed, got: {:?}",
495-
ret
496-
);
495+
let mut ubox = UninitializedSandbox::new(
496+
GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")),
497+
None,
498+
)
499+
.unwrap();
500+
ubox.register("Openat_Hostfunc", make_openat_syscall)?;
497501

498-
let mut ubox = UninitializedSandbox::new(
499-
GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")),
500-
None,
501-
)
502-
.unwrap();
503-
ubox.register("Openat_Hostfunc", make_openat_syscall)?;
502+
let mut sbox = ubox.evolve(Noop::default()).unwrap();
503+
let host_func_result = sbox
504+
.call_guest_function_by_name::<i64>(
505+
"CallGivenParamlessHostFuncThatReturnsI64",
506+
"Openat_Hostfunc".to_string(),
507+
)
508+
.expect("Expected to call host function that returns i64");
509+
510+
if cfg!(feature = "seccomp") {
511+
// If seccomp is enabled, we expect the syscall to return EACCES, as setup by our seccomp filter
512+
assert_eq!(host_func_result, -libc::EACCES as i64);
513+
} else {
514+
// If seccomp is not enabled, we expect the syscall to succeed
515+
assert!(host_func_result >= 0);
516+
}
517+
}
504518

505-
let mut sbox = ubox.evolve(Noop::default()).unwrap();
506-
let host_func_result = sbox
507-
.call_guest_function_by_name::<i64>(
508-
"CallGivenParamlessHostFuncThatReturnsI64",
509-
"Openat_Hostfunc".to_string(),
519+
#[cfg(feature = "seccomp")]
520+
{
521+
// Now let's make sure if we register the `openat` syscall as an extra allowed syscall, it will succeed
522+
let mut ubox = UninitializedSandbox::new(
523+
GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")),
524+
None,
510525
)
511-
.expect("Expected to call host function that returns i64");
526+
.unwrap();
527+
ubox.register_with_extra_allowed_syscalls(
528+
"Openat_Hostfunc",
529+
make_openat_syscall,
530+
[libc::SYS_openat],
531+
)?;
532+
let mut sbox = ubox.evolve(Noop::default()).unwrap();
533+
let host_func_result = sbox
534+
.call_guest_function_by_name::<i64>(
535+
"CallGivenParamlessHostFuncThatReturnsI64",
536+
"Openat_Hostfunc".to_string(),
537+
)
538+
.expect("Expected to call host function that returns i64");
512539

513-
if cfg!(feature = "seccomp") {
514-
// If seccomp is enabled, we expect the syscall to return EACCES, as setup by our seccomp filter
515-
assert_eq!(host_func_result, libc::EACCES as i64);
516-
} else {
517-
// If seccomp is not enabled, we expect the syscall to succeed
540+
// should pass regardless of seccomp feature
518541
assert!(host_func_result >= 0);
519542
}
520543

src/hyperlight_host/src/seccomp/guest.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,28 @@ pub(crate) fn get_seccomp_filter_for_host_function_worker_thread(
9393

9494
let arch: TargetArch = std::env::consts::ARCH.try_into()?;
9595

96-
// First: Filter that forces `openat` to return EACCES
97-
let errno_on_openat = SeccompFilter::new(
98-
[(libc::SYS_openat, vec![])].into_iter().collect(),
96+
// Allowlist filter that traps on unknown syscalls
97+
let allowlist = SeccompFilter::new(
98+
allowed_syscalls.into_iter().collect(),
99+
SeccompAction::Trap,
99100
SeccompAction::Allow,
100-
SeccompAction::Errno(libc::EACCES.try_into()?),
101101
arch,
102102
)?
103103
.try_into()?;
104104

105-
// Second: Allowlist filter that traps on unknown syscalls
106-
let allowlist = SeccompFilter::new(
107-
allowed_syscalls.into_iter().collect(),
108-
SeccompAction::Trap,
105+
// If `openat` is an exclicitly allowed syscall, we shouldn't return the filter that forces it to return EACCES.
106+
if let Some(extra_syscalls) = extra_allowed_syscalls {
107+
if extra_syscalls.contains(&libc::SYS_openat) {
108+
return Ok(vec![allowlist]);
109+
}
110+
}
111+
// Otherwise, we return both filters.
112+
113+
// Filter that forces `openat` to return EACCES
114+
let errno_on_openat = SeccompFilter::new(
115+
[(libc::SYS_openat, vec![])].into_iter().collect(),
109116
SeccompAction::Allow,
117+
SeccompAction::Errno(libc::EACCES.try_into()?),
110118
arch,
111119
)?
112120
.try_into()?;

0 commit comments

Comments
 (0)