Handle EINTR on recvmsg()
Resolves: RHEL-143222
This commit is contained in:
parent
912c717fe7
commit
942003502f
161
socat-1.7.4.1-handle-EINTR-on-recvmsg.patch
Normal file
161
socat-1.7.4.1-handle-EINTR-on-recvmsg.patch
Normal file
@ -0,0 +1,161 @@
|
||||
diff --git a/CHANGES b/CHANGES
|
||||
index 794b7a7..b2046e1 100644
|
||||
--- a/CHANGES
|
||||
+++ b/CHANGES
|
||||
@@ -91,6 +91,11 @@ Corrections:
|
||||
|
||||
Fixed some more non functional minor issues.
|
||||
|
||||
+ UDP-RECVFROM with fork sometimes terminated when multiple packets
|
||||
+ arrived. This issue was introduced with a bug fix in version 1.7.4.0.
|
||||
+ Reason was not handling EAGAIN on recvmsg().
|
||||
+ Thanks to Jamie McQuillan for reporting this issue.
|
||||
+
|
||||
Porting:
|
||||
In gcc version 10 the default changed from -fcommon to -fno-common.
|
||||
Consequently, linking filan and procan failed with error
|
||||
diff --git a/xio-socket.c b/xio-socket.c
|
||||
index d6b935c..4254394 100644
|
||||
--- a/xio-socket.c
|
||||
+++ b/xio-socket.c
|
||||
@@ -1214,6 +1214,7 @@ void xiosigaction_hasread(int signum
|
||||
return;
|
||||
}
|
||||
if (pid == xio_waitingfor) {
|
||||
+ xio_waitingfor = 0; /* so this child will not set hashappened again */
|
||||
xio_hashappened = true;
|
||||
xio_childstatus = WEXITSTATUS(status);
|
||||
Debug("xiosigaction_hasread() ->");
|
||||
@@ -1253,6 +1254,7 @@ void xiosigaction_hasread(int signum
|
||||
PH_INIT, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_EARLY, PH_PREOPEN, PH_FD,
|
||||
PH_CONNECTED, PH_LATE, PH_LATE2
|
||||
OPT_FORK, OPT_SO_TYPE, OPT_SO_PROTOTYPE, cloexec, OPT_RANGE, tcpwrap
|
||||
+ EINTR is not handled specially.
|
||||
*/
|
||||
int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
struct sockaddr *us, socklen_t uslen,
|
||||
@@ -1382,6 +1384,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
socklen_t palen = sizeof(_peername); /* peer address size */
|
||||
char ctrlbuff[1024]; /* ancillary messages */
|
||||
struct msghdr msgh = {0};
|
||||
+ int rc;
|
||||
|
||||
socket_init(pf, pa);
|
||||
|
||||
@@ -1392,6 +1395,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
drop = true;
|
||||
}
|
||||
|
||||
+ Info("Recvfrom: Checking/waiting for next packet");
|
||||
/* loop until select()/poll() returns valid */
|
||||
do {
|
||||
struct pollfd readfd;
|
||||
@@ -1424,9 +1428,9 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||
#endif
|
||||
- if (xiogetpacketsrc(xfd->fd, &msgh) < 0) {
|
||||
- return STAT_RETRYLATER;
|
||||
- }
|
||||
+ while ((rc = xiogetpacketsrc(xfd->fd, &msgh)) < 0 &&
|
||||
+ errno == EINTR) ;
|
||||
+ if (rc < 0) return STAT_RETRYLATER;
|
||||
palen = msgh.msg_namelen;
|
||||
|
||||
Notice1("receiving packet from %s"/*"src"*/,
|
||||
@@ -1497,24 +1501,21 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||
break;
|
||||
}
|
||||
|
||||
- /* server: continue loop with listen */
|
||||
xio_waitingfor = pid;
|
||||
|
||||
+ do {
|
||||
#if HAVE_PSELECT
|
||||
- {
|
||||
+ {
|
||||
struct timespec timeout = { LONG_MAX, 0 };
|
||||
Pselect(0, NULL, NULL, NULL, &timeout, &oldset);
|
||||
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
- }
|
||||
+ }
|
||||
#else /* ! HAVE_PSELECT */
|
||||
- /* now we are ready to handle signals */
|
||||
- Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
-
|
||||
- while (!xio_hashappened) {
|
||||
- Sleep(1); /* any signal speeds up return */
|
||||
- }
|
||||
+ /* now we are ready to handle signals */
|
||||
+ Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
+ Sleep(1); /* any signal speeds up return */
|
||||
#endif /* ! HAVE_PSELECT */
|
||||
- xio_waitingfor = 0; /* so this child will not set hashappened again */
|
||||
+ } while (!xio_hashappened) ;
|
||||
xio_hashappened = false;
|
||||
|
||||
if (xio_childstatus != 0) {
|
||||
@@ -1639,9 +1640,12 @@ int retropt_socket_pf(struct opt *opts, int *pf) {
|
||||
}
|
||||
|
||||
|
||||
-/* this function calls recvmsg(..., MSG_PEEK, ...) to obtain information about
|
||||
- the arriving packet. in msgh the msg_name pointer must refer to an (empty)
|
||||
- sockaddr storage. */
|
||||
+/* This function calls recvmsg(..., MSG_PEEK, ...) to obtain information about
|
||||
+ the arriving packet, thus it does not "consume" the packet.
|
||||
+ In msgh the msg_name pointer must refer to an (empty) sockaddr storage.
|
||||
+ Returns STAT_OK on success, or STAT_RETRYLATER when an error occurred,
|
||||
+ including EINTR.
|
||||
+ */
|
||||
int xiogetpacketsrc(int fd, struct msghdr *msgh) {
|
||||
char peekbuff[1];
|
||||
#if HAVE_STRUCT_IOVEC
|
||||
diff --git a/xioread.c b/xioread.c
|
||||
index 24f3c88..b89e78a 100644
|
||||
--- a/xioread.c
|
||||
+++ b/xioread.c
|
||||
@@ -118,6 +118,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
socklen_t fromlen = sizeof(from);
|
||||
char infobuff[256];
|
||||
char ctrlbuff[1024]; /* ancillary messages */
|
||||
+ int rc;
|
||||
|
||||
msgh.msg_name = &from;
|
||||
msgh.msg_namelen = fromlen;
|
||||
@@ -127,9 +128,10 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||
#endif
|
||||
- if (xiogetpacketsrc(pipe->fd, &msgh) < 0) {
|
||||
- return -1;
|
||||
- }
|
||||
+ while ((rc = xiogetpacketsrc(pipe->fd, &msgh)) < 0 &&
|
||||
+ errno == EINTR) ;
|
||||
+ if (rc < 0) return -1;
|
||||
+
|
||||
do {
|
||||
bytes =
|
||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
||||
@@ -313,6 +315,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
char infobuff[256];
|
||||
struct msghdr msgh = {0};
|
||||
char ctrlbuff[1024]; /* ancillary messages */
|
||||
+ int rc;
|
||||
|
||||
socket_init(pipe->para.socket.la.soa.sa_family, &from);
|
||||
/* get source address */
|
||||
@@ -324,9 +327,10 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||
#if HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||
msgh.msg_controllen = sizeof(ctrlbuff);
|
||||
#endif
|
||||
- if (xiogetpacketsrc(pipe->fd, &msgh) < 0) {
|
||||
- return -1;
|
||||
- }
|
||||
+ while ((rc = xiogetpacketsrc(pipe->fd, &msgh)) < 0 &&
|
||||
+ errno == EINTR) ;
|
||||
+ if (rc < 0) return -1;
|
||||
+
|
||||
xiodopacketinfo(&msgh, true, false);
|
||||
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
|
||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
|
||||
@ -3,7 +3,7 @@
|
||||
Summary: Bidirectional data relay between two data channels ('netcat++')
|
||||
Name: socat
|
||||
Version: 1.7.4.1
|
||||
Release: 8%{?dist}
|
||||
Release: 9%{?dist}
|
||||
License: GPLv2
|
||||
Url: http://www.dest-unreach.org/socat/
|
||||
Source: http://www.dest-unreach.org/socat/download/%{name}-%{version}.tar.gz
|
||||
@ -16,6 +16,9 @@ Patch3: socat-1.7.4.1-CVE-2024-54661.patch
|
||||
# https://issues.redhat.com/browse/RHEL-107884
|
||||
# Based on: https://repo.or.cz/socat.git/commit/ed4780553fd05bb8ed8a29462698090482be3393
|
||||
Patch4: socat-1.7.4.1-tcp-address-with-connect-timeout.patch
|
||||
# https://issues.redhat.com/browse/RHEL-143222
|
||||
# Based on: https://repo.or.cz/socat.git/commit/45d87df2fd32756b56f8a48c2d6cdb476342aa20
|
||||
Patch5: socat-1.7.4.1-handle-EINTR-on-recvmsg.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: gcc
|
||||
@ -80,6 +83,10 @@ export OD_C=/usr/bin/od
|
||||
%doc %{_mandir}/man1/*
|
||||
|
||||
%changelog
|
||||
* Fri Jan 30 2026 Martin Osvald <mosvald@redhat.com> - 1.7.4.1-9
|
||||
- Handle EINTR on recvmsg()
|
||||
Resolves: RHEL-143222
|
||||
|
||||
* Thu Aug 07 2025 Martin Osvald <mosvald@redhat.com> - 1.7.4.1-8
|
||||
- Fix for: Client may exit 0 despite connection being reset
|
||||
Resolves: RHEL-107884
|
||||
|
||||
Loading…
Reference in New Issue
Block a user