From d2b3a0ed31ef6270c712d0779a95bb222df88909 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Thu, 17 Feb 2022 09:07:31 -0800 Subject: [PATCH] sendto: don't clear transient errors for atomic protocols The changeset 65572cade35 uncovered the fact that top layer of sendto(2) would clear a transient error code if some data was copied out of uio. The clearing of the error makes sense for non-atomic protocols, since they have sent some data. The atomic protocols send all or nothing. The current implementation of unix/dgram uses sosend_generic(), which would always copyout and only then it may fail to deliver a message. The sosend_dgram(), currently used by UDP only, also has same behavior. Reported by: pho Reviewed by: pho, markj Differential revision: https://reviews.freebsd.org/D34309 --- sys/kern/uipc_syscalls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 766c68b35cf..72336d31071 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -785,8 +785,10 @@ kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, len = auio.uio_resid; error = sosend(so, mp->msg_name, &auio, 0, control, flags, td); if (error != 0) { - if (auio.uio_resid != len && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) + if (auio.uio_resid != len && + (so->so_proto->pr_flags & PR_ATOMIC) == 0 && + (error == ERESTART || error == EINTR || + error == EWOULDBLOCK)) error = 0; /* Generation of SIGPIPE can be controlled per socket */ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&