@@ -4,260 +4,11 @@ mod set_identity_header;
4
4
#[ cfg( test) ]
5
5
mod tests;
6
6
7
+ #[ cfg( fuzzing) ]
8
+ pub mod fuzz;
9
+
7
10
fn trace_labels ( ) -> std:: collections:: HashMap < String , String > {
8
11
let mut l = std:: collections:: HashMap :: new ( ) ;
9
12
l. insert ( "direction" . to_string ( ) , "inbound" . to_string ( ) ) ;
10
13
l
11
14
}
12
-
13
- #[ cfg( fuzzing) ]
14
- pub mod fuzz {
15
- use crate :: {
16
- http:: router:: Http ,
17
- policy,
18
- test_util:: { support:: connect:: Connect , * } ,
19
- Config , Inbound ,
20
- } ;
21
- use hyper:: { Body , Request , Response } ;
22
- use libfuzzer_sys:: arbitrary:: Arbitrary ;
23
- use linkerd_app_core:: {
24
- identity, io,
25
- proxy:: http,
26
- svc:: { self , NewService } ,
27
- tls,
28
- transport:: { ClientAddr , OrigDstAddr , Remote , ServerAddr } ,
29
- NameAddr , ProxyRuntime ,
30
- } ;
31
- pub use linkerd_app_test as support;
32
- use linkerd_app_test:: * ;
33
- use std:: { fmt, str, sync:: Arc } ;
34
-
35
- #[ derive( Arbitrary ) ]
36
- pub struct HttpRequestSpec {
37
- pub uri : Vec < u8 > ,
38
- pub header_name : Vec < u8 > ,
39
- pub header_value : Vec < u8 > ,
40
- pub http_method : bool ,
41
- }
42
-
43
- pub async fn fuzz_entry_raw ( requests : Vec < HttpRequestSpec > ) {
44
- let server = hyper:: server:: conn:: http1:: Builder :: new ( ) ;
45
- let mut client = hyper:: client:: conn:: http1:: Builder :: new ( ) ;
46
- let connect =
47
- support:: connect ( ) . endpoint_fn_boxed ( Target :: addr ( ) , hello_fuzz_server ( server) ) ;
48
- let profiles = profile:: resolver ( ) ;
49
- let profile_tx = profiles
50
- . profile_tx ( NameAddr :: from_str_and_port ( "foo.svc.cluster.local" , 5550 ) . unwrap ( ) ) ;
51
- profile_tx. send ( profile:: Profile :: default ( ) ) . unwrap ( ) ;
52
-
53
- // Build the outbound server
54
- let cfg = default_config ( ) ;
55
- let ( rt, _shutdown) = runtime ( ) ;
56
- let server = build_fuzz_server ( cfg, rt, profiles, connect) . new_service ( Target :: HTTP1 ) ;
57
- let ( mut client, bg) = http_util:: connect_and_accept_http1 ( & mut client, server) . await ;
58
-
59
- // Now send all of the requests
60
- for inp in requests. iter ( ) {
61
- if let Ok ( uri) = std:: str:: from_utf8 ( & inp. uri [ ..] ) {
62
- if let Ok ( header_name) = std:: str:: from_utf8 ( & inp. header_name [ ..] ) {
63
- if let Ok ( header_value) = std:: str:: from_utf8 ( & inp. header_value [ ..] ) {
64
- let http_method = if inp. http_method {
65
- hyper:: http:: Method :: GET
66
- } else {
67
- hyper:: http:: Method :: POST
68
- } ;
69
-
70
- if let Ok ( req) = Request :: builder ( )
71
- . method ( http_method)
72
- . uri ( uri)
73
- . header ( header_name, header_value)
74
- . body ( Body :: default ( ) )
75
- {
76
- let rsp = client. send_request ( req) . await ;
77
- tracing:: info!( ?rsp) ;
78
- if let Ok ( rsp) = rsp {
79
- let body = http_util:: body_to_string ( rsp. into_body ( ) ) . await ;
80
- tracing:: info!( ?body) ;
81
- }
82
- }
83
- }
84
- }
85
- }
86
- }
87
-
88
- // It's okay if the background task returns an error, as this would
89
- // indicate that the proxy closed the connection --- which it will do on
90
- // invalid inputs. We want to ensure that the proxy doesn't crash in the
91
- // face of these inputs, and the background task will panic in this
92
- // case.
93
- drop ( client) ;
94
- let res = bg. join_all ( ) . await ;
95
- tracing:: info!( ?res, "background tasks completed" )
96
- }
97
-
98
- fn hello_fuzz_server (
99
- http : hyper:: server:: conn:: http1:: Builder ,
100
- ) -> impl Fn ( Remote < ServerAddr > ) -> io:: Result < io:: BoxedIo > {
101
- move |_endpoint| {
102
- let ( client_io, server_io) = support:: io:: duplex ( 4096 ) ;
103
- let hello_svc = hyper:: service:: service_fn ( |_request : Request < Body > | async move {
104
- Ok :: < _ , io:: Error > ( Response :: new ( Body :: from ( "Hello world!" ) ) )
105
- } ) ;
106
- tokio:: spawn (
107
- http. serve_connection ( server_io, hello_svc)
108
- . in_current_span ( ) ,
109
- ) ;
110
- Ok ( io:: BoxedIo :: new ( client_io) )
111
- }
112
- }
113
-
114
- fn build_fuzz_server < I > (
115
- cfg : Config ,
116
- rt : ProxyRuntime ,
117
- profiles : resolver:: Profiles ,
118
- connect : Connect < Remote < ServerAddr > > ,
119
- ) -> svc:: ArcNewTcp < Target , I >
120
- where
121
- I : io:: AsyncRead + io:: AsyncWrite + io:: PeerAddr + Send + Unpin + ' static ,
122
- {
123
- let connect = svc:: stack ( connect)
124
- . push_map_target ( |t : Http | svc:: Param :: < Remote < ServerAddr > > :: param ( & t) )
125
- . into_inner ( ) ;
126
- Inbound :: new ( cfg, rt)
127
- . with_stack ( connect)
128
- . push_http_router ( profiles)
129
- . push_http_server ( )
130
- . push_http_tcp_server ( )
131
- . into_inner ( )
132
- }
133
-
134
- impl fmt:: Debug for HttpRequestSpec {
135
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
136
- // Custom `Debug` impl that formats the URI, header name, and header
137
- // value as strings if they are UTF-8, or falls back to raw bytes
138
- // otherwise.
139
- let mut dbg = f. debug_struct ( "HttpRequestSpec" ) ;
140
- dbg. field ( "http_method" , & self . http_method ) ;
141
-
142
- if let Ok ( uri) = str:: from_utf8 ( & self . uri [ ..] ) {
143
- dbg. field ( "uri" , & uri) ;
144
- } else {
145
- dbg. field ( "uri" , & self . uri ) ;
146
- }
147
-
148
- if let Ok ( name) = str:: from_utf8 ( & self . header_name [ ..] ) {
149
- dbg. field ( "header_name" , & name) ;
150
- } else {
151
- dbg. field ( "header_name" , & self . header_name ) ;
152
- }
153
-
154
- if let Ok ( value) = str:: from_utf8 ( & self . header_value [ ..] ) {
155
- dbg. field ( "header_value" , & value) ;
156
- } else {
157
- dbg. field ( "header_value" , & self . header_value ) ;
158
- }
159
-
160
- dbg. finish ( )
161
- }
162
- }
163
-
164
- #[ derive( Clone , Debug ) ]
165
- struct Target ( http:: Variant ) ;
166
-
167
- // === impl Target ===
168
-
169
- impl Target {
170
- const HTTP1 : Self = Self ( http:: Variant :: Http1 ) ;
171
-
172
- fn addr ( ) -> SocketAddr {
173
- ( [ 127 , 0 , 0 , 1 ] , 80 ) . into ( )
174
- }
175
- }
176
-
177
- impl svc:: Param < OrigDstAddr > for Target {
178
- fn param ( & self ) -> OrigDstAddr {
179
- OrigDstAddr ( Self :: addr ( ) )
180
- }
181
- }
182
-
183
- impl svc:: Param < Remote < ServerAddr > > for Target {
184
- fn param ( & self ) -> Remote < ServerAddr > {
185
- Remote ( ServerAddr ( Self :: addr ( ) ) )
186
- }
187
- }
188
-
189
- impl svc:: Param < Remote < ClientAddr > > for Target {
190
- fn param ( & self ) -> Remote < ClientAddr > {
191
- Remote ( ClientAddr ( ( [ 192 , 0 , 2 , 3 ] , 50000 ) . into ( ) ) )
192
- }
193
- }
194
-
195
- impl svc:: Param < http:: Variant > for Target {
196
- fn param ( & self ) -> http:: Variant {
197
- self . 0
198
- }
199
- }
200
-
201
- impl svc:: Param < tls:: ConditionalServerTls > for Target {
202
- fn param ( & self ) -> tls:: ConditionalServerTls {
203
- tls:: ConditionalServerTls :: None ( tls:: NoServerTls :: NoClientHello )
204
- }
205
- }
206
-
207
- impl svc:: Param < policy:: AllowPolicy > for Target {
208
- fn param ( & self ) -> policy:: AllowPolicy {
209
- let ( policy, _) = policy:: AllowPolicy :: for_test (
210
- self . param ( ) ,
211
- policy:: ServerPolicy {
212
- protocol : policy:: Protocol :: Http1 ( Arc :: new ( [
213
- linkerd_proxy_server_policy:: http:: default ( Arc :: new ( [
214
- policy:: Authorization {
215
- authentication : policy:: Authentication :: Unauthenticated ,
216
- networks : vec ! [ std:: net:: IpAddr :: from( [ 192 , 0 , 2 , 3 ] ) . into( ) ] ,
217
- meta : Arc :: new ( policy:: Meta :: Resource {
218
- group : "policy.linkerd.io" . into ( ) ,
219
- kind : "server" . into ( ) ,
220
- name : "testsaz" . into ( ) ,
221
- } ) ,
222
- } ,
223
- ] ) ) ,
224
- ] ) ) ,
225
- meta : Arc :: new ( policy:: Meta :: Resource {
226
- group : "policy.linkerd.io" . into ( ) ,
227
- kind : "server" . into ( ) ,
228
- name : "testsrv" . into ( ) ,
229
- } ) ,
230
- local_rate_limit : Arc :: new (
231
- linkerd_proxy_server_policy:: LocalRateLimit :: default ( ) ,
232
- ) ,
233
- } ,
234
- ) ;
235
- policy
236
- }
237
- }
238
-
239
- impl svc:: Param < policy:: ServerLabel > for Target {
240
- fn param ( & self ) -> policy:: ServerLabel {
241
- policy:: ServerLabel (
242
- Arc :: new ( policy:: Meta :: Resource {
243
- group : "policy.linkerd.io" . into ( ) ,
244
- kind : "server" . into ( ) ,
245
- name : "testsrv" . into ( ) ,
246
- } ) ,
247
- 1000 ,
248
- )
249
- }
250
- }
251
-
252
- impl svc:: Param < http:: normalize_uri:: DefaultAuthority > for Target {
253
- fn param ( & self ) -> http:: normalize_uri:: DefaultAuthority {
254
- http:: normalize_uri:: DefaultAuthority ( None )
255
- }
256
- }
257
-
258
- impl svc:: Param < Option < identity:: Id > > for Target {
259
- fn param ( & self ) -> Option < identity:: Id > {
260
- None
261
- }
262
- }
263
- }
0 commit comments