@@ -25,16 +25,24 @@ pub(crate) fn open_impl(
2525 path : & Path ,
2626 options : & OpenOptions ,
2727) -> io:: Result < fs:: File > {
28- let result = open_beneath ( start, path, options) ;
28+ // On regular Linux, attempt to use `openat2` to accelerate sandboxed
29+ // lookups. On Android, the [seccomp policy] prevents us from even
30+ // detecting whether `openat2` is supported, so don't even try.
31+ //
32+ // [seccomp policy]: https://android-developers.googleblog.com/2017/07/seccomp-filter-in-android-o.html
33+ #[ cfg( target_os = "linux" ) ]
34+ {
35+ let result = open_beneath ( start, path, options) ;
2936
30- // If that returned `ENOSYS`, use a fallback strategy.
31- if let Err ( err) = & result {
32- if Some ( rustix:: io:: Errno :: NOSYS . raw_os_error ( ) ) == err. raw_os_error ( ) {
33- return manually:: open ( start, path, options) ;
37+ // If we got anything other than a `ENOSYS` error, that's our result.
38+ match result {
39+ Err ( err) if err. raw_os_error ( ) == Some ( rustix:: io:: Errno :: NOSYS . raw_os_error ( ) ) => { }
40+ Err ( err) => return Err ( err. into ( ) ) ,
41+ Ok ( fd) => return Ok ( fd) ,
3442 }
3543 }
3644
37- result
45+ manually :: open ( start , path , options )
3846}
3947
4048/// Call the `openat2` system call with `RESOLVE_BENEATH`. If the syscall is
@@ -61,23 +69,6 @@ pub(crate) fn open_beneath(
6169 Mode :: empty ( )
6270 } ;
6371
64- // On Android, seccomp kills processes that execute unrecognized system
65- // calls, so we do an explicit version check rather than relying on
66- // getting an `ENOSYS`.
67- #[ cfg( target_os = "android" ) ]
68- {
69- static CHECKED : AtomicBool = AtomicBool :: new ( false ) ;
70-
71- if !CHECKED . load ( Relaxed ) {
72- if !openat2_supported ( ) {
73- INVALID . store ( true , Relaxed ) ;
74- return Err ( rustix:: io:: Errno :: NOSYS . into ( ) ) ;
75- }
76-
77- CHECKED . store ( true , Relaxed ) ;
78- }
79- }
80-
8172 // We know `openat2` needs a `&CStr` internally; to avoid allocating on
8273 // each iteration of the loop below, allocate the `CString` now.
8374 path. into_with_c_str ( |path_c_str| {
@@ -135,54 +126,6 @@ pub(crate) fn open_beneath(
135126 } )
136127}
137128
138- /// Test whether `openat2` is supported on the currently running OS.
139- #[ cfg( target_os = "android" ) ]
140- fn openat2_supported ( ) -> bool {
141- // `openat2` is supported in Linux 5.6 and later. Parse the current
142- // Linux version from the `release` field from `uname` to detect this.
143- let uname = rustix:: process:: uname ( ) ;
144- let release = uname. release ( ) . to_bytes ( ) ;
145- if let Some ( ( major, minor) ) = linux_major_minor ( release) {
146- if major >= 6 || ( major == 5 && minor >= 6 ) {
147- return true ;
148- }
149- }
150-
151- false
152- }
153-
154- /// Extract the major and minor values from a Linux `release` string.
155- #[ cfg( target_os = "android" ) ]
156- fn linux_major_minor ( release : & [ u8 ] ) -> Option < ( u32 , u32 ) > {
157- let mut parts = release. split ( |b| * b == b'.' ) ;
158- if let Some ( major) = parts. next ( ) {
159- if let Ok ( major) = std:: str:: from_utf8 ( major) {
160- if let Ok ( major) = major. parse :: < u32 > ( ) {
161- if let Some ( minor) = parts. next ( ) {
162- if let Ok ( minor) = std:: str:: from_utf8 ( minor) {
163- if let Ok ( minor) = minor. parse :: < u32 > ( ) {
164- return Some ( ( major, minor) ) ;
165- }
166- }
167- }
168- }
169- }
170- }
171-
172- None
173- }
174-
175- #[ cfg( target_os = "android" ) ]
176- #[ test]
177- fn test_linux_major_minor ( ) {
178- assert_eq ! ( linux_major_minor( b"5.11.0-5489-something" ) , Some ( ( 5 , 11 ) ) ) ;
179- assert_eq ! ( linux_major_minor( b"5.10.0-9-whatever" ) , Some ( ( 5 , 10 ) ) ) ;
180- assert_eq ! ( linux_major_minor( b"5.6.0" ) , Some ( ( 5 , 6 ) ) ) ;
181- assert_eq ! ( linux_major_minor( b"2.6.34" ) , Some ( ( 2 , 6 ) ) ) ;
182- assert_eq ! ( linux_major_minor( b"" ) , None ) ;
183- assert_eq ! ( linux_major_minor( b"linux-2.6.32" ) , None ) ;
184- }
185-
186129#[ cfg( racy_asserts) ]
187130fn check_open ( start : & fs:: File , path : & Path , options : & OpenOptions , file : & fs:: File ) {
188131 let check = manually:: open (
0 commit comments