Skip to content

Commit 8470fa4

Browse files
soopelDawidWesierski4
authored andcommitted
Harden udp recvmsg payload bounds
1 parent 6248abe commit 8470fa4

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

lib/src/udp/udp_main.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,11 +1002,32 @@ static ssize_t udp_rx_msg_dequeue(struct mudp_impl* s, struct msghdr* msg, int f
10021002
s->stat_pkt_dequeue++;
10031003

10041004
struct mt_udp_hdr* hdr = rte_pktmbuf_mtod(pkt, struct mt_udp_hdr*);
1005+
const size_t hdr_len = sizeof(*hdr);
1006+
uint32_t pkt_len = rte_pktmbuf_pkt_len(pkt);
1007+
1008+
if (pkt_len < hdr_len) {
1009+
err("%s(%d), invalid packet len %u < header len %zu\n", __func__, idx, pkt_len,
1010+
hdr_len);
1011+
rte_pktmbuf_free(pkt);
1012+
errno = EBADMSG;
1013+
return -1;
1014+
}
1015+
10051016
struct rte_udp_hdr* udp = &hdr->udp;
1006-
void* payload = &udp[1];
10071017
struct rte_ipv4_hdr* ipv4 = &hdr->ipv4;
1008-
ssize_t payload_len = ntohs(udp->dgram_len) - sizeof(*udp);
1009-
dbg("%s(%d), payload_len %" PRId64 " bytes\n", __func__, idx, payload_len);
1018+
ssize_t payload_len = (ssize_t)ntohs(udp->dgram_len) - sizeof(*udp);
1019+
ssize_t payload_cap = (ssize_t)pkt_len - hdr_len;
1020+
1021+
if (payload_len < 0 || payload_len > payload_cap) {
1022+
err("%s(%d), invalid payload len %" PRId64 " (cap %" PRId64 ")\n", __func__, idx,
1023+
(int64_t)payload_len, (int64_t)payload_cap);
1024+
rte_pktmbuf_free(pkt);
1025+
errno = EBADMSG;
1026+
return -1;
1027+
}
1028+
1029+
uint8_t* payload = rte_pktmbuf_mtod_offset(pkt, uint8_t*, hdr_len);
1030+
dbg("%s(%d), payload_len %" PRId64 " bytes\n", __func__, idx, (int64_t)payload_len);
10101031

10111032
msg->msg_flags = 0;
10121033

@@ -1030,19 +1051,21 @@ static ssize_t udp_rx_msg_dequeue(struct mudp_impl* s, struct msghdr* msg, int f
10301051
}
10311052

10321053
if (msg->msg_iov) { /* Vector of data */
1054+
ssize_t remaining = payload_len;
10331055
for (int i = 0; i < msg->msg_iovlen; i++) {
1034-
size_t clen = RTE_MIN(msg->msg_iov[i].iov_len, payload_len);
1056+
size_t clen = RTE_MIN(msg->msg_iov[i].iov_len, (size_t)remaining);
10351057
rte_memcpy(msg->msg_iov[i].iov_base, payload, clen);
1036-
payload_len -= clen;
1058+
remaining -= (ssize_t)clen;
10371059
payload += clen;
10381060
copied += clen;
1039-
if (payload_len <= 0) break;
1061+
if (remaining <= 0) break;
10401062
}
1063+
payload_len = remaining;
10411064
s->stat_pkt_deliver++;
10421065
}
10431066

10441067
if (payload_len)
1045-
warn("%s(%d), %" PRIu64 " bytes not copied \n", __func__, idx, payload_len);
1068+
warn("%s(%d), %" PRId64 " bytes not copied \n", __func__, idx, (int64_t)payload_len);
10461069

10471070
rte_pktmbuf_free(pkt);
10481071
dbg("%s(%d), copied %" PRId64 " bytes, flags %d\n", __func__, idx, copied, flags);

0 commit comments

Comments
 (0)