Skip to content

Commit eae097b

Browse files
authored
Merge pull request #15 from CHERIoT-Platform/hlefeuvre/fix-dhcp
Three bug fixes in the TCP/IP stack.
2 parents 0085be2 + 551ef0e commit eae097b

File tree

3 files changed

+74
-27
lines changed

3 files changed

+74
-27
lines changed

lib/firewall/firewall.cc

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@
1212
#include <timeout.hh>
1313
#include <vector>
1414

15+
namespace
16+
{
17+
// TODO These should probably be in their own library.
18+
uint16_t constexpr ntohs(uint16_t value)
19+
{
20+
return
21+
#ifdef __LITTLE_ENDIAN__
22+
__builtin_bswap16(value)
23+
#else
24+
value
25+
#endif
26+
;
27+
}
28+
uint16_t constexpr htons(uint16_t value)
29+
{
30+
return
31+
#ifdef __LITTLE_ENDIAN__
32+
__builtin_bswap16(value)
33+
#else
34+
value
35+
#endif
36+
;
37+
}
38+
} // namespace
39+
1540
namespace
1641
{
1742
using Debug = ConditionalDebug<false, "Firewall">;
@@ -85,10 +110,13 @@ namespace
85110
UDP = 17,
86111
};
87112

113+
static constexpr const uint16_t DhcpServerPort = 67;
114+
static constexpr const uint16_t DhcpClientPort = 68;
115+
88116
struct IPv4Header
89117
{
90118
/**
91-
* Verson is in the low 4 bits, header length is in the high 4 bits.
119+
* Version is in the low 4 bits, header length is in the high 4 bits.
92120
*/
93121
uint8_t versionAndHeaderLength;
94122
/**
@@ -286,6 +314,23 @@ namespace
286314
}
287315
};
288316

317+
bool is_dhcp_reply(enum IPProtocolNumber protocol,
318+
bool isIngress,
319+
uint16_t remotePort,
320+
uint16_t localPort)
321+
{
322+
// A DHCP reply is an ingress UDP packet whose remote port
323+
// matches the DHCP server port, and whose local port matches
324+
// the DHCP client port.
325+
if (isIngress && (protocol == IPProtocolNumber::UDP) &&
326+
(remotePort == htons(DhcpServerPort)) &&
327+
(localPort == htons(DhcpClientPort)))
328+
{
329+
return true;
330+
}
331+
return false;
332+
}
333+
289334
uint32_t dnsServerAddress;
290335
_Atomic(uint32_t) dnsIsPermitted;
291336

@@ -304,19 +349,13 @@ namespace
304349
auto *ipv4Header = reinterpret_cast<const IPv4Header *>(data);
305350
switch (ipv4Header->protocol)
306351
{
307-
// Drop all packets with unknown protocol types.
352+
// Drop all packets with unknown IP protocol types.
308353
default:
309354
Debug::log("Dropping IPv4 packet with unknown protocol {}",
310355
ipv4Header->protocol);
311356
return false;
312357
case IPProtocolNumber::UDP:
313-
// If we haven't finished doing DHCP, permit all UDP packets
314-
// (we don't know the address of the DHCP server yet, so
315-
// IP-based filtering is not going to be reliable).
316-
if (__predict_false(dnsServerAddress == 0))
317-
{
318-
return true;
319-
}
358+
320359
// Permit DNS requests during a DNS query.
321360
if (dnsIsPermitted > 0)
322361
{
@@ -356,6 +395,7 @@ namespace
356395
uint32_t endpoint = ipv4Header->*remoteAddress;
357396
uint16_t localPortNumber = tcpudpHeader->*localPort;
358397
uint16_t remotePortNumber = tcpudpHeader->*remotePort;
398+
bool isIngress = (remoteAddress == &IPv4Header::sourceAddress);
359399
if (EndpointsTable<uint32_t>::instance().is_endpoint_permitted(
360400
ipv4Header->protocol,
361401
endpoint,
@@ -364,15 +404,21 @@ namespace
364404
{
365405
Debug::log("Permitting {} {} {}.{}.{}.{}",
366406
ipv4Header->protocol,
367-
remoteAddress == &IPv4Header::destinationAddress
368-
? "to"
369-
: "from",
407+
isIngress ? "from" : "to",
370408
static_cast<int>(endpoint) & 0xff,
371409
static_cast<int>(endpoint >> 8) & 0xff,
372410
static_cast<int>(endpoint >> 16) & 0xff,
373411
static_cast<int>(endpoint >> 24) & 0xff);
374412
return true;
375413
}
414+
// Permit DHCP replies
415+
if (is_dhcp_reply(ipv4Header->protocol,
416+
isIngress,
417+
remotePortNumber,
418+
localPortNumber))
419+
{
420+
return true;
421+
}
376422
return false;
377423
}
378424
break;

lib/sntp/xmake.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ compartment("SNTP")
1111
add_deps("freestanding", "NetAPI")
1212
add_files("sntp.cc")
1313
add_includedirs(".", "../../include", "../../third_party/coreSNTP/source/include")
14-
add_defines("CHERIOT_CUSTOM_DEFAULT_MALLOC_CAPABILITY")
14+
add_cflags("-DCHERIOT_CUSTOM_DEFAULT_MALLOC_CAPABILITY")
1515
add_files("../../third_party/coreSNTP/source/core_sntp_client.c",
1616
"../../third_party/coreSNTP/source/core_sntp_serializer.c")

lib/tcpip/BufferManagement.cc

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,19 @@ using Debug = ConditionalDebug<false, "Buffer management">;
1616
// may thus make sense to give it its own quota. We may want to expose this as
1717
// a build system configuration option at some point.
1818
#define USE_DEDICATED_BUFFERMANAGER_POOL false
19-
// Size of the buffer manager allocator quota. Only relevant if
20-
// USE_DEDICATED_BUFFERMANAGER_POOL is enabled.
21-
#define BUFFER_MANAGER_QUOTA \
22-
(ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * \
23-
(ipconfigTCP_MSS + ipBUFFER_PADDING))
2419

2520
#if USE_DEDICATED_BUFFERMANAGER_POOL
21+
// Size of the buffer manager allocator quota.
22+
# define BM_MALLOC_QUOTA \
23+
(ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * \
24+
(ipconfigTCP_MSS + ipBUFFER_PADDING))
25+
// Separate allocator capability for the buffer manager.
2626
DECLARE_AND_DEFINE_ALLOCATOR_CAPABILITY(BufferManagementMallocQuota,
27-
BUFFER_MANAGER_QUOTA);
28-
# define BM_MALLOC_QUOTA STATIC_SEALED_VALUE(BufferManagementMallocQuota)
27+
BM_MALLOC_QUOTA);
28+
# define BM_MALLOC_CAPABILITY \
29+
STATIC_SEALED_VALUE(BufferManagementMallocQuota)
2930
#else
30-
# define BM_MALLOC_QUOTA MALLOC_CAPABILITY
31+
# define BM_MALLOC_CAPABILITY MALLOC_CAPABILITY
3132
#endif
3233

3334
constexpr size_t MinimumBufferSize =
@@ -71,18 +72,18 @@ pxGetNetworkBufferWithDescriptor(size_t xRequestedSizeBytes,
7172

7273
// TODO we likely want to pre-allocate (or re-use) the descriptors at
7374
// some point
74-
auto deleter = [=](void *ptr) { heap_free(BM_MALLOC_QUOTA, ptr); };
75+
auto deleter = [=](void *ptr) { heap_free(BM_MALLOC_CAPABILITY, ptr); };
7576
std::unique_ptr<NetworkBufferDescriptor_t, decltype(deleter)> descriptor{
76-
static_cast<NetworkBufferDescriptor_t *>(
77-
heap_allocate(&t, BM_MALLOC_QUOTA, sizeof(NetworkBufferDescriptor_t))),
77+
static_cast<NetworkBufferDescriptor_t *>(heap_allocate(
78+
&t, BM_MALLOC_CAPABILITY, sizeof(NetworkBufferDescriptor_t))),
7879
deleter};
7980
if (descriptor == nullptr)
8081
{
8182
Debug::log("Failed to allocate descriptor");
8283
return nullptr;
8384
}
8485
auto *buffer = static_cast<uint8_t *>(heap_allocate(
85-
&t, BM_MALLOC_QUOTA, xRequestedSizeBytes + ipBUFFER_PADDING));
86+
&t, BM_MALLOC_CAPABILITY, xRequestedSizeBytes + ipBUFFER_PADDING));
8687
if (buffer == nullptr)
8788
{
8889
Debug::log("Failed to allocate {} byte buffer", xRequestedSizeBytes);
@@ -124,8 +125,8 @@ void vReleaseNetworkBufferAndDescriptor(
124125
networkBuffer,
125126
bufferWithoutOffset);
126127

127-
int ret = heap_free(MALLOC_CAPABILITY, bufferWithoutOffset);
128-
ret |= heap_free(MALLOC_CAPABILITY, networkBuffer);
128+
int ret = heap_free(BM_MALLOC_CAPABILITY, bufferWithoutOffset);
129+
ret |= heap_free(BM_MALLOC_CAPABILITY, networkBuffer);
129130

130131
// Failure is not supposed to happen unless we have a bug here
131132
// or in FreeRTOS.

0 commit comments

Comments
 (0)