blob: 005d0fc4352da6708599dfc7f6f0c932fdb612c2 [file] [log] [blame]
From b30a0b2a83e3a0e24a76d956c8b8051cbdea7947 Mon Sep 17 00:00:00 2001
From: Andrzej Ostruszka <amo@semihalf.com>
Date: Thu, 4 Nov 2021 10:05:05 +0000
Subject: [PATCH] More robust checks for packet reception
In ChromeOS dhcpcd is being used with "fortified" string functions and
there are being observed crashes in arp_read() (memcpy related). This
is most probably from bpf_read() (arp_packet() seems to be clean) so
let's rework checks there to be more robust (maybe even paranoid).
---
src/arp.c | 2 +-
src/dhcp.c | 2 +-
src/if-linux.c | 43 ++++++++++++++++++++++++-------------------
3 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/src/arp.c b/src/arp.c
index 601b0a64..a323a9cc 100644
--- a/src/arp.c
+++ b/src/arp.c
@@ -235,7 +235,7 @@ arp_read(void *arg)
while (!(state->bpf_flags & BPF_EOF)) {
bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf),
&state->bpf_flags);
- if (bytes == -1) {
+ if (bytes < 0) {
logerr("%s: %s", __func__, ifp->name);
arp_close(ifp);
break;
diff --git a/src/dhcp.c b/src/dhcp.c
index ac339a6a..cedb950b 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -3842,7 +3842,7 @@ dhcp_readpacket(void *arg)
while (!(state->bpf_flags & BPF_EOF)) {
bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf),
&state->bpf_flags);
- if (bytes == -1) {
+ if (bytes < 0) {
if (state->state != DHS_NONE) {
logerr("%s: %s", __func__, ifp->name);
dhcp_close(ifp);
diff --git a/src/if-linux.c b/src/if-linux.c
index d0f982e1..a7998442 100644
--- a/src/if-linux.c
+++ b/src/if-linux.c
@@ -1418,31 +1418,36 @@ bpf_read(struct interface *ifp, int s, void *data, size_t len,
#endif
bytes = recvmsg(s, &msg, 0);
- if (bytes == -1)
- return -1;
+ if (bytes <= 0)
+ return bytes;
+
+ if (msg.msg_flags != 0)
+ logwarn("%s: non-zero recv flags = %d", __func__, msg.msg_flags);
*flags |= BPF_EOF; /* We only ever read one packet. */
*flags &= ~BPF_PARTIALCSUM;
- if (bytes) {
- ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
- bytes -= fl;
- if ((size_t)bytes > len)
- bytes = (ssize_t)len;
- memcpy(data, state->buffer + fl, (size_t)bytes);
+ ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
+ if (bytes < fl) {
+ logwarn("%s: packet too short = %zd", __func__, bytes);
+ return 0;
+ }
+ bytes -= fl;
+ if ((size_t)bytes > len)
+ bytes = (ssize_t)len;
+ memcpy(data, state->buffer + fl, (size_t)bytes);
#ifdef PACKET_AUXDATA
- for (cmsg = CMSG_FIRSTHDR(&msg);
- cmsg;
- cmsg = CMSG_NXTHDR(&msg, cmsg))
- {
- if (cmsg->cmsg_level == SOL_PACKET &&
- cmsg->cmsg_type == PACKET_AUXDATA) {
- aux = (void *)CMSG_DATA(cmsg);
- if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
- *flags |= BPF_PARTIALCSUM;
- }
+ for (cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_PACKET &&
+ cmsg->cmsg_type == PACKET_AUXDATA) {
+ aux = (void *)CMSG_DATA(cmsg);
+ if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
+ *flags |= BPF_PARTIALCSUM;
}
-#endif
}
+#endif
return bytes;
}
--
2.34.0.rc0.344.g81b53c2807-goog