NetBSD Problem Report #60638

From e@80x24.org  Mon Aug 24 20:35:23 2026
Return-Path: <e@80x24.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits)
	 client-signature RSA-PSS (2048 bits))
	(Client CN "mail.netbsd.org", Issuer "YR2" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id D31F91A923B
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 24 Aug 2026 20:35:22 +0000 (UTC)
Message-Id: <20260824202951.M404824@dcvr>
Date: Mon, 24 Aug 2026 20:29:51 +0000
From: Eric Wong <e@80x24.org>
To: gnats-bugs@netbsd.org
Subject: AF_UNIX SOCK_SEQPACKET recvmsg truncates messages sent w/ MSG_EOR
X-Send-Pr-Version: 3.95
X-From4GNATS: "Eric Wong via gnats" <gnats-admin@NetBSD.org>

>Number:         60638
>Category:       kern
>Synopsis:       AF_UNIX SOCK_SEQPACKET recvmsg truncates messages sent w/ MSG_EOR
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 24 20:40:00 +0000 2026
>Originator:     Eric Wong <e@80x24.org>
>Release:        NetBSD 11.0
>Organization:
	self
>Environment:
System: NetBSD netbsd110-amd64 11.0 NetBSD 11.0 (GENERIC) #0: Thu Jul 30 15:23:12 UTC 2026 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:
	AF_UNIX SOCK_SEQPACKET messages sent with MSG_EOR are truncated
	upon recvmsg small values under 2K even when receiver supplies
	adequately large buffers.
	-
	While I have workaround for sending large buffers by putting the
	payload in an extra FD via SCM_RIGHTS, 1972 bytes seems like an
	unusually small value for a buffer (smaller than _SC_PAGE_SIZE
	or PIPE_BUF) and the workaround costs extra FDs.
	-
	The problem doesn't appear to manifest w/o MSG_EOR, but MSG_EOR
	seems like the right thing to demarcate individual messages
	when using SOCK_SEQPACKET with local Unix sockets.
	-
	OpenBSD fixed a similar issue several years ago (see code comments).
	MSG_EOR seems required for my code to work with FreeBSD 15.x+ (it
	worked fine w/o MSG_EOR in FreeBSD <=14.x).  I've used Linux with
	and without MSG_EOR since 2013 for AF_UNIX+SOCK_SEQPACKET and haven't
	noticed unusually small truncation lengths.
>How-To-Repeat:
/*
 * compile + run following code:
 *	cc -o /path/to/run /this/file.c -Wall && /path/to/run
 *
 * Using sendmsg(..., MSG_EOR) on an AF_UNIX + SOCK_SEQPACKET socket
 * appears to cause the recvmsg() caller to receive truncated data
 * (and set MSG_TRUNC) on NetBSD 11.0.
 *
 * OpenBSD had a similar bug fixed in 2023:
 * <https://marc.info/?i=fac37d6e4b2996a6@cvs.openbsd.org>
 *
 * Feel free to use this as test case under what ever license fits
 * best (CC-0, MIT, BSD-[23], ISC).
 * I extracted this test case from a codebase which I've been
 * using on both FreeBSD 12.x+ and Linux since 2021.
 * I normally send data between processes, but this truncation
 * happens within the same process, too.
 */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <err.h>

#define NSEND 2048
#define NRECV (4096 * 33)

// the most FDs I ever intend to send:
#define SEND_FD_CAPA 10
#define SEND_FD_SPACE (SEND_FD_CAPA * sizeof(int))
union my_cmsg {
	struct cmsghdr hdr;
	char pad[sizeof(struct cmsghdr) + 16 + SEND_FD_SPACE];
};

static void do_sendmsg(int fd)
{
	/*
	 * FreeBSD 15.x seems to require MSG_EOR nowadays for proper
	 * message boundaries (didn't need it before 14.x).  Linux
	 * doesn't seem to care...
	 */
	int sflags = MSG_EOR;

	/*
	 * I normally have several FDs to send, but the
	 * discrepancy happens even with nfds == 0
	 */
	int i, nfds = 4;
	struct msghdr msg = { 0 };
	union my_cmsg cmsg = { 0 };
	char to_send[NSEND];
	struct iovec iov;
	int *fdp;
	ssize_t sent;

	memset(to_send, 'a', sizeof(to_send));
	to_send[NSEND - 1] = 'b'; // for kdump || strace output

	iov.iov_base = to_send;
	iov.iov_len = sizeof(to_send);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = &cmsg.hdr;
	msg.msg_controllen = CMSG_SPACE(nfds * sizeof(int));
	cmsg.hdr.cmsg_level = SOL_SOCKET;
	cmsg.hdr.cmsg_type = SCM_RIGHTS;
	cmsg.hdr.cmsg_len = CMSG_LEN(nfds * sizeof(int));
	fdp = (int *)CMSG_DATA(&cmsg.hdr);
	for (i = 0; i < nfds; i++)
		*fdp++ = i;
	sent = sendmsg(fd, &msg, sflags);
	fprintf(stderr, "%d sent: %zd of %zu\n",
		(int)getpid(), sent, iov.iov_len);
}

static void do_recvmsg(int fd)
{
	union my_cmsg cmsg = { 0 };
	struct msghdr msg = { 0 };
	struct iovec iov;
	ssize_t r;
	char recvbuf[NRECV];

	iov.iov_base = recvbuf;
	iov.iov_len = sizeof(recvbuf);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = &cmsg.hdr;
	msg.msg_controllen = CMSG_SPACE(SEND_FD_SPACE);

	r = recvmsg(fd, &msg, 0);
	/*
	 * FreeBSD and Linux receive everything sent, here, but
	 * NetBSD only gets 1972 bytes and sets MSG_TRUNC here:
	 */
	fprintf(stderr, "%d recv: %zd of %zu "
			"EOR=%d TRUNC=%d CTRUNC=%d OOB=%d\n",
			getpid(), r, iov.iov_len,
			msg.msg_flags & MSG_EOR,
			msg.msg_flags & MSG_TRUNC,
			msg.msg_flags & MSG_CTRUNC,
			msg.msg_flags & MSG_OOB);
	if (r > 0 && cmsg.hdr.cmsg_level == SOL_SOCKET &&
			cmsg.hdr.cmsg_type == SCM_RIGHTS) {
		size_t len = cmsg.hdr.cmsg_len;
		int *fdp = (int *)CMSG_DATA(&cmsg.hdr);
		size_t i;
		for (i = 0; CMSG_LEN((i + 1) * sizeof(int)) <= len; i++)
			fprintf(stderr, "%d recv fd=%d\n",
				(int)getpid(), *fdp++);
	}

	if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC))
		errx(EXIT_FAILURE, "truncated (BAD)");
	else
		warnx("no truncation (GOOD)");
}

int main(void)
{
	int fds[2];
	int rc = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds);
	assert(rc == 0);

	do_sendmsg(fds[0]);
	do_recvmsg(fds[1]);

	return 0;
}
>Fix:
	<how to correct or work around the problem, if known (multiple lines)>

>Unformatted:
 	<Please check that the above is correct for the bug being reported,>
 	<and append source date of snapshot, if applicable (one line).>

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.