@@ -7,7 +7,7 @@ extern crate sys_util;
7
7
use std:: io;
8
8
use std:: result:: Result ;
9
9
10
- use libc:: { _exit, c_int, c_void, siginfo_t, SIGSYS } ;
10
+ use libc:: { _exit, c_int, c_void, siginfo_t, SIGBUS , SIGSEGV , SIGSYS } ;
11
11
12
12
use logger:: { Metric , LOGGER , METRICS } ;
13
13
use sys_util:: register_signal_handler;
@@ -53,12 +53,45 @@ extern "C" fn sigsys_handler(num: c_int, info: *mut siginfo_t, _unused: *mut c_v
53
53
} ;
54
54
}
55
55
56
+ extern "C" fn sigbus_sigsegv_handler ( num : c_int , info : * mut siginfo_t , _unused : * mut c_void ) {
57
+ // Safe because we're just reading some fields from a supposedly valid argument.
58
+ let si_signo = unsafe { ( * info) . si_signo } ;
59
+
60
+ // Sanity check. The condition should never be true.
61
+ if num != si_signo || ( num != SIGBUS && num != SIGSEGV ) {
62
+ // Safe because we're terminating the process anyway.
63
+ unsafe { _exit ( i32:: from ( super :: FC_EXIT_CODE_UNEXPECTED_ERROR ) ) } ;
64
+ }
65
+
66
+ // Other signals which might do async unsafe things incompatible with the rest of this
67
+ // function are blocked due to the sa_mask used when registering the signal handler.
68
+ error ! ( "Shutting down VM after intercepting signal {}." , si_signo) ;
69
+ // Log the metrics before exiting.
70
+ if let Err ( e) = LOGGER . log_metrics ( ) {
71
+ error ! ( "Failed to log metrics while stopping: {}" , e) ;
72
+ }
73
+
74
+ // Safe because we're terminating the process anyway. We don't actually do anything when
75
+ // running unit tests.
76
+ #[ cfg( not( test) ) ]
77
+ unsafe {
78
+ _exit ( i32:: from ( match si_signo {
79
+ SIGBUS => super :: FC_EXIT_CODE_SIGBUS ,
80
+ SIGSEGV => super :: FC_EXIT_CODE_SIGSEGV ,
81
+ _ => super :: FC_EXIT_CODE_UNEXPECTED_ERROR ,
82
+ } ) )
83
+ } ;
84
+ }
85
+
56
86
/// Registers all the required signal handlers.
57
87
///
58
- /// Custom handlers are installed for: `SIGSYS`.
88
+ /// Custom handlers are installed for: `SIGBUS`, `SIGSEGV`, ` SIGSYS`.
59
89
///
60
90
pub fn register_signal_handlers ( ) -> Result < ( ) , io:: Error > {
61
- register_signal_handler ( SIGSYS , sigsys_handler)
91
+ register_signal_handler ( SIGSYS , sigsys_handler) ?;
92
+ register_signal_handler ( SIGBUS , sigbus_sigsegv_handler) ?;
93
+ register_signal_handler ( SIGSEGV , sigbus_sigsegv_handler) ?;
94
+ Ok ( ( ) )
62
95
}
63
96
64
97
#[ cfg( test) ]
@@ -137,5 +170,10 @@ mod tests {
137
170
// The signal handler should let the program continue during unit tests.
138
171
assert_eq ! ( METRICS . seccomp. num_faults. count( ) , 1 ) ;
139
172
}
173
+
174
+ // Assert that the SIGSEGV handler left the process alive.
175
+ let foo = 0 as * const i32 ;
176
+ let _bar = unsafe { * foo } ;
177
+ assert ! ( true ) ;
140
178
}
141
179
}
0 commit comments