Skip to content

Commit e153818

Browse files
authored
Wireshark: reduce use of wmem_file_scope (#240)
The wmem scope `wmem_file_scope()` is used in several places to allocate strings which are actually only used in the packet scope, and discarded after. This is effectively a memory leak since those strings are re-allocated each time the packet is processed, and each copy is kept until the file is closed. Change the functions which return file-scoped strings (such as `ja4s()`) to instead accept a wmem scope as a second argument, and return the string allocated in that scope instead. Those functions are all only called from `dissect_ja4()` so call them with `pinfo->pool` as the scope, ensuring the memory will be reused after each packet rather than kept around. Also in `dissect_ja4()`, allocate display strings in `pinfo->pool` scope for the same reasons as above. More minor performance changes: Create `conn_hash` and `quic_conn_hash` using `wmem_map_new_autoreset()` at registration time instead of using `wmem_map_new()` upon each new file. Get the value of `proto_http` once at handoff time instead of each time a new file is loaded.
1 parent 83a5b4d commit e153818

File tree

1 file changed

+49
-50
lines changed

1 file changed

+49
-50
lines changed

wireshark/source/packet-ja4.c

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,10 @@ void update_mode(int pkt_len, wmem_map_t *hash_table) {
313313
}
314314
}
315315

316-
int get_max_mode(wmem_map_t *hash_table) {
316+
int get_max_mode(wmem_allocator_t *scratch, wmem_map_t *hash_table) {
317317
int counter = 0;
318318
int max_mode = 0;
319-
wmem_list_t *keys = wmem_map_get_keys(wmem_file_scope(), hash_table);
319+
wmem_list_t *keys = wmem_map_get_keys(scratch, hash_table);
320320
wmem_list_frame_t *key = wmem_list_head(keys);
321321
while (key) {
322322
int pkt_len = GPOINTER_TO_INT(wmem_list_frame_data(key));
@@ -450,8 +450,8 @@ void create_sorted_cookies(wmem_strbuf_t **fields, wmem_strbuf_t **values, wmem_
450450
);
451451
}
452452

453-
char *ja4s_r(ja4_info_t *data) {
454-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
453+
char *ja4s_r(wmem_allocator_t *scope, ja4_info_t *data) {
454+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
455455
wmem_strbuf_append_printf(
456456
display, "%c%s%02d%c%c_%s_%s", data->proto,
457457
val_to_str_const(data->version, ssl_versions, "00"), data->ext_len,
@@ -464,8 +464,8 @@ char *ja4s_r(ja4_info_t *data) {
464464
return (char *)wmem_strbuf_get_str(display);
465465
}
466466

467-
char *ja4s(ja4_info_t *data) {
468-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
467+
char *ja4s(wmem_allocator_t *scope, ja4_info_t *data) {
468+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
469469
gchar *_hash =
470470
g_compute_checksum_for_string(G_CHECKSUM_SHA256, wmem_strbuf_get_str(data->extensions), -1);
471471
wmem_strbuf_append_printf(
@@ -483,8 +483,8 @@ char *ja4s(ja4_info_t *data) {
483483
return (char *)wmem_strbuf_get_str(display);
484484
}
485485

486-
char *ja4x(cert_t *cert) {
487-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
486+
char *ja4x(wmem_allocator_t *scope, cert_t *cert) {
487+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
488488
gchar *hash1 =
489489
g_compute_checksum_for_string(G_CHECKSUM_SHA256, wmem_strbuf_get_str(cert->oids[0]), -1);
490490
gchar *hash2 =
@@ -506,8 +506,8 @@ char *ja4x(cert_t *cert) {
506506
return (char *)wmem_strbuf_get_str(display);
507507
}
508508

509-
char *ja4h_r(ja4h_info_t *data) {
510-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
509+
char *ja4h_r(wmem_allocator_t *scope, ja4h_info_t *data) {
510+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
511511
wmem_strbuf_append_printf(
512512
display, "%s%s%s%s%02d%s_%s_%s_%s", wmem_strbuf_get_str(data->method),
513513
wmem_strbuf_get_str(data->version), data->cookie ? "c" : "n", data->referer ? "r" : "n",
@@ -518,8 +518,8 @@ char *ja4h_r(ja4h_info_t *data) {
518518
return (char *)wmem_strbuf_get_str(display);
519519
}
520520

521-
char *ja4h_ro(ja4h_info_t *data) {
522-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
521+
char *ja4h_ro(wmem_allocator_t *scope, ja4h_info_t *data) {
522+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
523523
wmem_strbuf_append_printf(
524524
display, "%s%s%s%s%02d%s_%s_%s_%s", wmem_strbuf_get_str(data->method),
525525
wmem_strbuf_get_str(data->version), data->cookie ? "c" : "n", data->referer ? "r" : "n",
@@ -530,8 +530,8 @@ char *ja4h_ro(ja4h_info_t *data) {
530530
return (char *)wmem_strbuf_get_str(display);
531531
}
532532

533-
char *ja4h(ja4h_info_t *data) {
534-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
533+
char *ja4h(wmem_allocator_t *scope, ja4h_info_t *data) {
534+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
535535
gchar *hash1 =
536536
g_compute_checksum_for_string(G_CHECKSUM_SHA256, wmem_strbuf_get_str(data->headers), -1);
537537
gchar *hash2 = g_compute_checksum_for_string(
@@ -556,19 +556,19 @@ char *ja4h(ja4h_info_t *data) {
556556
return (char *)wmem_strbuf_get_str(display);
557557
}
558558

559-
char *ja4ssh(conn_info_t *conn) {
560-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
559+
char *ja4ssh(wmem_allocator_t *scope, conn_info_t *conn) {
560+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
561561
wmem_strbuf_append_printf(
562-
display, "c%ds%d_c%ds%d_c%ds%d", get_max_mode(conn->client_mode),
563-
get_max_mode(conn->server_mode), conn->client_pkts, conn->server_pkts,
562+
display, "c%ds%d_c%ds%d_c%ds%d", get_max_mode(scope, conn->client_mode),
563+
get_max_mode(scope, conn->server_mode), conn->client_pkts, conn->server_pkts,
564564
conn->tcp_client_acks, conn->tcp_server_acks
565565
);
566566
return (char *)wmem_strbuf_get_str(display);
567567
}
568568

569569
// Compute JA4T
570-
char *ja4t(ja4t_info_t *data, conn_info_t *conn) {
571-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
570+
char *ja4t(wmem_allocator_t *scope, ja4t_info_t *data, conn_info_t *conn) {
571+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
572572
if (wmem_strbuf_get_len(data->tcp_options) > 0)
573573
wmem_strbuf_truncate(data->tcp_options, wmem_strbuf_get_len(data->tcp_options) - 1);
574574
if (data->window_scale == 0) {
@@ -605,8 +605,8 @@ char *ja4t(ja4t_info_t *data, conn_info_t *conn) {
605605
return (char *)wmem_strbuf_get_str(display);
606606
}
607607

608-
char *ja4d(ja4d_info_t *data) {
609-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
608+
char *ja4d(wmem_allocator_t *scope, ja4d_info_t *data) {
609+
wmem_strbuf_t *display = wmem_strbuf_new(scope, "");
610610
if (wmem_strbuf_get_len(data->size) == 0)
611611
wmem_strbuf_append_printf(data->size, "00");
612612
if (wmem_strbuf_get_len(data->options) == 0)
@@ -758,7 +758,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
758758
ja4h_data.sorted_cookie_values = wmem_strbuf_new(pinfo->pool, "");
759759

760760
ja4t_info_t ja4t_data;
761-
ja4t_data.tcp_options = wmem_strbuf_new(wmem_file_scope(), "");
761+
ja4t_data.tcp_options = wmem_strbuf_new(pinfo->pool, "");
762762
ja4t_data.mss_val = 0;
763763
ja4t_data.window_scale = 0;
764764
ja4t_data.window_size = 0;
@@ -798,10 +798,10 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
798798
set_ja4_ciphers(tree, &ja4_data);
799799
set_ja4s_extensions(tree, &ja4_data);
800800
update_tree_item(
801-
tvb, tree, &ja4_tree, hf_ja4s, ja4s(&ja4_data), proto
801+
tvb, tree, &ja4_tree, hf_ja4s, ja4s(pinfo->pool, &ja4_data), proto
802802
);
803803
update_tree_item(
804-
tvb, tree, &ja4_tree, hf_ja4s_raw, ja4s_r(&ja4_data), proto
804+
tvb, tree, &ja4_tree, hf_ja4s_raw, ja4s_r(pinfo->pool, &ja4_data), proto
805805
);
806806
}
807807

@@ -1137,9 +1137,9 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
11371137
// Denotes first PSH, ACK
11381138
nstime_copy(&conn->timestamp_D, packet_time);
11391139
} else {
1140-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
1141-
wmem_strbuf_t *display2 = wmem_strbuf_new(wmem_file_scope(), "");
1142-
1140+
wmem_strbuf_t *display = wmem_strbuf_new(pinfo->pool, "");
1141+
wmem_strbuf_t *display2 = wmem_strbuf_new(pinfo->pool, "");
1142+
11431143
bool is_http = false;
11441144
GPtrArray *proto_http_array = proto_find_first_finfo(tree, proto_http);
11451145
if (proto_http_array && proto_http_array->len > 0) {
@@ -1210,7 +1210,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
12101210
if ((fvalue_get_uinteger(get_value_ptr(field)) == 0x011) &&
12111211
((srcport == 22) || (dstport == 22))) {
12121212
update_tree_item(
1213-
tvb, tree, &ja4_tree, hf_ja4ssh, ja4ssh(conn), "tcp"
1213+
tvb, tree, &ja4_tree, hf_ja4ssh, ja4ssh(pinfo->pool, conn), "tcp"
12141214
);
12151215
}
12161216
}
@@ -1244,8 +1244,8 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
12441244
(nstime_is_zero(&conn->timestamp_D))) {
12451245
nstime_copy(&conn->timestamp_D, packet_time);
12461246

1247-
wmem_strbuf_t *display = wmem_strbuf_new(wmem_file_scope(), "");
1248-
wmem_strbuf_t *display2 = wmem_strbuf_new(wmem_file_scope(), "");
1247+
wmem_strbuf_t *display = wmem_strbuf_new(pinfo->pool, "");
1248+
wmem_strbuf_t *display2 = wmem_strbuf_new(pinfo->pool, "");
12491249

12501250
nstime_delta(&latency, &conn->timestamp_B, &conn->timestamp_A);
12511251
wmem_strbuf_append_printf(
@@ -1295,7 +1295,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
12951295

12961296
if ((conn->pkts % SAMPLE_COUNT) == 0) {
12971297
update_tree_item(
1298-
tvb, tree, &ja4_tree, hf_ja4ssh, ja4ssh(conn), "ssh"
1298+
tvb, tree, &ja4_tree, hf_ja4ssh, ja4ssh(pinfo->pool, conn), "ssh"
12991299
);
13001300

13011301
// reset conn parameters for the next ssh iteration
@@ -1362,7 +1362,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
13621362
}
13631363

13641364
if (syn == 1) {
1365-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4t, ja4t(&ja4t_data, NULL), "tcp");
1365+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4t, ja4t(pinfo->pool, &ja4t_data, NULL), "tcp");
13661366
}
13671367
if (syn == 2) {
13681368
conn_info_t *conn = conn_lookup(ja4_data.proto, stream);
@@ -1372,7 +1372,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
13721372
if (conn->tcp_options == NULL)
13731373
conn->tcp_options =
13741374
wmem_strbuf_new(wmem_file_scope(), wmem_strbuf_get_str(ja4t_data.tcp_options));
1375-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4ts, ja4t(&ja4t_data, conn), "tcp");
1375+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4ts, ja4t(pinfo->pool, &ja4t_data, conn), "tcp");
13761376
}
13771377

13781378
if (syn == 3) {
@@ -1384,14 +1384,14 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
13841384
wmem_strbuf_append_printf(
13851385
ja4t_data.tcp_options, "%s", wmem_strbuf_get_str(conn->tcp_options)
13861386
);
1387-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4ts, ja4t(&ja4t_data, conn), "tcp");
1387+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4ts, ja4t(pinfo->pool, &ja4t_data, conn), "tcp");
13881388
}
13891389

13901390
if (handshake_type == 2) {
13911391
set_ja4_ciphers(tree, &ja4_data);
13921392
set_ja4s_extensions(tree, &ja4_data);
1393-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4s, ja4s(&ja4_data), proto);
1394-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4s_raw, ja4s_r(&ja4_data), proto);
1393+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4s, ja4s(pinfo->pool, &ja4_data), proto);
1394+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4s_raw, ja4s_r(pinfo->pool, &ja4_data), proto);
13951395
}
13961396

13971397
if (handshake_type == 11) {
@@ -1406,7 +1406,7 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
14061406
tvb, tree, &ja4_tree, hf_ja4x_raw,
14071407
wmem_strbuf_get_str(current_cert->raw), proto
14081408
);
1409-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4x, ja4x(current_cert), proto);
1409+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4x, ja4x(pinfo->pool, current_cert), proto);
14101410
}
14111411
}
14121412

@@ -1432,54 +1432,50 @@ static int dissect_ja4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
14321432
if (ja4h_data.http2 == true) {
14331433
http_proto = "http2";
14341434
}
1435-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4h, ja4h(&ja4h_data), http_proto);
1435+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4h, ja4h(pinfo->pool, &ja4h_data), http_proto);
14361436
update_tree_item(
1437-
tvb, tree, &ja4_tree, hf_ja4h_raw, ja4h_r(&ja4h_data), http_proto
1437+
tvb, tree, &ja4_tree, hf_ja4h_raw, ja4h_r(pinfo->pool, &ja4h_data), http_proto
14381438
);
14391439
update_tree_item(
1440-
tvb, tree, &ja4_tree, hf_ja4h_raw_original, ja4h_ro(&ja4h_data), http_proto
1440+
tvb, tree, &ja4_tree, hf_ja4h_raw_original, ja4h_ro(pinfo->pool, &ja4h_data), http_proto
14411441
);
14421442
}
14431443

14441444
if (ja4d_data.proto != 0) {
14451445
wmem_strbuf_truncate(ja4d_data.options, wmem_strbuf_get_len(ja4d_data.options) - 1);
14461446
wmem_strbuf_truncate(ja4d_data.request_list, wmem_strbuf_get_len(ja4d_data.request_list) - 1);
1447-
1447+
14481448
char *dhcp_proto = "dhcp";
14491449
if (ja4d_data.proto == '6') {
14501450
dhcp_proto = "dhcpv6";
14511451
}
1452-
1453-
update_tree_item(tvb, tree, &ja4_tree, hf_ja4d, ja4d(&ja4d_data), dhcp_proto);
1452+
1453+
update_tree_item(tvb, tree, &ja4_tree, hf_ja4d, ja4d(pinfo->pool, &ja4d_data), dhcp_proto);
14541454
}
14551455

14561456
return tvb_reported_length(tvb);
14571457
}
14581458

14591459
static void init_globals(void) {
1460-
conn_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1461-
quic_conn_hash = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1462-
14631460
GArray *wanted_hfids = g_array_new(FALSE, FALSE, (guint)sizeof(int));
14641461
for (int i = 0; i < HFIDS; i++) {
14651462
int id = proto_registrar_get_id_byname(interesting_hfids[i]);
14661463
if (id != -1) {
14671464
g_array_append_val(wanted_hfids, id);
14681465
} else {
14691466
g_warning("JA4: Unknown field: %s", interesting_hfids[i]);
1470-
}
1467+
}
14711468
}
14721469

14731470
set_postdissector_wanted_hfids(ja4_handle, wanted_hfids);
1474-
1475-
proto_http = proto_registrar_get_id_byname("http");
14761471
}
14771472

14781473
static void cleanup_globals(void) {
14791474
set_postdissector_wanted_hfids(ja4_handle, NULL);
14801475
}
14811476

14821477
void proto_reg_handoff_ja4(void) {
1478+
proto_http = proto_registrar_get_id_byname("http");
14831479
}
14841480

14851481
void proto_register_ja4(void) {
@@ -1521,4 +1517,7 @@ void proto_register_ja4(void) {
15211517
"'000000000000') will be omitted when cookies are missing.",
15221518
&pref_omit_ja4h_zero_sections
15231519
);
1520+
1521+
conn_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
1522+
quic_conn_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
15241523
}

0 commit comments

Comments
 (0)