1
1
use std:: io:: { BufRead , BufReader } ;
2
- use std:: path:: PathBuf ;
2
+ use std:: path:: { Path , PathBuf } ;
3
3
use std:: { env, fs} ;
4
+ use std:: ffi:: OsStr ;
4
5
5
6
const INCLUDED_TYPES : & [ & str ] = & [ "file_system_type" , "mode_t" , "umode_t" , "ctl_table" ] ;
6
7
const INCLUDED_FUNCTIONS : & [ & str ] = & [
@@ -111,9 +112,22 @@ fn handle_kernel_symbols_cfg(symvers_path: &PathBuf) {
111
112
}
112
113
}
113
114
115
+ // Alist of plugin basename (without .so) to whether it leaves the ABI unchanged. See
116
+ // https://github.com/fishinabarrel/linux-kernel-module-rust/issues/152#issuecomment-671219181
117
+ const KNOWN_PLUGINS : & [ ( & str , bool ) ] = & [
118
+ ( "cyc_complexity_plugin" , true ) ,
119
+ ( "latent_entropy_plugin" , true ) ,
120
+ ( "sancov_plugin" , true ) ,
121
+ ( "structleak_plugin" , true ) ,
122
+ ( "randomize_layout_plugin" , false ) ,
123
+ ( "stackleak_plugin" , true ) ,
124
+ ( "arm_ssp_per_task_plugin" , true ) ,
125
+ ] ;
126
+
114
127
// Takes the CFLAGS from the kernel Makefile and changes all the include paths to be absolute
115
- // instead of relative.
116
- fn prepare_cflags ( cflags : & str , kernel_dir : & str ) -> Vec < String > {
128
+ // instead of relative. Also, filter out arguments to load or configure plugins and throw an error
129
+ // if the requested plugin would change the ABI.
130
+ fn prepare_cflags ( cflags : & str , kernel_dir : & str ) -> Option < Vec < String > > {
117
131
let cflag_parts = shlex:: split ( & cflags) . unwrap ( ) ;
118
132
let mut cflag_iter = cflag_parts. iter ( ) ;
119
133
let mut kernel_args = vec ! [ ] ;
@@ -128,11 +142,34 @@ fn prepare_cflags(cflags: &str, kernel_dir: &str) -> Vec<String> {
128
142
} else {
129
143
kernel_args. push ( format ! ( "{}/{}" , kernel_dir, include_path) ) ;
130
144
}
145
+ } else if arg. starts_with ( "-fplugin=" ) {
146
+ continue ;
147
+ let plugin_filename = arg. strip_prefix ( "-fplugin=" ) . unwrap ( ) ;
148
+ let plugin_basename = Path :: new ( & plugin_filename) . file_stem ( ) . unwrap ( ) ;
149
+ for ( known_plugin, abi_safe) in KNOWN_PLUGINS {
150
+ if plugin_basename == OsStr :: new ( known_plugin) {
151
+ if !abi_safe {
152
+ eprintln ! ( "Your kernel uses the {:?} plugin, which changes the ABI in a way we can't handle :(" , plugin_basename) ;
153
+ return None ;
154
+ }
155
+ if known_plugin == & "stackleak_plugin" {
156
+ println ! ( "cargo:warning=Rust code will not call stackleak, potentially weakining stackleak's protection." ) ;
157
+ }
158
+ continue ;
159
+ }
160
+ }
161
+ eprintln ! ( "Your kernel uses the {:?} plugin, which we don't know about." , plugin_basename) ;
162
+ eprintln ! ( "Edit linux-kernel-module-rust/build.rs if it doesn't change the ABI." ) ;
163
+ return None ;
164
+ } else if arg. starts_with ( "-fplugin-arg-" ) {
165
+ continue ;
131
166
} else {
132
167
kernel_args. push ( arg. to_string ( ) ) ;
133
168
}
134
169
}
135
- kernel_args
170
+ kernel_args. push ( "-USTRUCTLEAK_PLUGIN" . to_owned ( ) ) ;
171
+ kernel_args. push ( "-DMODULE" . to_owned ( ) ) ;
172
+ Some ( kernel_args)
136
173
}
137
174
138
175
fn main ( ) {
@@ -143,7 +180,8 @@ fn main() {
143
180
let kernel_dir = env:: var ( "abs_srctree" ) . expect ( "Must be invoked from kernel makefile" ) ;
144
181
let kernel_cflags = env:: var ( "c_flags" ) . expect ( "Add 'export c_flags' to Kbuild" ) ;
145
182
146
- let kernel_args = prepare_cflags ( & kernel_cflags, & kernel_dir) ;
183
+ let kernel_args =
184
+ prepare_cflags ( & kernel_cflags, & kernel_dir) . unwrap_or_else ( || std:: process:: exit ( 1 ) ) ;
147
185
148
186
let target = env:: var ( "TARGET" ) . unwrap ( ) ;
149
187
0 commit comments