git: 48a55bbfe95b - main - unix: change error code for recvmsg() failed due to RLIMIT_NOFILE

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Wed, 29 Jun 2022 16:43:14 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=48a55bbfe95bc7b32d37673839edc2f365ffc028

commit 48a55bbfe95bc7b32d37673839edc2f365ffc028
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2022-06-29 16:42:58 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2022-06-29 16:42:58 +0000

    unix: change error code for recvmsg() failed due to RLIMIT_NOFILE
    
    Instead of returning EMSGSIZE pass the error code from fdallocn() directly
    to userland.  That would be EMFILE, which makes much more sense.  This
    error code is not listed in the specification[1], but the specification
    doesn't cover such edge case at all.  Meanwhile the specification lists
    EMSGSIZE as the error code for invalid value of msg_iovlen, and FreeBSD
    follows that, see sys_recmsg().  Differentiating these two cases will make
    a developer/admin life much easier when debugging.
    
    [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
    
    Reviewed by:            markj
    Differential revision:  https://reviews.freebsd.org/D35640
---
 lib/libc/sys/recv.2               | 19 +++++++++++++++----
 sys/kern/uipc_usrreq.c            |  3 +--
 tests/sys/kern/unix_passfd_test.c |  4 ++--
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2
index 46e0cf8163dd..1f3bf531c3e7 100644
--- a/lib/libc/sys/recv.2
+++ b/lib/libc/sys/recv.2
@@ -28,7 +28,7 @@
 .\"     @(#)recv.2	8.3 (Berkeley) 2/21/94
 .\" $FreeBSD$
 .\"
-.Dd August 19, 2018
+.Dd June 29, 2022
 .Dt RECV 2
 .Os
 .Sh NAME
@@ -332,7 +332,7 @@ and
 The argument
 .Fa s
 does not refer to a socket.
-.It Bq Er EMSGSIZE
+.It Bq Er EMFILE
 The
 .Fn recvmsg
 system call
@@ -340,9 +340,20 @@ was used to receive rights (file descriptors) that were in flight on the
 connection.
 However, the receiving program did not have enough free file
 descriptor slots to accept them.
-In this case the descriptors are
-closed, any pending data can be returned by another call to
+In this case the descriptors are closed, with pending data either discarded
+in the case of the unreliable datagram protocol or preserved in the case of a
+reliable protocol.
+The pending data can be retrieved with another call to
 .Fn recvmsg .
+.It Bq Er EMSGSIZE
+The
+.Fa msg_iovlen
+member of the
+.Fa msghdr
+structure pointed to by
+.Fa msg
+is less than or equal to 0, or is greater than
+.Va IOV_MAX .
 .It Bq Er EAGAIN
 The socket is marked non-blocking and the receive operation
 would block, or
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 2eb9db632a11..b0661c0d0daf 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -2547,9 +2547,8 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
 
 			fdp = (int *)
 			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
-			if (fdallocn(td, 0, fdp, newfds) != 0) {
+			if ((error = fdallocn(td, 0, fdp, newfds))) {
 				FILEDESC_XUNLOCK(fdesc);
-				error = EMSGSIZE;
 				unp_freerights(fdep, newfds);
 				m_freem(*controlp);
 				*controlp = NULL;
diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c
index bbd298f9a26f..dc017db4f1ce 100644
--- a/tests/sys/kern/unix_passfd_test.c
+++ b/tests/sys/kern/unix_passfd_test.c
@@ -428,8 +428,8 @@ ATF_TC_BODY(send_a_lot, tc)
 	msghdr.msg_controllen = CMSG_LEN(sizeof(int));
 	ATF_REQUIRE(sendmsg(fd[0], &msghdr, 0) == 1);
 	ATF_REQUIRE(recvmsg(fd[1], &msghdr, 0) == -1);
-	/* Such attempt shall fail with EMSGSIZE. */
-	ATF_REQUIRE(errno == EMSGSIZE);
+	/* Such attempt shall fail with EMFILE. */
+	ATF_REQUIRE(errno == EMFILE);
 	ATF_REQUIRE(getnfds() == nfds);
 #if TEST_PROTO == SOCK_STREAM
 	/*