@@ -25,16 +25,24 @@ pub(crate) fn open_impl(
25
25
path : & Path ,
26
26
options : & OpenOptions ,
27
27
) -> 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) ;
29
36
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) ,
34
42
}
35
43
}
36
44
37
- result
45
+ manually :: open ( start , path , options )
38
46
}
39
47
40
48
/// Call the `openat2` system call with `RESOLVE_BENEATH`. If the syscall is
@@ -61,23 +69,6 @@ pub(crate) fn open_beneath(
61
69
Mode :: empty ( )
62
70
} ;
63
71
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
-
81
72
// We know `openat2` needs a `&CStr` internally; to avoid allocating on
82
73
// each iteration of the loop below, allocate the `CString` now.
83
74
path. into_with_c_str ( |path_c_str| {
@@ -135,54 +126,6 @@ pub(crate) fn open_beneath(
135
126
} )
136
127
}
137
128
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
-
186
129
#[ cfg( racy_asserts) ]
187
130
fn check_open ( start : & fs:: File , path : & Path , options : & OpenOptions , file : & fs:: File ) {
188
131
let check = manually:: open (
0 commit comments