]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: fix handling of socket errors with error queue
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 4 Apr 2018 07:07:10 +0000 (09:07 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 4 Apr 2018 07:18:44 +0000 (09:18 +0200)
In the next Linux version the recvmmsg() system call will be probably
fixed to not return socket errors (e.g. due to ICMP) when reading from
the error queue.

The NTP I/O code assumed this was the correct behavior. When the system
call is fixed, a socket error on a client socket will cause chronyd to
enter a busy loop consuming the CPU until the receive timeout is reached
(8 seconds by default).

Use getsockopt(SO_ERROR) to clear the socket error when reading from the
error queue failed.

ntp_io.c
sys_linux.c

index d63eb1d3c363f2ec98fbd349549e2baff66a3c77..5c8c47a997924c7a1fbc4952cb1dcbbf0725bd4c 100644 (file)
--- a/ntp_io.c
+++ b/ntp_io.c
@@ -717,6 +717,20 @@ read_from_socket(int sock_fd, int event, void *anything)
 #endif
 
   if (status < 0) {
+#ifdef HAVE_LINUX_TIMESTAMPING
+    /* If reading from the error queue failed, the exception should be
+       for a socket error.  Clear the error to avoid a busy loop. */
+    if (flags & MSG_ERRQUEUE) {
+      int error = 0;
+      socklen_t len = sizeof (error);
+
+      if (getsockopt(sock_fd, SOL_SOCKET, SO_ERROR, &error, &len))
+        DEBUG_LOG("Could not get SO_ERROR");
+      if (error)
+        errno = error;
+    }
+#endif
+
     DEBUG_LOG("Could not receive from fd %d : %s", sock_fd,
               strerror(errno));
     return;
index 202e7c2061476a1c4ca05d09937a7e6cfc353910..f4b532d95858e21d8688ab5314837703f47febdd 100644 (file)
@@ -497,7 +497,7 @@ SYS_Linux_EnableSystemCallFilter(int level)
     SCMP_SYS(lseek), SCMP_SYS(rename), SCMP_SYS(stat), SCMP_SYS(stat64),
     SCMP_SYS(statfs), SCMP_SYS(statfs64), SCMP_SYS(unlink),
     /* Socket */
-    SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname),
+    SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
     SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
     SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
     /* TODO: check socketcall arguments */