krb5/Prevent-SIGPIPE-from-socket-writes-on-UNIX-likes.patch

87 lines
2.7 KiB
Diff
Raw Normal View History

From 23e01e9a966ee0aa08668a75f5753a55e1ea4547 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 12 Oct 2018 16:57:05 -0400
Subject: [PATCH] Prevent SIGPIPE from socket writes on UNIX-likes
When writing to a disconnected socket, try to only get EPIPE rather
than taking down the process with SIGPIPE.
On recent Linux and other systems which have it, switch from writev to
sendmsg and pass MSG_NOSIGNAL.
On BSD-likes, set SO_NOSIGPIPE at connect time.
ticket: 8753 (new)
(cherry picked from commit 98bf22027bd6e746f456a671ca5e257ca4bd371e)
---
src/include/port-sockets.h | 43 +++++++++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/src/include/port-sockets.h b/src/include/port-sockets.h
index b3ab9c906..3b05e022d 100644
--- a/src/include/port-sockets.h
+++ b/src/include/port-sockets.h
@@ -158,6 +158,7 @@ typedef int socklen_t;
#include <netinet/in.h> /* For struct sockaddr_in and in_addr */
#include <arpa/inet.h> /* For inet_ntoa */
#include <netdb.h>
+#include <string.h> /* For memset */
#ifndef HAVE_NETDB_H_H_ERRNO
extern int h_errno; /* In case it's missing, e.g., HP-UX 10.20. */
@@ -218,15 +219,51 @@ typedef struct iovec sg_buf;
#define SOCKET_NFDS(f) ((f)+1) /* select() arg for a single fd */
#define SOCKET_READ read
#define SOCKET_WRITE write
-#define SOCKET_CONNECT connect
+static inline int
+socket_connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ int st;
+#ifdef SO_NOSIGPIPE
+ int set = 1;
+#endif
+
+ st = connect(fd, addr, addrlen);
+ if (st == -1)
+ return st;
+
+#ifdef SO_NOSIGPIPE
+ st = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
+ if (st != 0)
+ st = -1;
+#endif
+
+ return st;
+}
+#define SOCKET_CONNECT socket_connect
#define SOCKET_GETSOCKNAME getsockname
#define SOCKET_CLOSE close
#define SOCKET_EINTR EINTR
#define SOCKET_WRITEV_TEMP int
+static inline ssize_t
+socket_sendmsg(SOCKET fd, sg_buf *iov, int iovcnt)
+{
+ struct msghdr msg;
+ int flags = 0;
+
+#ifdef MSG_NOSIGNAL
+ flags |= MSG_NOSIGNAL;
+#endif
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = iov;
+ msg.msg_iovlen = iovcnt;
+
+ return sendmsg(fd, &msg, flags);
+}
/* Use TMP to avoid compiler warnings and keep things consistent with
* Windows version. */
-#define SOCKET_WRITEV(FD, SG, LEN, TMP) \
- ((TMP) = writev((FD), (SG), (LEN)), (TMP))
+#define SOCKET_WRITEV(FD, SG, LEN, TMP) \
+ ((TMP) = socket_sendmsg((FD), (SG), (LEN)), (TMP))
#define SHUTDOWN_READ 0
#define SHUTDOWN_WRITE 1