Skip to content

Commit dd45f9e

Browse files
committed
fix: Stop memcpy-ing internal data structures into packets.
1 parent 7b1db6a commit dd45f9e

File tree

10 files changed

+71
-37
lines changed

10 files changed

+71
-37
lines changed

toxcore/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,12 @@ cc_test(
478478
cc_fuzz_test(
479479
name = "DHT_fuzz_test",
480480
size = "small",
481+
testonly = True,
481482
srcs = ["DHT_fuzz_test.cc"],
482483
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
483484
deps = [
484485
":DHT",
486+
":DHT_test_util",
485487
"//c-toxcore/testing/fuzzing:fuzz_support",
486488
],
487489
)

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 */
@@ -2539,7 +2547,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
25392547
dht->hole_punching_enabled = hole_punching_enabled;
25402548
dht->lan_discovery_enabled = lan_discovery_enabled;
25412549

2542-
dht->ping = ping_new(mem, mono_time, rng, dht);
2550+
dht->ping = ping_new(mem, mono_time, log, rng, dht);
25432551

25442552
if (dht->ping == nullptr) {
25452553
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.hh"
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
@@ -2591,7 +2591,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
25912591
announce.base_announce.ip_port_is_set = ip_port_is_set;
25922592

25932593
if (ip_port_is_set) {
2594-
memcpy(&announce.base_announce.ip_port, &chat->self_ip_port, sizeof(IP_Port));
2594+
announce.base_announce.ip_port = chat->self_ip_port;
25952595
}
25962596

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

toxcore/network.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
933933
{
934934
IP_Port ipp_copy = *ip_port;
935935

936-
if (net_family_is_unspec(ip_port->ip.family)) {
936+
if (net_family_is_unspec(ipp_copy.ip.family)) {
937937
// TODO(iphydf): Make this an error. Currently this fails sometimes when
938938
// called from DHT.c:do_ping_and_sendnode_requests.
939939
return -1;
@@ -996,7 +996,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
996996
}
997997

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

10011001
assert(res <= INT_MAX);
10021002
return (int)res;
@@ -1021,7 +1021,8 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
10211021
non_null()
10221022
static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
10231023
{
1024-
memset(ip_port, 0, sizeof(IP_Port));
1024+
ipport_reset(ip_port);
1025+
10251026
Network_Addr addr = {{0}};
10261027
addr.size = sizeof(addr.addr);
10271028
*length = 0;
@@ -1514,13 +1515,25 @@ void ip_reset(IP *ip)
15141515
static const IP_Port empty_ip_port = {{{0}}};
15151516

15161517
/** nulls out ip_port */
1517-
void ipport_reset(IP_Port *ipport)
1518+
void ipport_reset(IP_Port *ip_port)
15181519
{
1519-
if (ipport == nullptr) {
1520+
if (ip_port == nullptr) {
15201521
return;
15211522
}
15221523

1523-
*ipport = empty_ip_port;
1524+
#ifdef RANDOM_PADDING
1525+
// Leave padding bytes as uninitialized data. This should not matter, because we
1526+
// then set all the actual fields to 0.
1527+
IP_Port empty;
1528+
empty.ip.family.value = 0;
1529+
empty.ip.ip.v6.uint64[0] = 0;
1530+
empty.ip.ip.v6.uint64[1] = 0;
1531+
empty.port = 0;
1532+
1533+
*ip_port = empty;
1534+
#else
1535+
*ip_port = empty_ip_port;
1536+
#endif /* RANDOM_PADDING */
15241537
}
15251538

15261539
/** nulls out ip, sets family according to flag */
@@ -1630,7 +1643,7 @@ bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port
16301643
Ip_Ntoa ip_str;
16311644
// TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
16321645
// doing that, and turn this into an error.
1633-
LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
1646+
LOGGER_DEBUG(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
16341647
return false;
16351648
}
16361649

@@ -1651,6 +1664,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_
16511664
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
16521665

16531666
if (size > length) {
1667+
LOGGER_ERROR(logger, "not enough space for packed IP: %u but need %u", length, size);
16541668
return -1;
16551669
}
16561670

toxcore/network.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ non_null()
378378
void ip_reset(IP *ip);
379379
/** nulls out ip_port */
380380
non_null()
381-
void ipport_reset(IP_Port *ipport);
381+
void ipport_reset(IP_Port *ip_port);
382382
/** nulls out ip, sets family according to flag */
383383
non_null()
384384
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
@@ -24,6 +24,7 @@
2424
#include "onion.h"
2525
#include "shared_key_cache.h"
2626
#include "timed_auth.h"
27+
#include "util.h"
2728

2829
#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
2930

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

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

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

@@ -510,7 +512,7 @@ static int handle_announce_request_common(
510512
int nodes_length = 0;
511513

512514
if (num_nodes != 0) {
513-
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,
514516
(uint16_t)num_nodes);
515517

516518
if (nodes_length <= 0) {

toxcore/onion_client.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -576,11 +576,12 @@ non_null()
576576
static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,
577577
uint32_t path_num, uint64_t *sendback)
578578
{
579-
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
579+
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
580580
memcpy(data, &num, sizeof(uint32_t));
581-
memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
582-
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, ip_port, sizeof(IP_Port));
583-
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
581+
memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE);
582+
const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port);
583+
memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
584+
memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t));
584585
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
585586

586587
if (*sendback == 0) {
@@ -607,15 +608,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
607608
{
608609
uint64_t sback;
609610
memcpy(&sback, sendback, sizeof(uint64_t));
610-
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
611+
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
611612

612613
if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
613614
return -1;
614615
}
615616

616617
memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
617-
memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
618-
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
618+
unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
619+
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));
619620

620621
uint32_t num;
621622
memcpy(&num, data, sizeof(uint32_t));

toxcore/ping.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
#include "attributes.h"
1616
#include "ccompat.h"
1717
#include "crypto_core.h"
18+
#include "logger.h"
1819
#include "mem.h"
1920
#include "mono_time.h"
2021
#include "network.h"
2122
#include "ping_array.h"
23+
#include "util.h"
2224

2325
#define PING_NUM_MAX 512
2426

@@ -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

@@ -40,7 +43,7 @@ struct Ping {
4043

4144
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
4245
#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
43-
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
46+
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT)
4447

4548
void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key)
4649
{
@@ -57,7 +60,8 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
5760
// Generate random ping_id.
5861
uint8_t data[PING_DATA_SIZE];
5962
pk_copy(data, public_key);
60-
memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, ipp, sizeof(IP_Port));
63+
const int packed_len = pack_ip_port(ping->log, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, ipp);
64+
memzero(&data[packed_len], SIZE_IPPORT - packed_len);
6165
ping_id = ping_array_add(ping->ping_array, ping->mono_time, ping->rng, data, sizeof(data));
6266

6367
if (ping_id == 0) {
@@ -209,7 +213,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8
209213
}
210214

211215
IP_Port ipp;
212-
memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
216+
unpack_ip_port(&ipp, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, false);
213217

214218
if (!ipport_equal(&ipp, source)) {
215219
return 1;
@@ -331,7 +335,7 @@ void ping_iterate(Ping *ping)
331335
}
332336
}
333337

334-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
338+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht)
335339
{
336340
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
337341

@@ -347,6 +351,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
347351
}
348352

349353
ping->mono_time = mono_time;
354+
ping->log = log;
350355
ping->rng = rng;
351356
ping->dht = dht;
352357
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
@@ -22,7 +22,7 @@
2222
typedef struct Ping Ping;
2323

2424
non_null()
25-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht);
25+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht);
2626

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

0 commit comments

Comments
 (0)