Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * api_fuzz_test.c - Binary API fuzz hook
4 : *
5 : * Copyright (c) 2020 Cisco and/or its affiliates.
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at:
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *------------------------------------------------------------------
18 : */
19 : #include <vppinfra/format.h>
20 : #include <vppinfra/byte_order.h>
21 : #include <vppinfra/error.h>
22 : #include <vlib/vlib.h>
23 : #include <vlib/unix/unix.h>
24 : #include <vlibapi/api.h>
25 :
26 : static u32 fuzz_seed = 0xdeaddabe;
27 : static u16 fuzz_first;
28 : static u16 fuzz_cli_first, fuzz_cli_last;
29 :
30 : extern void (*vl_mem_api_fuzz_hook) (u16, void *);
31 :
32 : static void
33 0 : fuzz_hook (u16 id, void *the_msg)
34 : {
35 : /*
36 : * Fuzz (aka screw up) this message? Leave connection establishment
37 : * messages alone as well as CLI messages.
38 : */
39 0 : if ((id > fuzz_first) && !(id >= fuzz_cli_first && id < fuzz_cli_last))
40 : {
41 : msgbuf_t *mb;
42 : u8 *limit, *start;
43 :
44 0 : mb = (msgbuf_t *) (((u8 *) the_msg) - offsetof (msgbuf_t, data));
45 :
46 0 : limit = (u8 *) (mb->data + ntohl (mb->data_len));
47 :
48 : /*
49 : * Leave the first 14 octets alone, aka msg_id, client_index,
50 : * context, sw_if_index
51 : */
52 :
53 0 : start = ((u8 *) the_msg) + 14;
54 :
55 0 : for (; start < limit; start++)
56 0 : *start ^= (random_u32 (&fuzz_seed) & 0xFF);
57 : }
58 0 : }
59 :
60 : static void
61 0 : default_fuzz_config (void)
62 : {
63 0 : fuzz_first = vl_msg_api_get_msg_index
64 : ((u8 *) "memclnt_keepalive_reply_e8d4e804");
65 0 : fuzz_cli_first = vl_msg_api_get_msg_index ((u8 *) "cli_23bfbfff");
66 0 : fuzz_cli_last = vl_msg_api_get_msg_index
67 : ((u8 *) "cli_inband_reply_05879051");
68 0 : }
69 :
70 : static clib_error_t *
71 0 : test_api_fuzz_command_fn (vlib_main_t * vm,
72 : unformat_input_t * input, vlib_cli_command_t * cmd)
73 : {
74 : u32 tmp;
75 :
76 0 : default_fuzz_config ();
77 :
78 0 : if (fuzz_first == 0xFFFF)
79 : {
80 0 : vlib_cli_output (vm, "Couldn't find 'memclnt_keepalive_reply' ID");
81 0 : vlib_cli_output
82 : (vm, "Manual setting required, use 'show api message table'");
83 : }
84 :
85 0 : if (fuzz_cli_first == 0xFFFF)
86 : {
87 0 : vlib_cli_output (vm, "Couldn't find 'cli' ID");
88 0 : vlib_cli_output
89 : (vm, "Manual setting required, use 'show api message table'");
90 : }
91 :
92 0 : if (fuzz_cli_last == 0xFFFF)
93 : {
94 0 : vlib_cli_output (vm, "Couldn't find 'cli_inband_reply' ID");
95 0 : vlib_cli_output
96 : (vm, "Manual setting required, use 'show api message table'");
97 : }
98 :
99 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
100 : {
101 0 : if (unformat (input, "seed %d", &fuzz_seed))
102 : ;
103 0 : else if (unformat (input, "disable") | unformat (input, "off"))
104 0 : fuzz_first = ~0;
105 0 : else if (unformat (input, "fuzz-first %d", &tmp))
106 0 : fuzz_first = (u16) tmp;
107 0 : else if (unformat (input, "fuzz-cli-first %d", &tmp))
108 0 : fuzz_cli_first = (u16) tmp;
109 0 : else if (unformat (input, "fuzz-cli-last %d", &tmp))
110 0 : fuzz_cli_last = (u16) tmp;
111 : else
112 0 : break;
113 : }
114 :
115 0 : if (fuzz_first == 0xFFFF)
116 : {
117 0 : vl_mem_api_fuzz_hook = 0;
118 0 : return clib_error_return (0, "fuzz_first is ~0, fuzzing disabled");
119 : }
120 0 : vl_mem_api_fuzz_hook = fuzz_hook;
121 :
122 0 : vlib_cli_output (vm, "Fuzzing enabled: first %d, skip cli range %d - %d",
123 : (u32) fuzz_first, (u32) fuzz_cli_first,
124 : (u32) fuzz_cli_last);
125 :
126 0 : return 0;
127 : }
128 :
129 : /* *INDENT-OFF* */
130 16239 : VLIB_CLI_COMMAND (test_api_fuzz, static) = {
131 : .path = "test api fuzz",
132 : .short_help = "test api fuzz [disable][seed nnn]\n"
133 : " [fuzz-first nn][fuzz-cli-first nn][fuzz-cli-last nn]",
134 : .function = test_api_fuzz_command_fn,
135 : };
136 : /* *INDENT-ON* */
137 :
138 : static u8 main_loop_enter_enable_api_fuzz;
139 :
140 : static clib_error_t *
141 559 : api_fuzz_config (vlib_main_t * vm, unformat_input_t * input)
142 : {
143 1118 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
144 : {
145 559 : if (unformat (input, "off")
146 0 : || unformat (input, "disable") || unformat (input, "no"))
147 : ; /* ok, no action */
148 0 : else if (unformat (input, "on")
149 0 : || unformat (input, "enable") || unformat (input, "yes"))
150 0 : main_loop_enter_enable_api_fuzz = 1;
151 : else
152 0 : return clib_error_return (0, "unknown input '%U'",
153 : format_unformat_error, input);
154 : }
155 559 : return 0;
156 : }
157 :
158 1119 : VLIB_CONFIG_FUNCTION (api_fuzz_config, "api-fuzz");
159 :
160 : static clib_error_t *
161 559 : api_fuzz_api_init (vlib_main_t * vm)
162 : {
163 : /* Are we supposed to fuzz API messages? */
164 559 : if (main_loop_enter_enable_api_fuzz == 0)
165 559 : return 0;
166 :
167 0 : default_fuzz_config ();
168 :
169 0 : if (fuzz_first == 0xFFFF)
170 : {
171 0 : return clib_error_return
172 : (0, "Couldn't find 'memclnt_keepalive_reply' ID");
173 : }
174 : /* Turn on fuzzing */
175 0 : vl_mem_api_fuzz_hook = fuzz_hook;
176 0 : return 0;
177 : }
178 :
179 1119 : VLIB_API_INIT_FUNCTION (api_fuzz_api_init);
180 :
181 : /*
182 : * fd.io coding-style-patch-verification: ON
183 : *
184 : * Local Variables:
185 : * eval: (c-set-style "gnu")
186 : * End:
187 : */
|