Enforced absolute maximum read size in GDB server
This commit is contained in:
@@ -175,10 +175,12 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> Connection::read(
|
std::vector<unsigned char> Connection::read(
|
||||||
size_t bytes,
|
std::optional<std::size_t> bytes,
|
||||||
bool interruptible,
|
bool interruptible,
|
||||||
std::optional<std::chrono::milliseconds> timeout
|
std::optional<std::chrono::milliseconds> timeout
|
||||||
) {
|
) {
|
||||||
|
assert(!bytes.has_value() || *bytes <= Connection::ABSOLUTE_MAXIMUM_PACKET_READ_SIZE);
|
||||||
|
|
||||||
auto output = std::vector<unsigned char>();
|
auto output = std::vector<unsigned char>();
|
||||||
constexpr size_t bufferSize = 1024;
|
constexpr size_t bufferSize = 1024;
|
||||||
std::array<unsigned char, bufferSize> buffer = {};
|
std::array<unsigned char, bufferSize> buffer = {};
|
||||||
@@ -209,7 +211,7 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
throw DebugServerInterrupted();
|
throw DebugServerInterrupted();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytesToRead = (bytes > bufferSize || bytes == 0) ? bufferSize : bytes;
|
size_t bytesToRead = (!bytes.has_value() || bytes > bufferSize) ? bufferSize : *bytes;
|
||||||
while (
|
while (
|
||||||
bytesToRead > 0
|
bytesToRead > 0
|
||||||
&& (bytesRead = ::read(this->socketFileDescriptor.value(), buffer.data(), bytesToRead)) > 0
|
&& (bytesRead = ::read(this->socketFileDescriptor.value(), buffer.data(), bytesToRead)) > 0
|
||||||
@@ -221,7 +223,19 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesToRead = ((bytes - output.size()) > bufferSize || bytes == 0) ? bufferSize : (bytes - output.size());
|
if (output.size() >= Connection::ABSOLUTE_MAXIMUM_PACKET_READ_SIZE) {
|
||||||
|
/*
|
||||||
|
* We're receiving far too much data from GDB - something is definitely not right here.
|
||||||
|
* This could be an attempted DoS attack.
|
||||||
|
*
|
||||||
|
* Assume the worst and throw an exception. The connection will be killed as a result.
|
||||||
|
*/
|
||||||
|
throw ClientCommunicationError("GDB client attempted to send too much data");
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesToRead = (!bytes.has_value() || (*bytes - output.size()) > bufferSize)
|
||||||
|
? bufferSize
|
||||||
|
: (*bytes - output.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.empty()) {
|
if (output.empty()) {
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
class Connection
|
class Connection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
|
* GDB should never attempt to send more than this in a single instance.
|
||||||
|
*
|
||||||
|
* In the event that it does, we assume the worst and kill the connection.
|
||||||
|
*/
|
||||||
|
static constexpr auto ABSOLUTE_MAXIMUM_PACKET_READ_SIZE = 5120;
|
||||||
|
|
||||||
explicit Connection(int serverSocketFileDescriptor, EventFdNotifier& interruptEventNotifier);
|
explicit Connection(int serverSocketFileDescriptor, EventFdNotifier& interruptEventNotifier);
|
||||||
|
|
||||||
Connection() = delete;
|
Connection() = delete;
|
||||||
@@ -67,15 +74,10 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
*/
|
*/
|
||||||
void writePacket(const ResponsePackets::ResponsePacket& packet);
|
void writePacket(const ResponsePackets::ResponsePacket& packet);
|
||||||
|
|
||||||
[[nodiscard]] int getMaxPacketSize() const {
|
|
||||||
return this->maxPacketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<int> socketFileDescriptor;
|
std::optional<int> socketFileDescriptor;
|
||||||
|
|
||||||
struct sockaddr_in socketAddress = {};
|
struct sockaddr_in socketAddress = {};
|
||||||
int maxPacketSize = 1024;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interruptEventNotifier (instance of EventFdNotifier) allows us to interrupt blocking I/O calls on this
|
* The interruptEventNotifier (instance of EventFdNotifier) allows us to interrupt blocking I/O calls on this
|
||||||
@@ -123,7 +125,7 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
std::vector<unsigned char> read(
|
std::vector<unsigned char> read(
|
||||||
std::size_t bytes = 0,
|
std::optional<std::size_t> bytes = std::nullopt,
|
||||||
bool interruptible = true,
|
bool interruptible = true,
|
||||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "DebugSession.hpp"
|
#include "DebugSession.hpp"
|
||||||
|
|
||||||
#include "src/Logger/Logger.hpp"
|
|
||||||
#include "src/EventManager/EventManager.hpp"
|
#include "src/EventManager/EventManager.hpp"
|
||||||
|
|
||||||
namespace Bloom::DebugServer::Gdb
|
namespace Bloom::DebugServer::Gdb
|
||||||
@@ -15,7 +14,7 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
, gdbTargetDescriptor(targetDescriptor)
|
, gdbTargetDescriptor(targetDescriptor)
|
||||||
{
|
{
|
||||||
this->supportedFeatures.insert({
|
this->supportedFeatures.insert({
|
||||||
Feature::PACKET_SIZE, std::to_string(this->connection.getMaxPacketSize())
|
Feature::PACKET_SIZE, std::to_string(Connection::ABSOLUTE_MAXIMUM_PACKET_READ_SIZE)
|
||||||
});
|
});
|
||||||
|
|
||||||
EventManager::triggerEvent(std::make_shared<Events::DebugSessionStarted>());
|
EventManager::triggerEvent(std::make_shared<Events::DebugSessionStarted>());
|
||||||
|
|||||||
Reference in New Issue
Block a user