|
| 1 | +From 837c1f9389fc64938a6081517c34a749a11692b0 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Kanishk-Bansal <kbkanishk975@gmail.com> |
| 3 | +Date: Tue, 31 Dec 2024 09:23:23 +0000 |
| 4 | +Subject: [PATCH] Fix CVE-2024-53580 |
| 5 | + |
| 6 | +--- |
| 7 | + src/iperf_api.c | 98 +++++++++++++++++++++++------------------------ |
| 8 | + src/iperf_error.c | 6 +-- |
| 9 | + src/iperf_util.c | 36 +++++++++++++++++ |
| 10 | + src/iperf_util.h | 1 + |
| 11 | + 4 files changed, 89 insertions(+), 52 deletions(-) |
| 12 | + |
| 13 | +diff --git a/src/iperf_api.c b/src/iperf_api.c |
| 14 | +index 7fb741e..bb3be92 100644 |
| 15 | +--- a/src/iperf_api.c |
| 16 | ++++ b/src/iperf_api.c |
| 17 | +@@ -2308,72 +2308,72 @@ get_parameters(struct iperf_test *test) |
| 18 | + cJSON_free(str); |
| 19 | + } |
| 20 | + |
| 21 | +- if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL) |
| 22 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "tcp", cJSON_True)) != NULL) |
| 23 | + set_protocol(test, Ptcp); |
| 24 | +- if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL) |
| 25 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "udp", cJSON_True)) != NULL) |
| 26 | + set_protocol(test, Pudp); |
| 27 | +- if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL) |
| 28 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "sctp", cJSON_True)) != NULL) |
| 29 | + set_protocol(test, Psctp); |
| 30 | +- if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL) |
| 31 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "omit", cJSON_Number)) != NULL) |
| 32 | + test->omit = j_p->valueint; |
| 33 | +- if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL) |
| 34 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "server_affinity", cJSON_Number)) != NULL) |
| 35 | + test->server_affinity = j_p->valueint; |
| 36 | +- if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL) |
| 37 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "time", cJSON_Number)) != NULL) |
| 38 | + test->duration = j_p->valueint; |
| 39 | + test->settings->bytes = 0; |
| 40 | +- if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL) |
| 41 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "num", cJSON_Number)) != NULL) |
| 42 | + test->settings->bytes = j_p->valueint; |
| 43 | + test->settings->blocks = 0; |
| 44 | +- if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL) |
| 45 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "blockcount", cJSON_Number)) != NULL) |
| 46 | + test->settings->blocks = j_p->valueint; |
| 47 | +- if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL) |
| 48 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "MSS", cJSON_Number)) != NULL) |
| 49 | + test->settings->mss = j_p->valueint; |
| 50 | +- if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL) |
| 51 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "nodelay", cJSON_True)) != NULL) |
| 52 | + test->no_delay = 1; |
| 53 | +- if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL) |
| 54 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "parallel", cJSON_Number)) != NULL) |
| 55 | + test->num_streams = j_p->valueint; |
| 56 | +- if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL) |
| 57 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "reverse", cJSON_True)) != NULL) |
| 58 | + iperf_set_test_reverse(test, 1); |
| 59 | +- if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL) |
| 60 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "bidirectional", cJSON_True)) != NULL) |
| 61 | + iperf_set_test_bidirectional(test, 1); |
| 62 | +- if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL) |
| 63 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "window", cJSON_Number)) != NULL) |
| 64 | + test->settings->socket_bufsize = j_p->valueint; |
| 65 | +- if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL) |
| 66 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "len", cJSON_Number)) != NULL) |
| 67 | + test->settings->blksize = j_p->valueint; |
| 68 | +- if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL) |
| 69 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "bandwidth", cJSON_Number)) != NULL) |
| 70 | + test->settings->rate = j_p->valueint; |
| 71 | +- if ((j_p = cJSON_GetObjectItem(j, "fqrate")) != NULL) |
| 72 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "fqrate", cJSON_Number)) != NULL) |
| 73 | + test->settings->fqrate = j_p->valueint; |
| 74 | +- if ((j_p = cJSON_GetObjectItem(j, "pacing_timer")) != NULL) |
| 75 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "pacing_timer", cJSON_Number)) != NULL) |
| 76 | + test->settings->pacing_timer = j_p->valueint; |
| 77 | +- if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL) |
| 78 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "burst", cJSON_Number)) != NULL) |
| 79 | + test->settings->burst = j_p->valueint; |
| 80 | +- if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) |
| 81 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "TOS", cJSON_Number)) != NULL) |
| 82 | + test->settings->tos = j_p->valueint; |
| 83 | +- if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL) |
| 84 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "flowlabel", cJSON_Number)) != NULL) |
| 85 | + test->settings->flowlabel = j_p->valueint; |
| 86 | +- if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL) |
| 87 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "title", cJSON_String)) != NULL) |
| 88 | + test->title = strdup(j_p->valuestring); |
| 89 | +- if ((j_p = cJSON_GetObjectItem(j, "extra_data")) != NULL) |
| 90 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "extra_data", cJSON_String)) != NULL) |
| 91 | + test->extra_data = strdup(j_p->valuestring); |
| 92 | +- if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL) |
| 93 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "congestion", cJSON_String)) != NULL) |
| 94 | + test->congestion = strdup(j_p->valuestring); |
| 95 | +- if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL) |
| 96 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "congestion_used", cJSON_String)) != NULL) |
| 97 | + test->congestion_used = strdup(j_p->valuestring); |
| 98 | +- if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL) |
| 99 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "get_server_output", cJSON_Number)) != NULL) |
| 100 | + iperf_set_test_get_server_output(test, 1); |
| 101 | +- if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL) |
| 102 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "udp_counters_64bit", cJSON_Number)) != NULL) |
| 103 | + iperf_set_test_udp_counters_64bit(test, 1); |
| 104 | +- if ((j_p = cJSON_GetObjectItem(j, "repeating_payload")) != NULL) |
| 105 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "repeating_payload", cJSON_Number)) != NULL) |
| 106 | + test->repeating_payload = 1; |
| 107 | +- if ((j_p = cJSON_GetObjectItem(j, "zerocopy")) != NULL) |
| 108 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "zerocopy", cJSON_Number)) != NULL) |
| 109 | + test->zerocopy = j_p->valueint; |
| 110 | + #if defined(HAVE_DONT_FRAGMENT) |
| 111 | +- if ((j_p = cJSON_GetObjectItem(j, "dont_fragment")) != NULL) |
| 112 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "dont_fragment", cJSON_Number)) != NULL) |
| 113 | + test->settings->dont_fragment = j_p->valueint; |
| 114 | + #endif /* HAVE_DONT_FRAGMENT */ |
| 115 | + #if defined(HAVE_SSL) |
| 116 | +- if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL) |
| 117 | ++ if ((j_p = iperf_cJSON_GetObjectItemType(j, "authtoken", cJSON_String)) != NULL) |
| 118 | + test->settings->authtoken = strdup(j_p->valuestring); |
| 119 | + #endif //HAVE_SSL |
| 120 | + if (test->mode && test->protocol->id == Ptcp && has_tcpinfo_retransmits()) |
| 121 | +@@ -2532,10 +2532,10 @@ get_results(struct iperf_test *test) |
| 122 | + i_errno = IERECVRESULTS; |
| 123 | + r = -1; |
| 124 | + } else { |
| 125 | +- j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total"); |
| 126 | +- j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user"); |
| 127 | +- j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system"); |
| 128 | +- j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits"); |
| 129 | ++ j_cpu_util_total = iperf_cJSON_GetObjectItemType(j, "cpu_util_total", cJSON_Number); |
| 130 | ++ j_cpu_util_user = iperf_cJSON_GetObjectItemType(j, "cpu_util_user", cJSON_Number); |
| 131 | ++ j_cpu_util_system = iperf_cJSON_GetObjectItemType(j, "cpu_util_system", cJSON_Number); |
| 132 | ++ j_sender_has_retransmits = iperf_cJSON_GetObjectItemType(j, "sender_has_retransmits", cJSON_Number); |
| 133 | + if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) { |
| 134 | + i_errno = IERECVRESULTS; |
| 135 | + r = -1; |
| 136 | +@@ -2557,7 +2557,7 @@ get_results(struct iperf_test *test) |
| 137 | + else if ( test->mode == BIDIRECTIONAL ) |
| 138 | + test->other_side_has_retransmits = result_has_retransmits; |
| 139 | + |
| 140 | +- j_streams = cJSON_GetObjectItem(j, "streams"); |
| 141 | ++ j_streams = iperf_cJSON_GetObjectItemType(j, "streams", cJSON_Array); |
| 142 | + if (j_streams == NULL) { |
| 143 | + i_errno = IERECVRESULTS; |
| 144 | + r = -1; |
| 145 | +@@ -2569,16 +2569,16 @@ get_results(struct iperf_test *test) |
| 146 | + i_errno = IERECVRESULTS; |
| 147 | + r = -1; |
| 148 | + } else { |
| 149 | +- j_id = cJSON_GetObjectItem(j_stream, "id"); |
| 150 | +- j_bytes = cJSON_GetObjectItem(j_stream, "bytes"); |
| 151 | +- j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits"); |
| 152 | +- j_jitter = cJSON_GetObjectItem(j_stream, "jitter"); |
| 153 | +- j_errors = cJSON_GetObjectItem(j_stream, "errors"); |
| 154 | +- j_omitted_errors = cJSON_GetObjectItem(j_stream, "omitted_errors"); |
| 155 | +- j_packets = cJSON_GetObjectItem(j_stream, "packets"); |
| 156 | +- j_omitted_packets = cJSON_GetObjectItem(j_stream, "omitted_packets"); |
| 157 | +- j_start_time = cJSON_GetObjectItem(j_stream, "start_time"); |
| 158 | +- j_end_time = cJSON_GetObjectItem(j_stream, "end_time"); |
| 159 | ++ j_id = iperf_cJSON_GetObjectItemType(j_stream, "id", cJSON_Number); |
| 160 | ++ j_bytes = iperf_cJSON_GetObjectItemType(j_stream, "bytes", cJSON_Number); |
| 161 | ++ j_retransmits = iperf_cJSON_GetObjectItemType(j_stream, "retransmits", cJSON_Number); |
| 162 | ++ j_jitter = iperf_cJSON_GetObjectItemType(j_stream, "jitter", cJSON_Number); |
| 163 | ++ j_errors = iperf_cJSON_GetObjectItemType(j_stream, "errors", cJSON_Number); |
| 164 | ++ j_omitted_errors = iperf_cJSON_GetObjectItemType(j_stream, "omitted_errors", cJSON_Number); |
| 165 | ++ j_packets = iperf_cJSON_GetObjectItemType(j_stream, "packets", cJSON_Number); |
| 166 | ++ j_omitted_packets = iperf_cJSON_GetObjectItemType(j_stream, "omitted_packets", cJSON_Number); |
| 167 | ++ j_start_time = iperf_cJSON_GetObjectItemType(j_stream, "start_time", cJSON_Number); |
| 168 | ++ j_end_time = iperf_cJSON_GetObjectItemType(j_stream, "end_time", cJSON_Number); |
| 169 | + if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) { |
| 170 | + i_errno = IERECVRESULTS; |
| 171 | + r = -1; |
| 172 | +@@ -2667,7 +2667,7 @@ get_results(struct iperf_test *test) |
| 173 | + } |
| 174 | + else { |
| 175 | + /* No JSON, look for textual output. Make a copy of the text for later. */ |
| 176 | +- j_server_output = cJSON_GetObjectItem(j, "server_output_text"); |
| 177 | ++ j_server_output = iperf_cJSON_GetObjectItemType(j, "server_output_text", cJSON_String); |
| 178 | + if (j_server_output != NULL) { |
| 179 | + test->server_output_text = strdup(j_server_output->valuestring); |
| 180 | + } |
| 181 | +@@ -2676,7 +2676,7 @@ get_results(struct iperf_test *test) |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | +- j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used"); |
| 186 | ++ j_remote_congestion_used = iperf_cJSON_GetObjectItemType(j, "congestion_used", cJSON_String); |
| 187 | + if (j_remote_congestion_used != NULL) { |
| 188 | + test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring); |
| 189 | + } |
| 190 | +@@ -4878,7 +4878,7 @@ iperf_json_finish(struct iperf_test *test) |
| 191 | + |
| 192 | + /* --json-stream, so we print various individual objects */ |
| 193 | + if (test->json_stream) { |
| 194 | +- cJSON *error = cJSON_GetObjectItem(test->json_top, "error"); |
| 195 | ++ cJSON *error = iperf_cJSON_GetObjectItemType(test->json_top, "error", cJSON_String); |
| 196 | + if (error) { |
| 197 | + JSONStream_Output(test, "error", error); |
| 198 | + } |
| 199 | +diff --git a/src/iperf_error.c b/src/iperf_error.c |
| 200 | +index 0fedf31..3cb9b45 100644 |
| 201 | +--- a/src/iperf_error.c |
| 202 | ++++ b/src/iperf_error.c |
| 203 | +@@ -60,11 +60,11 @@ iperf_err(struct iperf_test *test, const char *format, ...) |
| 204 | + if (test != NULL && test->json_output && test->json_top != NULL) |
| 205 | + cJSON_AddStringToObject(test->json_top, "error", str); |
| 206 | + else { |
| 207 | +- if (pthread_mutex_lock(&(test->print_mutex)) != 0) { |
| 208 | ++ if (test != NULL && pthread_mutex_lock(&(test->print_mutex)) != 0) { |
| 209 | + perror("iperf_err: pthread_mutex_lock"); |
| 210 | + } |
| 211 | + |
| 212 | +- if (test && test->outfile && test->outfile != stdout) { |
| 213 | ++ if (test != NULL && test->outfile != NULL && test->outfile != stdout) { |
| 214 | + if (ct) { |
| 215 | + fprintf(test->outfile, "%s", ct); |
| 216 | + } |
| 217 | +@@ -77,7 +77,7 @@ iperf_err(struct iperf_test *test, const char *format, ...) |
| 218 | + fprintf(stderr, "iperf3: %s\n", str); |
| 219 | + } |
| 220 | + |
| 221 | +- if (pthread_mutex_unlock(&(test->print_mutex)) != 0) { |
| 222 | ++ if (test != NULL && pthread_mutex_unlock(&(test->print_mutex)) != 0) { |
| 223 | + perror("iperf_err: pthread_mutex_unlock"); |
| 224 | + } |
| 225 | + |
| 226 | +diff --git a/src/iperf_util.c b/src/iperf_util.c |
| 227 | +index 81e8da1..a8a32e1 100644 |
| 228 | +--- a/src/iperf_util.c |
| 229 | ++++ b/src/iperf_util.c |
| 230 | +@@ -430,6 +430,42 @@ iperf_json_printf(const char *format, ...) |
| 231 | + return o; |
| 232 | + } |
| 233 | + |
| 234 | ++/********************** cJSON GetObjectItem w/ Type Helper ********************/ |
| 235 | ++cJSON * iperf_cJSON_GetObjectItemType(cJSON * j, char * item_string, int expected_type){ |
| 236 | ++ cJSON *j_p; |
| 237 | ++ if((j_p = cJSON_GetObjectItem(j, item_string)) != NULL) |
| 238 | ++ switch(expected_type){ |
| 239 | ++ case cJSON_True: |
| 240 | ++ if(cJSON_IsBool(j_p)) |
| 241 | ++ return j_p; |
| 242 | ++ else |
| 243 | ++ iperf_err(NULL, "iperf_cJSON_GetObjectItemType mismatch %s", item_string); |
| 244 | ++ break; |
| 245 | ++ case cJSON_String: |
| 246 | ++ if(cJSON_IsString(j_p)) |
| 247 | ++ return j_p; |
| 248 | ++ else |
| 249 | ++ iperf_err(NULL, "iperf_cJSON_GetObjectItemType mismatch %s", item_string); |
| 250 | ++ break; |
| 251 | ++ case cJSON_Number: |
| 252 | ++ if(cJSON_IsNumber(j_p)) |
| 253 | ++ return j_p; |
| 254 | ++ else |
| 255 | ++ iperf_err(NULL, "iperf_cJSON_GetObjectItemType mismatch %s", item_string); |
| 256 | ++ break; |
| 257 | ++ case cJSON_Array: |
| 258 | ++ if(cJSON_IsArray(j_p)) |
| 259 | ++ return j_p; |
| 260 | ++ else |
| 261 | ++ iperf_err(NULL, "iperf_cJSON_GetObjectItemType mismatch %s", item_string); |
| 262 | ++ break; |
| 263 | ++ default: |
| 264 | ++ iperf_err(NULL, "unsupported type"); |
| 265 | ++ } |
| 266 | ++ |
| 267 | ++ return NULL; |
| 268 | ++} |
| 269 | ++ |
| 270 | + /* Debugging routine to dump out an fd_set. */ |
| 271 | + void |
| 272 | + iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds) |
| 273 | +diff --git a/src/iperf_util.h b/src/iperf_util.h |
| 274 | +index b109af2..c39a1f7 100644 |
| 275 | +--- a/src/iperf_util.h |
| 276 | ++++ b/src/iperf_util.h |
| 277 | +@@ -53,6 +53,7 @@ const char* get_system_info(void); |
| 278 | + const char* get_optional_features(void); |
| 279 | + |
| 280 | + cJSON* iperf_json_printf(const char *format, ...); |
| 281 | ++cJSON * iperf_cJSON_GetObjectItemType(cJSON * j_p, char * item_string, int expected_type); |
| 282 | + |
| 283 | + void iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds); |
| 284 | + |
| 285 | +-- |
| 286 | +2.45.2 |
| 287 | + |
0 commit comments