Skip to content

Commit 40f40a6

Browse files
committed
fix: Stop memcpy-ing internal data structures into packets.
1 parent b66b8de commit 40f40a6

7 files changed

Lines changed: 53 additions & 23 deletions

File tree

toxcore/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ cc_fuzz_test(
631631
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
632632
deps = [
633633
":DHT",
634+
":DHT_test_util",
634635
":mem_test_util",
635636
":net_profile",
636637
"//c-toxcore/testing/fuzzing:fuzz_support",

toxcore/DHT.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,9 @@ static int friend_iplist(const DHT *_Nonnull dht, IP_Port *_Nonnull ip_portlist,
19311931
}
19321932

19331933
#ifdef FRIEND_IPLIST_PAD
1934-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1934+
for (int i = 0; i < num_ipv6s; ++i) {
1935+
ip_portlist[i] = ipv6s[i];
1936+
}
19351937

19361938
if (num_ipv6s == MAX_FRIEND_CLIENTS) {
19371939
return MAX_FRIEND_CLIENTS;
@@ -1943,7 +1945,9 @@ static int friend_iplist(const DHT *_Nonnull dht, IP_Port *_Nonnull ip_portlist,
19431945
num_ipv4s_used = num_ipv4s;
19441946
}
19451947

1946-
memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1948+
for (int i = 0; i < num_ipv4s_used; ++i) {
1949+
ip_portlist[num_ipv6s + i] = ipv4s[i];
1950+
}
19471951
return num_ipv6s + num_ipv4s_used;
19481952

19491953
#else /* !FRIEND_IPLIST_PAD */
@@ -1952,11 +1956,15 @@ static int friend_iplist(const DHT *_Nonnull dht, IP_Port *_Nonnull ip_portlist,
19521956
* with the shorter one...
19531957
*/
19541958
if (num_ipv6s >= num_ipv4s) {
1955-
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1959+
for (int i = 0; i < num_ipv6s; ++i) {
1960+
ip_portlist[i] = ipv6s[i];
1961+
}
19561962
return num_ipv6s;
19571963
}
19581964

1959-
memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
1965+
for (int i = 0; i < num_ipv4s; ++i) {
1966+
ip_portlist[i] = ipv4s[i];
1967+
}
19601968
return num_ipv4s;
19611969

19621970
#endif /* !FRIEND_IPLIST_PAD */
@@ -2515,7 +2523,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
25152523
dht->hole_punching_enabled = hole_punching_enabled;
25162524
dht->lan_discovery_enabled = lan_discovery_enabled;
25172525

2518-
dht->ping = ping_new(mem, mono_time, rng, dht, net);
2526+
dht->ping = ping_new(mem, mono_time, log, rng, dht, net);
25192527

25202528
if (dht->ping == nullptr) {
25212529
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
#include "mem_test_util.hh"
1011

1112
namespace {
@@ -29,32 +30,33 @@ void TestUnpackNodes(Fuzz_Data &input)
2930
CONSUME1_OR_RETURN(const bool, tcp_enabled, input);
3031

3132
const uint16_t node_count = 5;
32-
Node_format nodes[node_count];
33+
std::array<Node_format, node_count> nodes;
3334
uint16_t processed_data_len;
3435
const int packed_count = unpack_nodes(
35-
nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled);
36+
nodes.data(), nodes.size(), &processed_data_len, input.data(), input.size(), tcp_enabled);
3637
if (packed_count > 0) {
3738
const Memory *mem = os_memory();
3839
Logger *logger = logger_new(mem);
3940
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
4041
const int packed_size
41-
= pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count);
42+
= pack_nodes(logger, packed.data(), packed.size(), nodes.data(), packed_count);
4243
LOGGER_ASSERT(logger, packed_size == processed_data_len,
4344
"packed size (%d) != unpacked size (%d)", packed_size, processed_data_len);
4445
logger_kill(logger);
4546

4647
// Check that packed nodes can be unpacked again and result in the
4748
// original unpacked nodes.
48-
Node_format nodes2[node_count];
49+
std::array<Node_format, node_count> nodes2;
4950
uint16_t processed_data_len2;
50-
const int packed_count2 = unpack_nodes(
51-
nodes2, node_count, &processed_data_len2, packed.data(), packed.size(), tcp_enabled);
51+
const int packed_count2 = unpack_nodes(nodes2.data(), nodes2.size(), &processed_data_len2,
52+
packed.data(), packed.size(), tcp_enabled);
5253
(void)packed_count2;
5354
#if 0
5455
assert(processed_data_len2 == processed_data_len);
5556
assert(packed_count2 == packed_count);
5657
#endif
57-
assert(memcmp(nodes, nodes2, sizeof(Node_format) * packed_count) == 0);
58+
assert(std::vector<Node_format>(nodes.begin(), nodes.begin() + packed_count)
59+
== std::vector<Node_format>(nodes2.begin(), nodes2.begin() + packed_count));
5860
}
5961
}
6062

toxcore/Messenger.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2438,7 +2438,7 @@ static bool self_announce_group(const Messenger *_Nonnull m, GC_Chat *_Nonnull c
24382438
announce.base_announce.ip_port_is_set = ip_port_is_set;
24392439

24402440
if (ip_port_is_set) {
2441-
memcpy(&announce.base_announce.ip_port, &chat->self_ip_port, sizeof(IP_Port));
2441+
announce.base_announce.ip_port = chat->self_ip_port;
24422442
}
24432443

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

toxcore/network.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ int net_send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet p
842842
{
843843
IP_Port ipp_copy = *ip_port;
844844

845-
if (net_family_is_unspec(ip_port->ip.family)) {
845+
if (net_family_is_unspec(ipp_copy.ip.family)) {
846846
// TODO(iphydf): Make this an error. Currently this fails sometimes when
847847
// called from DHT.c:do_ping_and_sendnode_requests.
848848
return -1;
@@ -905,7 +905,7 @@ int net_send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet p
905905
}
906906

907907
const long res = net_sendto(net->ns, net->sock, packet.data, packet.length, &addr, &ipp_copy);
908-
net_log_data(net->log, "O=>", packet.data, packet.length, ip_port, res);
908+
net_log_data(net->log, "O=>", packet.data, packet.length, &ipp_copy, res);
909909

910910
assert(res <= INT_MAX);
911911

@@ -934,7 +934,8 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
934934
*/
935935
static int receivepacket(const Network *_Nonnull ns, const Logger *_Nonnull log, Socket sock, IP_Port *_Nonnull ip_port, uint8_t *_Nonnull data, uint32_t *_Nonnull length)
936936
{
937-
memset(ip_port, 0, sizeof(IP_Port));
937+
ipport_reset(ip_port);
938+
938939
Network_Addr addr = {{0}};
939940
addr.size = sizeof(addr.addr);
940941
*length = 0;
@@ -1431,13 +1432,25 @@ void ip_reset(IP *ip)
14311432
static const IP_Port empty_ip_port = {{{0}}};
14321433

14331434
/** nulls out ip_port */
1434-
void ipport_reset(IP_Port *ipport)
1435+
void ipport_reset(IP_Port *_Nonnull ipport)
14351436
{
14361437
if (ipport == nullptr) {
14371438
return;
14381439
}
14391440

1441+
#ifdef RANDOM_PADDING
1442+
// Leave padding bytes as uninitialized data. This should not matter, because we
1443+
// then set all the actual fields to 0.
1444+
IP_Port empty;
1445+
empty.ip.family.value = 0;
1446+
empty.ip.ip.v6.uint64[0] = 0;
1447+
empty.ip.ip.v6.uint64[1] = 0;
1448+
empty.port = 0;
1449+
1450+
*ipport = empty;
1451+
#else
14401452
*ipport = empty_ip_port;
1453+
#endif /* RANDOM_PADDING */
14411454
}
14421455

14431456
/** nulls out ip, sets family according to flag */
@@ -1546,7 +1559,7 @@ bool bin_pack_ip_port(Bin_Pack *bp, const Logger *logger, const IP_Port *ip_port
15461559
Ip_Ntoa ip_str;
15471560
// TODO(iphydf): Find out why we're trying to pack invalid IPs, stop
15481561
// doing that, and turn this into an error.
1549-
LOGGER_TRACE(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
1562+
LOGGER_DEBUG(logger, "cannot pack invalid IP: %s", net_ip_ntoa(&ip_port->ip, &ip_str));
15501563
return false;
15511564
}
15521565

@@ -1566,6 +1579,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_
15661579
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);
15671580

15681581
if (size > length) {
1582+
LOGGER_ERROR(logger, "not enough space for packed IP: %u but need %u", length, size);
15691583
return -1;
15701584
}
15711585

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
const Memory *mem;
3538
DHT *dht;
@@ -42,7 +45,7 @@ struct Ping {
4245

4346
#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
4447
#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
45-
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
48+
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT)
4649

4750
void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key)
4851
{
@@ -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) {
@@ -205,7 +209,7 @@ static int handle_ping_response(void *_Nonnull object, const IP_Port *_Nonnull s
205209
}
206210

207211
IP_Port ipp;
208-
memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
212+
unpack_ip_port(&ipp, &data[CRYPTO_PUBLIC_KEY_SIZE], PING_DATA_SIZE - CRYPTO_PUBLIC_KEY_SIZE, false);
209213

210214
if (!ipport_equal(&ipp, source)) {
211215
return 1;
@@ -325,7 +329,7 @@ void ping_iterate(Ping *ping)
325329
}
326330
}
327331

328-
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht, Networking_Core *net)
332+
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht, Networking_Core *net)
329333
{
330334
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
331335

@@ -341,6 +345,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
341345
}
342346

343347
ping->mono_time = mono_time;
348+
ping->log = log;
344349
ping->rng = rng;
345350
ping->mem = mem;
346351
ping->dht = dht;

toxcore/ping.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
typedef struct Ping Ping;
2323

24-
Ping *_Nullable ping_new(const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Random *_Nonnull rng, DHT *_Nonnull dht, Networking_Core *_Nonnull net);
24+
Ping *_Nullable ping_new(const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Logger *_Nonnull log, const Random *_Nonnull rng, DHT *_Nonnull dht, Networking_Core *_Nonnull net);
2525

2626
void ping_kill(const Memory *_Nonnull mem, Ping *_Nullable ping);
2727
/** @brief Add nodes to the to_ping list.

0 commit comments

Comments
 (0)