Use port-sockets.h macros in cc_kcm, sendto_kdc

Resolves: #1631998
This commit is contained in:
Robbie Harwood 2018-10-17 15:27:45 -04:00
parent c0ac611ad3
commit d760ebeab2
3 changed files with 231 additions and 1 deletions

View File

@ -0,0 +1,86 @@
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

View File

@ -0,0 +1,138 @@
From 76fc514d3d00b8ac9f7844ade35c08eaa7c8a1fc Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 15 Oct 2018 19:12:45 -0400
Subject: [PATCH] Use port-sockets.h macros in cc_kcm, sendto_kdc
Use SOCKET_CONNECT in cc_kcm.c and sendto_kdc.c to prevent SIGPIPE on
BSD-like systems. Use other port-sockets.h macros in cc_kcm.c in case
it is ever used on Windows.
ticket: 8753
(cherry picked from commit 2aaf0e74805e295358627ac1e5d589d625d8e6b0)
---
src/lib/krb5/ccache/cc_kcm.c | 34 ++++++++++++++++++----------------
src/lib/krb5/os/sendto_kdc.c | 3 ++-
2 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index a777f2710..b260cd81b 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -42,6 +42,7 @@
#include "k5-input.h"
#include "cc-int.h"
#include "kcm.h"
+#include "../os/os-proto.h"
#include <sys/socket.h>
#include <sys/un.h>
#ifdef __APPLE__
@@ -61,7 +62,7 @@ struct uuid_list {
};
struct kcmio {
- int fd;
+ SOCKET fd;
#ifdef __APPLE__
mach_port_t mport;
#endif
@@ -252,7 +253,7 @@ static krb5_error_code
kcmio_unix_socket_connect(krb5_context context, struct kcmio *io)
{
krb5_error_code ret;
- int fd = -1;
+ SOCKET fd = INVALID_SOCKET;
struct sockaddr_un addr;
char *path = NULL;
@@ -267,25 +268,25 @@ kcmio_unix_socket_connect(krb5_context context, struct kcmio *io)
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1) {
- ret = errno;
+ if (fd == INVALID_SOCKET) {
+ ret = SOCKET_ERRNO;
goto cleanup;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
- if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
- ret = (errno == ENOENT) ? KRB5_KCM_NO_SERVER : errno;
+ if (SOCKET_CONNECT(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
+ ret = (SOCKET_ERRNO == ENOENT) ? KRB5_KCM_NO_SERVER : SOCKET_ERRNO;
goto cleanup;
}
io->fd = fd;
- fd = -1;
+ fd = INVALID_SOCKET;
cleanup:
- if (fd != -1)
- close(fd);
+ if (fd != INVALID_SOCKET)
+ closesocket(fd);
profile_release_string(path);
return ret;
}
@@ -297,11 +298,12 @@ kcmio_unix_socket_write(krb5_context context, struct kcmio *io, void *request,
size_t len)
{
char lenbytes[4];
+ sg_buf sg[2];
+ SG_SET(&sg[0], lenbytes, sizeof(lenbytes));
+ SG_SET(&sg[1], request, len);
store_32_be(len, lenbytes);
- if (krb5_net_write(context, io->fd, lenbytes, 4) < 0)
- return errno;
- if (krb5_net_write(context, io->fd, request, len) < 0)
+ if (krb5int_net_writev(context, io->fd, sg, 2) < 0)
return errno;
return 0;
}
@@ -358,7 +360,7 @@ kcmio_connect(krb5_context context, struct kcmio **io_out)
io = calloc(1, sizeof(*io));
if (io == NULL)
return ENOMEM;
- io->fd = -1;
+ io->fd = INVALID_SOCKET;
/* Try Mach RPC (macOS only), then fall back to Unix domain sockets */
ret = kcmio_mach_connect(context, io);
@@ -384,7 +386,7 @@ kcmio_call(krb5_context context, struct kcmio *io, struct kcmreq *req)
if (k5_buf_status(&req->reqbuf) != 0)
return ENOMEM;
- if (io->fd != -1) {
+ if (io->fd != INVALID_SOCKET) {
ret = kcmio_unix_socket_write(context, io, req->reqbuf.data,
req->reqbuf.len);
if (ret)
@@ -411,8 +413,8 @@ kcmio_close(struct kcmio *io)
{
if (io != NULL) {
kcmio_mach_close(io);
- if (io->fd != -1)
- close(io->fd);
+ if (io->fd != INVALID_SOCKET)
+ closesocket(io->fd);
free(io);
}
}
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index e8bc0ad6e..0ed6b1d70 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -880,7 +880,8 @@ start_connection(krb5_context context, struct conn_state *state,
}
/* Start connecting to KDC. */
- e = connect(fd, (struct sockaddr *)&state->addr.saddr, state->addr.len);
+ e = SOCKET_CONNECT(fd, (struct sockaddr *)&state->addr.saddr,
+ state->addr.len);
if (e != 0) {
/*
* This is the path that should be followed for non-blocking

View File

@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
Name: krb5
Version: 1.16.1
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
Release: 23%{?dist}
Release: 24%{?dist}
# lookaside-cached sources; two downloads and a build artifact
Source0: https://web.mit.edu/kerberos/dist/krb5/1.16/krb5-%{version}%{prerelease}.tar.gz
@ -105,6 +105,8 @@ Patch85: Fix-k5test-prompts-for-Python-3.patch
Patch86: In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
Patch87: Prefer-TCP-to-UDP-for-password-changes.patch
Patch88: Correct-kpasswd_server-description-in-krb5.conf-5.patch
Patch89: Prevent-SIGPIPE-from-socket-writes-on-UNIX-likes.patch
Patch90: Use-port-sockets.h-macros-in-cc_kcm-sendto_kdc.patch
License: MIT
URL: http://web.mit.edu/kerberos/www/
@ -751,6 +753,10 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Wed Oct 17 2018 Robbie Harwood <rharwood@redhat.com> - 1.16.1-24
- Use port-sockets.h macros in cc_kcm, sendto_kdc
- Resolves: #1631998
* Wed Oct 17 2018 Robbie Harwood <rharwood@redhat.com> - 1.16.1-23
- Correct kpasswd_server description in krb5.conf(5)
- Resolves: #1640272