From fec6a8ae09b5e852f7672b5b8cb44cec3a714320 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Fri, 19 Jul 2024 15:44:13 +1000 Subject: [PATCH] resolvers: kernel: do not fall back to userspace resolver If the resolution failed 16 times, the program is probably being attacked and so while the userspace emulated lookup logic should be safe it seems like a better idea to tell userspace about it. Signed-off-by: Aleksa Sarai --- src/resolvers/kernel.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/resolvers/kernel.rs b/src/resolvers/kernel.rs index 3ce35593..4a86234a 100644 --- a/src/resolvers/kernel.rs +++ b/src/resolvers/kernel.rs @@ -17,8 +17,8 @@ */ use crate::{ - error::{self, Error, ErrorExt}, - resolvers::{self, ResolverFlags}, + error::{self, Error}, + resolvers::ResolverFlags, syscalls, Handle, }; @@ -52,17 +52,15 @@ pub(crate) fn resolve>( // openat2(2) can fail with -EAGAIN if there was a racing rename or mount // *anywhere on the system*. This can happen pretty frequently, so what we - // do is attempt the openat2(2) a couple of times, and then fall-back to - // userspace emulation. - let mut handle: Option = None; + // do is attempt the openat2(2) a couple of times. If it still fails, just + // error out. for _ in 0..16 { match syscalls::openat2(root.as_raw_fd(), path.as_ref(), &how) { - Ok(file) => { - handle = Some(file); - break; - } + Ok(file) => return Ok(Handle::from_file_unchecked(file)), Err(err) => match err.root_cause().raw_os_error() { - Some(libc::ENOSYS) => break, // shouldn't happen + Some(libc::ENOSYS) => { + return error::NotSupportedSnafu { feature: "openat2" }.fail() + } // shouldn't happen Some(libc::EAGAIN) => continue, // TODO: Add wrapper for known-bad openat2 return codes. //Some(libc::EXDEV) | Some(libc::ELOOP) => { ... } @@ -75,11 +73,8 @@ pub(crate) fn resolve>( } } - handle.map_or_else( - || { - resolvers::user::resolve(root, path, flags) - .wrap("fallback user-space resolution for RESOLVE_IN_ROOT") - }, - |file| Ok(Handle::from_file_unchecked(file)), - ) + return error::SafetyViolationSnafu { + description: "racing filesystem changes caused openat2 to abort", + } + .fail(); }