From 875df4e784530430b13e77f4c37e37466db4ef3c Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 3 May 2026 17:00:15 +0200 Subject: ipcpd: Reject outbound packets on eth AF_PACKET under `tc netem duplicate`, produces an extra PACKET_OUTGOING frame at the source that receive path didn't reject. Read with recvfrom(2) and discard frames whose sll_pkttype is PACKET_OUTGOING. Restores the dst-MAC check body (defense in depth, also bumps n_bad_id) so any frame addressed neither to us nor the broadcast MAC is dropped before flow lookup. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/ipcpd/eth/eth.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/ipcpd') diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c index 7981ade5..10a8b338 100644 --- a/src/ipcpd/eth/eth.c +++ b/src/ipcpd/eth/eth.c @@ -1117,6 +1117,10 @@ static void * eth_ipcp_packet_reader(void * o) struct ssm_pk_buff * spb; fd_set fds; int frame_len; +#endif +#if defined(HAVE_RAW_SOCKETS) + struct sockaddr_ll src; + socklen_t slen; #endif size_t eth_len; uint8_t hcs; @@ -1168,8 +1172,10 @@ static void * eth_ipcp_packet_reader(void * o) FETCH_ADD_RELAXED(ð_data.stat.n_buf_f, 1); continue; } - frame_len = recv(eth_data.s_fd, buf, - ETH_MTU + ETH_HEADER_TOT_SIZE, 0); + slen = sizeof(src); + frame_len = recvfrom(eth_data.s_fd, buf, + ETH_MTU + ETH_HEADER_TOT_SIZE, 0, + (struct sockaddr *) &src, &slen); #endif if (frame_len <= 0) { log_dbg("Failed to receive frame."); @@ -1179,6 +1185,12 @@ static void * eth_ipcp_packet_reader(void * o) } #endif +#if defined(HAVE_RAW_SOCKETS) + /* Drop our own egress. */ + if (src.sll_pkttype == PACKET_OUTGOING) + goto fail_frame; +#endif + #if defined(HAVE_BPF) && !defined(HAVE_NETMAP) e_frame = (struct eth_frame *) (buf + ((struct bpf_hdr *) buf)->bh_hdrlen); @@ -1196,6 +1208,8 @@ static void * eth_ipcp_packet_reader(void * o) e_frame->dst_hwaddr, MAC_SIZE) && memcmp(br_addr, e_frame->dst_hwaddr, MAC_SIZE)) { + FETCH_ADD_RELAXED(ð_data.stat.n_bad_id, 1); + goto fail_frame; } #endif length = ntohs(e_frame->length); -- cgit v1.2.3