@@ -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,21 @@ 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 or we don't have the permissions to open it, we will fall back to calling
160+ // the system call.
153161 match OpenOptions :: new ( )
154162 . read ( true )
155163 . write ( true )
156164 . open ( UFFD_DEVICE_PATH )
157165 {
158166 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) ) ,
167+ Err ( err) => match err. kind ( ) {
168+ ErrorKind :: NotFound => self . uffd_from_syscall ( flags) ,
169+ ErrorKind :: PermissionDenied if self . syscall_on_perms_error => {
170+ self . uffd_from_syscall ( flags)
171+ }
172+ _ => Err ( Error :: OpenDevUserfaultfd ( err) ) ,
173+ } ,
161174 }
162175 }
163176
0 commit comments