Skip to content

Commit 0912c60

Browse files
committed
fix: Stop memcpy-ing internal data structures into packets.
1 parent c084093 commit 0912c60

File tree

10 files changed

+64
-37
lines changed

10 files changed

+64
-37
lines changed

toxcore/BUILD.bazel

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

toxcore/DHT.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ static bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *
410410
Ip_Ntoa ip_str;
411411
// TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
412412
// doing that, and turn this into an error.
413-
LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
413+
LOGGER_DEBUG(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
414414
return false;
415415
}
416416

@@ -431,6 +431,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_
431431
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
432432

433433
if (size > length) {
434+
LOGGER_ERROR(logger, "not enough space for packed IP: %u but need %u", length, size);
434435
return -1;
435436
}
436437

@@ -2077,7 +2078,9 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
20772078
}
20782079

20792080
#ifdef FRIEND_IPLIST_PAD
2080-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
2081+
for (int i = 0; i < num_ipv6s; ++i) {
2082+
ip_portlist[i] = ipv6s[i];
2083+
}
20812084

20822085
if (num_ipv6s == MAX_FRIEND_CLIENTS) {
20832086
return MAX_FRIEND_CLIENTS;
@@ -2089,7 +2092,9 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
20892092
num_ipv4s_used = num_ipv4s;
20902093
}
20912094

2092-
memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
2095+
for (int i = 0; i < num_ipv4s_used; ++i) {
2096+
ip_portlist[num_ipv6s + i] = ipv4s[i];
2097+
}
20932098
return num_ipv6s + num_ipv4s_used;
20942099

20952100
#else /* !FRIEND_IPLIST_PAD */
@@ -2098,11 +2103,15 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
20982103
* with the shorter one...
20992104
*/
21002105
if (num_ipv6s >= num_ipv4s) {
2101-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
2106+
for (int i = 0; i < num_ipv6s; ++i) {
2107+
ip_portlist[i] = ipv6s[i];
2108+
}
21022109
return num_ipv6s;
21032110
}
21042111

2105-
memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
2112+
for (int i = 0; i < num_ipv4s; ++i) {
2113+
ip_portlist[i] = ipv4s[i];
2114+
}
21062115
return num_ipv4s;
21072116

21082117
#endif /* !FRIEND_IPLIST_PAD */
@@ -2680,7 +2689,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
26802689
dht->hole_punching_enabled = hole_punching_enabled;
26812690
dht->lan_discovery_enabled = lan_discovery_enabled;
26822691

2683-
dht->ping = ping_new(mem, mono_time, rng, dht);
2692+
dht->ping = ping_new(mem, mono_time, log, rng, dht);
26842693

26852694
if (dht->ping == nullptr) {
26862695
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: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
923923
{
924924
IP_Port ipp_copy = *ip_port;
925925

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

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

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

15031504
/** nulls out ip_port */
1504-
void ipport_reset(IP_Port *ipport)
1505+
void ipport_reset(IP_Port *ip_port)
15051506
{
1506-
if (ipport == nullptr) {
1507+
if (ip_port == nullptr) {
15071508
return;
15081509
}
15091510

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

15141522
/** nulls out ip, sets family according to flag */

toxcore/network.h

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

toxcore/onion_announce.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,13 @@ static int handle_announce_request_common(
462462
return 1;
463463
}
464464

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)];
465+
const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT;
466+
// Must zero-init, because pack_ip_port may not write to all bytes.
467+
// We only need to zero-init the last few bytes, but that's more
468+
// error-prone, so we just zero-init everything.
469+
uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT] = {0};
467470
memcpy(ping_id_data, packet_public_key, CRYPTO_PUBLIC_KEY_SIZE);
468-
memcpy(ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, source, sizeof(*source));
471+
pack_ip_port(onion_a->log, ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, source);
469472

470473
const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
471474

@@ -509,7 +512,7 @@ static int handle_announce_request_common(
509512
int nodes_length = 0;
510513

511514
if (num_nodes != 0) {
512-
nodes_length = pack_nodes(onion_a->log, response + nodes_offset, sizeof(nodes_list), nodes_list,
515+
nodes_length = pack_nodes(onion_a->log, response + nodes_offset, num_nodes * PACKED_NODE_SIZE_IP6, nodes_list,
513516
(uint16_t)num_nodes);
514517

515518
if (nodes_length <= 0) {

toxcore/onion_client.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,11 @@ 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));
589589
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));
590+
pack_ip_port(onion_c->logger, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, ip_port);
591+
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, &path_num, sizeof(uint32_t));
592592
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
593593

594594
if (*sendback == 0) {
@@ -615,15 +615,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
615615
{
616616
uint64_t sback;
617617
memcpy(&sback, sendback, sizeof(uint64_t));
618-
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
618+
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
619619

620620
if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
621621
return -1;
622622
}
623623

624624
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));
625+
unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
626+
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));
627627

628628
uint32_t num;
629629
memcpy(&num, data, sizeof(uint32_t));

toxcore/ping.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
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"
@@ -30,6 +31,7 @@
3031

3132
struct Ping {
3233
const Mono_Time *mono_time;
34+
const Logger *log;
3335
const Random *rng;
3436
DHT *dht;
3537

@@ -41,7 +43,7 @@ struct Ping {
4143

4244
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
4345
#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))
46+
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT)
4547

4648
void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key)
4749
{
@@ -59,7 +61,7 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
5961
// Generate random ping_id.
6062
uint8_t data[PING_DATA_SIZE];
6163
pk_copy(data, public_key);
62-
memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, ipp, sizeof(IP_Port));
64+
pack_ip_port(ping->log, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, ipp);
6365
ping_id = ping_array_add(ping->ping_array, ping->mono_time, ping->rng, data, sizeof(data));
6466

6567
if (ping_id == 0) {
@@ -212,7 +214,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8
212214
}
213215

214216
IP_Port ipp;
215-
memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
217+
unpack_ip_port(&ipp, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, false);
216218

217219
if (!ipport_equal(&ipp, source)) {
218220
return 1;
@@ -336,7 +338,7 @@ void ping_iterate(Ping *ping)
336338
}
337339

338340

339-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
341+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht)
340342
{
341343
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
342344

@@ -352,6 +354,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
352354
}
353355

354356
ping->mono_time = mono_time;
357+
ping->log = log;
355358
ping->rng = rng;
356359
ping->dht = dht;
357360
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)