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
This commit is contained in:
Gleb Smirnoff 2022-06-29 09:42:58 -07:00
parent baf8f20a4a
commit 48a55bbfe9
3 changed files with 18 additions and 8 deletions

View File

@ -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

View File

@ -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;

View File

@ -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
/*