Skip to content

Commit

Permalink
fix: Stop memcpy-ing internal data structures into packets.
Browse files Browse the repository at this point in the history
  • Loading branch information
iphydf committed Feb 2, 2024
1 parent b473630 commit c93ccdd
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 38 deletions.
2 changes: 2 additions & 0 deletions toxcore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,12 @@ cc_test(
cc_fuzz_test(
name = "DHT_fuzz_test",
size = "small",
testonly = True,
srcs = ["DHT_fuzz_test.cc"],
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
deps = [
":DHT",
":DHT_test_util",
"//c-toxcore/testing/fuzzing:fuzz_support",
],
)
Expand Down
18 changes: 13 additions & 5 deletions toxcore/DHT.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,9 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
}

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

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

memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
for (int i = 0; i < num_ipv4s_used; ++i) {
ip_portlist[num_ipv6s + i] = ipv4s[i];
}
return num_ipv6s + num_ipv4s_used;

#else /* !FRIEND_IPLIST_PAD */
Expand All @@ -1959,11 +1963,15 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
* with the shorter one...
*/
if (num_ipv6s >= num_ipv4s) {
memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
for (int i = 0; i < num_ipv6s; ++i) {
ip_portlist[i] = ipv6s[i];
}
return num_ipv6s;
}

memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
for (int i = 0; i < num_ipv4s; ++i) {
ip_portlist[i] = ipv4s[i];
}
return num_ipv4s;

#endif /* !FRIEND_IPLIST_PAD */
Expand Down Expand Up @@ -2539,7 +2547,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
dht->hole_punching_enabled = hole_punching_enabled;
dht->lan_discovery_enabled = lan_discovery_enabled;

dht->ping = ping_new(mem, mono_time, rng, dht);
dht->ping = ping_new(mem, mono_time, log, rng, dht);

if (dht->ping == nullptr) {
LOGGER_ERROR(log, "failed to initialise ping");
Expand Down
16 changes: 9 additions & 7 deletions toxcore/DHT_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <vector>

#include "../testing/fuzzing/fuzz_support.hh"
#include "DHT_test_util.hh"

namespace {

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

const uint16_t node_count = 5;
Node_format nodes[node_count];
std::array<Node_format, node_count> nodes;
uint16_t processed_data_len;
const int packed_count = unpack_nodes(
nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled);
nodes.data(), nodes.size(), &processed_data_len, input.data(), input.size(), tcp_enabled);
if (packed_count > 0) {
Logger *logger = logger_new();
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
const int packed_size
= pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count);
= pack_nodes(logger, packed.data(), packed.size(), nodes.data(), packed_count);
LOGGER_ASSERT(logger, packed_size == processed_data_len,
"packed size (%d) != unpacked size (%d)", packed_size, processed_data_len);
logger_kill(logger);

// Check that packed nodes can be unpacked again and result in the
// original unpacked nodes.
Node_format nodes2[node_count];
std::array<Node_format, node_count> nodes2;
uint16_t processed_data_len2;
const int packed_count2 = unpack_nodes(
nodes2, node_count, &processed_data_len2, packed.data(), packed.size(), tcp_enabled);
const int packed_count2 = unpack_nodes(nodes2.data(), nodes2.size(), &processed_data_len2,
packed.data(), packed.size(), tcp_enabled);
(void)packed_count2;
#if 0
assert(processed_data_len2 == processed_data_len);
assert(packed_count2 == packed_count);
#endif
assert(memcmp(nodes, nodes2, sizeof(Node_format) * packed_count) == 0);
assert(std::vector<Node_format>(nodes.begin(), nodes.begin() + packed_count)
== std::vector<Node_format>(nodes2.begin(), nodes2.begin() + packed_count));
}
}

Expand Down
2 changes: 1 addition & 1 deletion toxcore/Messenger.c
Original file line number Diff line number Diff line change
Expand Up @@ -2591,7 +2591,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
announce.base_announce.ip_port_is_set = ip_port_is_set;

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

memcpy(announce.base_announce.peer_public_key, chat->self_public_key, ENC_PUBLIC_KEY_SIZE);
Expand Down
25 changes: 17 additions & 8 deletions toxcore/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
{
IP_Port ipp_copy = *ip_port;

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

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

assert(res <= INT_MAX);
return (int)res;
Expand All @@ -1014,7 +1014,8 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
non_null()
static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
memset(ip_port, 0, sizeof(IP_Port));
ipport_reset(ip_port);

Network_Addr addr = {{0}};
addr.size = sizeof(addr.addr);
*length = 0;
Expand Down Expand Up @@ -1503,14 +1504,21 @@ void ip_reset(IP *ip)
}

/** nulls out ip_port */
void ipport_reset(IP_Port *ipport)
void ipport_reset(IP_Port *ip_port)
{
if (ipport == nullptr) {
if (ip_port == nullptr) {
return;
}

const IP_Port empty_ip_port = {{{0}}};
*ipport = empty_ip_port;
// Leave padding bytes as uninitialized data. This should not matter, because we
// then set all the actual fields to 0.
IP_Port empty;
empty.ip.family.value = 0;
empty.ip.ip.v6.uint64[0] = 0;
empty.ip.ip.v6.uint64[1] = 0;
empty.port = 0;

*ip_port = empty;
}

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

Expand All @@ -1641,6 +1649,7 @@ int pack_ip_port(const Logger *logger, uint8_t *data, uint16_t length, const IP_
const uint32_t size = bin_pack_obj_size(bin_pack_ip_port_handler, ip_port, logger);

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

Expand Down
2 changes: 1 addition & 1 deletion toxcore/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ non_null()
void ip_reset(IP *ip);
/** nulls out ip_port */
non_null()
void ipport_reset(IP_Port *ipport);
void ipport_reset(IP_Port *ip_port);
/** nulls out ip, sets family according to flag */
non_null()
void ip_init(IP *ip, bool ipv6enabled);
Expand Down
10 changes: 6 additions & 4 deletions toxcore/onion_announce.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "onion.h"
#include "shared_key_cache.h"
#include "timed_auth.h"
#include "util.h"

#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT

Expand Down Expand Up @@ -463,10 +464,11 @@ static int handle_announce_request_common(
return 1;
}

const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source);
uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source)];
const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT;
uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT];
memcpy(ping_id_data, packet_public_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, source, sizeof(*source));
const int packed_len = pack_ip_port(onion_a->log, &ping_id_data[CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, source);
memzero(&ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);

const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;

Expand Down Expand Up @@ -510,7 +512,7 @@ static int handle_announce_request_common(
int nodes_length = 0;

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

if (nodes_length <= 0) {
Expand Down
15 changes: 8 additions & 7 deletions toxcore/onion_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,11 +576,12 @@ non_null()
static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,
uint32_t path_num, uint64_t *sendback)
{
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
memcpy(data, &num, sizeof(uint32_t));
memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, ip_port, sizeof(IP_Port));
memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE);
const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port);
memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t));
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));

if (*sendback == 0) {
Expand All @@ -607,15 +608,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
{
uint64_t sback;
memcpy(&sback, sendback, sizeof(uint64_t));
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];

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

memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));

uint32_t num;
memcpy(&num, data, sizeof(uint32_t));
Expand Down
13 changes: 9 additions & 4 deletions toxcore/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "ping_array.h"
#include "util.h"

#define PING_NUM_MAX 512

Expand All @@ -30,6 +32,7 @@

struct Ping {
const Mono_Time *mono_time;
const Logger *log;
const Random *rng;
DHT *dht;

Expand All @@ -40,7 +43,7 @@ struct Ping {

#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT)

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

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

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

if (!ipport_equal(&ipp, source)) {
return 1;
Expand Down Expand Up @@ -331,7 +335,7 @@ void ping_iterate(Ping *ping)
}
}

Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht)
{
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));

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

ping->mono_time = mono_time;
ping->log = log;
ping->rng = rng;
ping->dht = dht;
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
Expand Down
2 changes: 1 addition & 1 deletion toxcore/ping.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
typedef struct Ping Ping;

non_null()
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht);
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Logger *log, const Random *rng, DHT *dht);

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

0 comments on commit c93ccdd

Please sign in to comment.