]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Prevent SIGPIPE from socket writes on UNIX-likes
authorRobbie Harwood <rharwood@redhat.com>
Fri, 12 Oct 2018 20:57:05 +0000 (16:57 -0400)
committerGreg Hudson <ghudson@mit.edu>
Wed, 17 Oct 2018 19:00:16 +0000 (15:00 -0400)
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)

src/include/port-sockets.h

index f0fc2b804e0e3eaa3d3bd2fd8918d0b0d414d49f..57e5d1dd33eef30911905ecce595c9c9d53b50cf 100644 (file)
@@ -159,6 +159,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. */
@@ -219,15 +220,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