Skip to content

Commit b9515af

Browse files
author
Walid Nejmi
committed
Validate offload block request lengths
Check the received and declared payload sizes before processing block requests and add defensive bounds checks to block request handling. The payload offset is derived with offsetof() rather than sizeof(), since the message struct ends in a flexible-style array and sizeof() may include trailing padding. Signed-off-by: Walid Nejmi <wnejmi@bloomberg.net>
1 parent 442406b commit b9515af

2 files changed

Lines changed: 37 additions & 5 deletions

File tree

db/handle_buf.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,24 @@ int handle_buf_block_offload(struct dbenv *dbenv, uint8_t *p_buf,
879879
const uint8_t *p_buf_end, int debug,
880880
char *frommach, unsigned long long rqid)
881881
{
882-
int length = p_buf_end - p_buf;
882+
if (p_buf == NULL || p_buf_end == NULL || p_buf_end < p_buf) {
883+
logmsg(LOGMSG_ERROR, "%s: invalid block request buffer\n", __func__);
884+
return ERR_INTERNAL;
885+
}
886+
887+
ptrdiff_t length = p_buf_end - p_buf;
888+
if (length > MAX_BUFFER_SIZE) {
889+
logmsg(LOGMSG_ERROR, "%s: invalid block request length %td\n", __func__, length);
890+
return ERR_INTERNAL;
891+
}
892+
883893
uint8_t *p_bigbuf = get_bigbuf();
884-
memcpy(p_bigbuf, p_buf, length);
894+
if (p_bigbuf == NULL) {
895+
logmsg(LOGMSG_ERROR, "%s: unable to acquire block request buffer\n", __func__);
896+
return ERR_INTERNAL;
897+
}
898+
899+
memcpy(p_bigbuf, p_buf, (size_t)length);
885900
if (length < EXTRA_RESPONSE_ROOM)
886901
length = EXTRA_RESPONSE_ROOM;
887902
int rc = handle_buf_main(dbenv, NULL, p_bigbuf, p_bigbuf + length, debug,

db/osqlcomm.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3642,11 +3642,28 @@ static void net_block_req(void *hndl, void *uptr, char *fromhost,
36423642
struct interned_string *frominterned, int usertype,
36433643
void *dtap, int dtalen, uint8_t is_tcp)
36443644
{
3645+
/* The payload starts at 'data'; sizeof() may include trailing padding. */
3646+
const size_t header_len = offsetof(net_block_msg_t, data);
3647+
3648+
/* Validate the received message before reading any of its fields. */
3649+
if (dtap == NULL || dtalen < 0 || (size_t)dtalen < header_len) {
3650+
logmsg(LOGMSG_ERROR, "%s: invalid block request message length %d\n", __func__, dtalen);
3651+
return;
3652+
}
36453653

36463654
net_block_msg_t *net_msg = dtap;
3647-
handle_buf_block_offload(thedb, (uint8_t *)net_msg->data,
3648-
(uint8_t *)net_msg->data + net_msg->datalen, 0,
3649-
fromhost, net_msg->rqid);
3655+
int datalen = net_msg->datalen;
3656+
size_t available = (size_t)dtalen - header_len;
3657+
3658+
/* The declared payload length has to fit in what was actually received
3659+
* and in the buffer it will be copied into. */
3660+
if (datalen < 0 || (size_t)datalen > available || (size_t)datalen > MAX_BUFFER_SIZE) {
3661+
logmsg(LOGMSG_ERROR, "%s: invalid block request payload length %d\n", __func__, datalen);
3662+
return;
3663+
}
3664+
3665+
handle_buf_block_offload(thedb, (uint8_t *)net_msg->data, (uint8_t *)net_msg->data + datalen, 0, fromhost,
3666+
net_msg->rqid);
36503667
}
36513668

36523669
int offload_comm_send_blockreply(char *host, unsigned long long rqid, void *buf,

0 commit comments

Comments
 (0)