@@ -87,26 +87,26 @@ fn alloc_notify_allocs() -> NotifyAllocs {
87
87
}
88
88
}
89
89
90
- /// Returns 'false ' if the ioctl failed with E_NOENT, 'true ' if it succeeded.
90
+ /// Returns 'None ' if the ioctl failed with E_NOENT, 'Some(()) ' if it succeeded.
91
91
/// This aborts the program in any other situation.
92
92
///
93
93
/// # Safety
94
94
///
95
95
/// `ioctl(fd, request, ptr)` must be safe to call
96
- unsafe fn ioctl < T > ( fd : RawFd , request : libc:: c_ulong , ptr : * mut T ) -> bool {
96
+ unsafe fn ioctl < T > ( fd : RawFd , request : libc:: c_ulong , ptr : * mut T ) -> Option < ( ) > {
97
97
// SAFETY: By function contract
98
98
if unsafe { libc:: ioctl ( fd, request, ptr) } == -1 {
99
99
// SAFETY: Trivial
100
100
if unsafe { * __errno_location ( ) } == ENOENT {
101
- false
101
+ None
102
102
} else {
103
103
// SAFETY: Not actually unsafe
104
104
unsafe {
105
105
libc:: abort ( ) ;
106
106
}
107
107
}
108
108
} else {
109
- true
109
+ Some ( ( ) )
110
110
}
111
111
}
112
112
@@ -120,37 +120,42 @@ unsafe fn handle_notifications(notify_fd: OwnedFd) -> ! {
120
120
resp,
121
121
} = alloc_notify_allocs ( ) ;
122
122
123
- // The first notification must be allowed to pass unhindered.
124
- let mut error = 0 ;
125
- let mut flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE as _ ;
126
-
127
- loop {
123
+ // SAFETY: See individual SAFETY comments
124
+ let handle_syscall = |create_response : fn ( & mut _) | unsafe {
128
125
// SECCOMP_IOCTL_NOTIF_RECV expects the target struct to be zeroed
129
126
// SAFETY: req is at least req_size bytes big.
130
- unsafe { std:: ptr:: write_bytes ( req. cast :: < u8 > ( ) , 0 , req_size) } ;
127
+ std:: ptr:: write_bytes ( req. cast :: < u8 > ( ) , 0 , req_size) ;
131
128
132
129
// SAFETY: A valid pointer to a seccomp_notify is passed in; notify_fd is valid.
133
- if unsafe { !ioctl ( notify_fd. as_raw_fd ( ) , SECCOMP_IOCTL_NOTIF_RECV , req) } {
134
- continue ;
135
- }
130
+ ioctl ( notify_fd. as_raw_fd ( ) , SECCOMP_IOCTL_NOTIF_RECV , req) ?;
136
131
137
132
// Allow the first execve call as this is sudo itself starting the target executable.
138
133
// SAFETY: resp is a valid pointer to a seccomp_notify_resp.
139
- unsafe {
140
- ( * resp) . id = ( * req) . id ;
141
- ( * resp) . val = 0 ;
142
- ( * resp) . error = error;
143
- ( * resp) . flags = flags;
144
- }
134
+ ( * resp) . id = ( * req) . id ;
135
+ create_response ( & mut * resp) ;
145
136
146
137
// SAFETY: A valid pointer to a seccomp_notify_resp is passed in; notify_fd is valid.
147
- if unsafe { !ioctl ( notify_fd. as_raw_fd ( ) , SECCOMP_IOCTL_NOTIF_SEND , resp) } {
148
- continue ;
138
+ ioctl ( notify_fd. as_raw_fd ( ) , SECCOMP_IOCTL_NOTIF_SEND , resp)
139
+ } ;
140
+
141
+ loop {
142
+ if handle_syscall ( |resp| {
143
+ resp. val = 0 ;
144
+ resp. error = 0 ;
145
+ resp. flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE as _
146
+ } )
147
+ . is_some ( )
148
+ {
149
+ break ;
149
150
}
151
+ }
150
152
151
- // As soon as we have reached this point, all notifications will be acted upon.
152
- error = -EACCES ;
153
- flags = 0 ;
153
+ loop {
154
+ handle_syscall ( |resp| {
155
+ resp. val = 0 ;
156
+ resp. error = -EACCES ;
157
+ resp. flags = 0 ;
158
+ } ) ;
154
159
}
155
160
}
156
161
0 commit comments