Skip to content

Commit 9ce17ef

Browse files
committed
fix: Stop memcpy-ing internal data structures into packets.
1 parent 1710a0d commit 9ce17ef

File tree

10 files changed

+67
-38
lines changed

10 files changed

+67
-38
lines changed

toxcore/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,12 @@ cc_test(
447447
cc_fuzz_test(
448448
name = "DHT_fuzz_test",
449449
size = "small",
450+
testonly = True,
450451
srcs = ["DHT_fuzz_test.cc"],
451452
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
452453
deps = [
453454
":DHT",
455+
":DHT_test_util",
454456
"//c-toxcore/testing/fuzzing:fuzz_support",
455457
],
456458
)

toxcore/DHT.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,7 +1938,9 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
19381938
}
19391939

19401940
#ifdef FRIEND_IPLIST_PAD
1941-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1941+
for (int i = 0; i < num_ipv6s; ++i) {
1942+
ip_portlist[i] = ipv6s[i];
1943+
}
19421944

19431945
if (num_ipv6s == MAX_FRIEND_CLIENTS) {
19441946
return MAX_FRIEND_CLIENTS;
@@ -1950,7 +1952,9 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
19501952
num_ipv4s_used = num_ipv4s;
19511953
}
19521954

1953-
memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1955+
for (int i = 0; i < num_ipv4s_used; ++i) {
1956+
ip_portlist[num_ipv6s + i] = ipv4s[i];
1957+
}
19541958
return num_ipv6s + num_ipv4s_used;
19551959

19561960
#else /* !FRIEND_IPLIST_PAD */
@@ -1959,11 +1963,15 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
19591963
* with the shorter one...
19601964
*/
19611965
if (num_ipv6s >= num_ipv4s) {
1962-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1966+
for (int i = 0; i < num_ipv6s; ++i) {
1967+
ip_portlist[i] = ipv6s[i];
1968+
}
19631969
return num_ipv6s;
19641970
}
19651971

1966-
memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
1972+
for (int i = 0; i < num_ipv4s; ++i) {
1973+
ip_portlist[i] = ipv4s[i];
1974+
}
19671975
return num_ipv4s;
19681976

19691977
#endif /* !FRIEND_IPLIST_PAD */
@@ -2541,7 +2549,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
25412549
dht->hole_punching_enabled = hole_punching_enabled;
25422550
dht->lan_discovery_enabled = lan_discovery_enabled;
25432551

2544-
dht->ping = ping_new(mem, mono_time, rng, dht);
2552+
dht->ping = ping_new(mem, mono_time, log, rng, dht);
25452553

25462554
if (dht->ping == nullptr) {
25472555
LOGGER_ERROR(log, "failed to initialise ping");

toxcore/DHT_fuzz_test.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <vector>
77

88
#include "../testing/fuzzing/fuzz_support.h"
9+
#include "DHT_test_util.hh"
910

1011
namespace {
1112

@@ -26,31 +27,32 @@ void TestUnpackNodes(Fuzz_Data &input)
2627
CONSUME1_OR_RETURN(const bool, tcp_enabled, input);
2728

2829
const uint16_t node_count = 5;
29-
Node_format nodes[node_count];
30+
std::array<Node_format, node_count> nodes;
3031
uint16_t processed_data_len;
3132
const int packed_count = unpack_nodes(
32-
nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled);
33+
nodes.data(), nodes.size(), &processed_data_len, input.data(), input.size(), tcp_enabled);
3334
if (packed_count > 0) {
3435
Logger *logger = logger_new();
3536
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
3637
const int packed_size
37-
= pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count);
38+
= pack_nodes(logger, packed.data(), packed.size(), nodes.data(), packed_count);
3839
LOGGER_ASSERT(logger, packed_size == processed_data_len,
3940
"packed size (%d) != unpacked size (%d)", packed_size, processed_data_len);
4041
logger_kill(logger);
4142

4243
// Check that packed nodes can be unpacked again and result in the
4344
// original unpacked nodes.
44-
Node_format nodes2[node_count];
45+
std::array<Node_format, node_count> nodes2;
4546
uint16_t processed_data_len2;
46-
const int packed_count2 = unpack_nodes(
47-
nodes2, node_count, &processed_data_len2, packed.data(), packed.size(), tcp_enabled);
47+
const int packed_count2 = unpack_nodes(nodes2.data(), nodes2.size(), &processed_data_len2,
48+
packed.data(), packed.size(), tcp_enabled);
4849
(void)packed_count2;
4950
#if 0
5051
assert(processed_data_len2 == processed_data_len);
5152
assert(packed_count2 == packed_count);
5253
#endif
53-
assert(memcmp(nodes, nodes2, sizeof(Node_format) * packed_count) == 0);
54+
assert(std::vector<Node_format>(nodes.begin(), nodes.begin() + packed_count)
55+
== std::vector<Node_format>(nodes2.begin(), nodes2.begin() + packed_count));
5456
}
5557
}
5658

toxcore/Messenger.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2597,7 +2597,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
25972597
announce.base_announce.ip_port_is_set = (uint8_t)(ip_port_is_set ? 1 : 0);
25982598

25992599
if (ip_port_is_set) {
2600-
memcpy(&announce.base_announce.ip_port, &chat->self_ip_port, sizeof(IP_Port));
2600+
announce.base_announce.ip_port = chat->self_ip_port;
26012601
}
26022602

26032603
memcpy(announce.base_announce.peer_public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);

toxcore/network.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
924924
{
925925
IP_Port ipp_copy = *ip_port;
926926

927-
if (net_family_is_unspec(ip_port->ip.family)) {
927+
if (net_family_is_unspec(ipp_copy.ip.family)) {
928928
// TODO(iphydf): Make this an error. Currently this fails sometimes when
929929
// called from DHT.c:do_ping_and_sendnode_requests.
930930
return -1;
@@ -987,7 +987,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
987987
}
988988

989989
const long res = net_sendto(net->ns, net->sock, packet.data, packet.length, &addr, &ipp_copy);
990-
loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res);
990+
loglogdata(net->log, "O=>", packet.data, packet.length, &ipp_copy, res);
991991

992992
assert(res <= INT_MAX);
993993
return (int)res;
@@ -1012,7 +1012,8 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
10121012
non_null()
10131013
static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
10141014
{
1015-
memset(ip_port, 0, sizeof(IP_Port));
1015+
ipport_reset(ip_port);
1016+
10161017
Network_Addr addr = {{0}};
10171018
addr.size = sizeof(addr.addr);
10181019
*length = 0;
@@ -1502,14 +1503,21 @@ void ip_reset(IP *ip)
15021503
}
15031504

15041505
/** nulls out ip_port */
1505-
void ipport_reset(IP_Port *ipport)
1506+
void ipport_reset(IP_Port *ip_port)
15061507
{
1507-
if (ipport == nullptr) {
1508+
if (ip_port == nullptr) {
15081509
return;
15091510
}
15101511

1511-
const IP_Port empty_ip_port = {{{0}}};
1512-
*ipport = empty_ip_port;
1512+
// Leave padding bytes as uninitialized data. This should not matter, because we
1513+
// then set all the actual fields to 0.
1514+
IP_Port empty;
1515+
empty.ip.family.value = 0;
1516+
empty.ip.ip.v6.uint64[0] = 0;
1517+
empty.ip.ip.v6.uint64[1] = 0;
1518+
empty.port = 0;
1519+
1520+
*ip_port = empty;
15131521
}
15141522

15151523
/** nulls out ip, sets family according to flag */
@@ -1619,7 +1627,7 @@ bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port
16191627
Ip_Ntoa ip_str;
16201628
// TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
16211629
// doing that, and turn this into an error.
1622-
LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
1630+
LOGGER_DEBUG(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
16231631
return false;
16241632
}
16251633

@@ -1640,6 +1648,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_
16401648
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
16411649

16421650
if (size > length) {
1651+
LOGGER_ERROR(logger, "not enough space for packed IP: %u but need %u", length, size);
16431652
return -1;
16441653
}
16451654

toxcore/network.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ non_null()
374374
void ip_reset(IP *ip);
375375
/** nulls out ip_port */
376376
non_null()
377-
void ipport_reset(IP_Port *ipport);
377+
void ipport_reset(IP_Port *ip_port);
378378
/** nulls out ip, sets family according to flag */
379379
non_null()
380380
void ip_init(IP *ip, bool ipv6enabled);

toxcore/onion_announce.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "onion.h"
2424
#include "shared_key_cache.h"
2525
#include "timed_auth.h"
26+
#include "util.h"
2627

2728
#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
2829

@@ -462,10 +463,11 @@ static int handle_announce_request_common(
462463
return 1;
463464
}
464465

465-
const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source);
466-
uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source)];
466+
const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT;
467+
uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT];
467468
memcpy(ping_id_data, packet_public_key, CRYPTO_PUBLIC_KEY_SIZE);
468-
memcpy(ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, source, sizeof(*source));
469+
const int packed_len = pack_ip_port(onion_a->log, &ping_id_data[CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, source);
470+
memzero(&ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
469471

470472
const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
471473

@@ -509,7 +511,7 @@ static int handle_announce_request_common(
509511
int nodes_length = 0;
510512

511513
if (num_nodes != 0) {
512-
nodes_length = pack_nodes(onion_a->log, response + nodes_offset, sizeof(nodes_list), nodes_list,
514+
nodes_length = pack_nodes(onion_a->log, &response[nodes_offset], num_nodes * PACKED_NODE_SIZE_IP6, nodes_list,
513515
(uint16_t)num_nodes);
514516

515517
if (nodes_length <= 0) {

toxcore/onion_client.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,12 @@ non_null()
584584
static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,
585585
uint32_t path_num, uint64_t *sendback)
586586
{
587-
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
587+
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
588588
memcpy(data, &num, sizeof(uint32_t));
589-
memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
590-
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, ip_port, sizeof(IP_Port));
591-
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
589+
memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE);
590+
const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port);
591+
memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
592+
memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t));
592593
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
593594

594595
if (*sendback == 0) {
@@ -615,15 +616,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
615616
{
616617
uint64_t sback;
617618
memcpy(&sback, sendback, sizeof(uint64_t));
618-
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
619+
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
619620

620621
if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
621622
return -1;
622623
}
623624

624625
memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
625-
memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
626-
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
626+
unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
627+
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));
627628

628629
uint32_t num;
629630
memcpy(&num, data, sizeof(uint32_t));

toxcore/ping.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
#include "DHT.h"
1515
#include "ccompat.h"
1616
#include "crypto_core.h"
17+
#include "logger.h"
1718
#include "mem.h"
1819
#include "mono_time.h"
1920
#include "network.h"
2021
#include "ping_array.h"
22+
#include "util.h"
2123

2224
#define PING_NUM_MAX 512
2325

@@ -30,6 +32,7 @@
3032

3133
struct Ping {
3234
const Mono_Time *mono_time;
35+
const Logger *log;
3336
const Random *rng;
3437
DHT *dht;
3538

@@ -41,7 +44,7 @@ struct Ping {
4144

4245
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
4346
#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
44-
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
47+
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT)
4548

4649
void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key)
4750
{
@@ -59,7 +62,8 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
5962
// Generate random ping_id.
6063
uint8_t data[PING_DATA_SIZE];
6164
pk_copy(data, public_key);
62-
memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, ipp, sizeof(IP_Port));
65+
const int packed_len = pack_ip_port(ping->log, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, ipp);
66+
memzero(&data[packed_len], SIZE_IPPORT - packed_len);
6367
ping_id = ping_array_add(ping->ping_array, ping->mono_time, ping->rng, data, sizeof(data));
6468

6569
if (ping_id == 0) {
@@ -212,7 +216,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8
212216
}
213217

214218
IP_Port ipp;
215-
memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
219+
unpack_ip_port(&ipp, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, false);
216220

217221
if (!ipport_equal(&ipp, source)) {
218222
return 1;
@@ -336,7 +340,7 @@ void ping_iterate(Ping *ping)
336340
}
337341

338342

339-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
343+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht)
340344
{
341345
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
342346

@@ -352,6 +356,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
352356
}
353357

354358
ping->mono_time = mono_time;
359+
ping->log = log;
355360
ping->rng = rng;
356361
ping->dht = dht;
357362
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);

toxcore/ping.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
typedef struct Ping Ping;
1919

2020
non_null()
21-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht);
21+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht);
2222

2323
non_null(1) nullable(2)
2424
void ping_kill(const Memory *mem, Ping *ping);

0 commit comments

Comments
 (0)