@@ -58,6 +58,7 @@ pub struct UffdBuilder {
5858 close_on_exec : bool ,
5959 non_blocking : bool ,
6060 user_mode_only : bool ,
61+ syscall_on_perms_error : bool ,
6162 req_features : FeatureFlags ,
6263 req_ioctls : IoctlFlags ,
6364}
@@ -70,6 +71,7 @@ impl UffdBuilder {
7071 close_on_exec : false ,
7172 non_blocking : false ,
7273 user_mode_only : true ,
74+ syscall_on_perms_error : false ,
7375 req_features : FeatureFlags :: empty ( ) ,
7476 req_ioctls : IoctlFlags :: empty ( ) ,
7577 }
@@ -104,6 +106,13 @@ impl UffdBuilder {
104106 self
105107 }
106108
109+ /// Fall back to using the `userfaultfd` system call if opening `/dev/userfaultfd` fails with
110+ /// a permissions error.
111+ pub fn syscall_on_perms_error ( & mut self , syscall_on_perms_error : bool ) -> & mut Self {
112+ self . syscall_on_perms_error = syscall_on_perms_error;
113+ self
114+ }
115+
107116 /// Add a requirement that a particular feature or set of features is available.
108117 ///
109118 /// If a required feature is unavailable, `UffdBuilder.create()` will return an error.
@@ -147,17 +156,23 @@ impl UffdBuilder {
147156 // fall back to calling the system call.
148157 fn open_file_descriptor ( & self , flags : i32 ) -> Result < Uffd > {
149158 // If `/dev/userfaultfd` exists we'll try to get the file descriptor from it. If the file
150- // doesn't exist we will fall back to calling the system call. This means, that if the
151- // device exists but the calling process does not have access rights to it, this will fail,
152- // i.e. we will not fall back to calling the system call.
159+ // doesn't exist we will fall back to calling the system call.
160+ // If the file exists but calling process does not have access rights to it, we have the
161+ // option to fall back to calling the system call instead. This is only done when the
162+ // `syscall_on_perms_error` setting is true. Otherwise, this will just fail.
153163 match OpenOptions :: new ( )
154164 . read ( true )
155165 . write ( true )
156166 . open ( UFFD_DEVICE_PATH )
157167 {
158168 Ok ( mut file) => self . uffd_from_dev ( & mut file, flags) ,
159- Err ( err) if err. kind ( ) == ErrorKind :: NotFound => self . uffd_from_syscall ( flags) ,
160- Err ( err) => Err ( Error :: OpenDevUserfaultfd ( err) ) ,
169+ Err ( err) => match err. kind ( ) {
170+ ErrorKind :: NotFound => self . uffd_from_syscall ( flags) ,
171+ ErrorKind :: PermissionDenied if self . syscall_on_perms_error => {
172+ self . uffd_from_syscall ( flags)
173+ }
174+ _ => Err ( Error :: OpenDevUserfaultfd ( err) ) ,
175+ } ,
161176 }
162177 }
163178
0 commit comments