summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Routhier <sar@isc.org>2010-10-06 00:32:52 +0000
committerShawn Routhier <sar@isc.org>2010-10-06 00:32:52 +0000
commitc5b80aeecd88132e2beee9a228b21b1b6d58a5c4 (patch)
treeb24701d382b5e5365758cf7cb630604b14a61045
parent0b57020efe8938c75bc48f046c667e2f28089134 (diff)
downloadisc-dhcp-c5b80aeecd88132e2beee9a228b21b1b6d58a5c4.tar.gz
Handle pipe failures better - ticket 22269
-rw-r--r--RELNOTES20
-rw-r--r--client/dhclient.c8
-rw-r--r--common/socket.c24
-rw-r--r--includes/dhcpd.h1
-rw-r--r--omapip/connection.c16
-rw-r--r--relay/dhcrelay.c9
-rw-r--r--server/dhcpd.c8
7 files changed, 85 insertions, 1 deletions
diff --git a/RELNOTES b/RELNOTES
index 53246362..92604267 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -153,6 +153,26 @@ work on other platforms. Please report any problems and suggested fixes to
[ISC-Bugs #20952] Add 64 bit types to configure.ac
[ISC-Bugs #21308] Add "PATH=" to CLIENT_PATH envrionment variable
+! Handle pipe failures more gracefully. Some OSes pass a SIGPIPE
+ signal to a process and will kill the process if the signal isn't
+ caught. This patch adds code to turn off the SIGPIPE signal via
+ a setsockopt() call and to ignore the SIGPIPE signal in case the
+ OS doesn't support the necessary setsockopt() option. This problem
+ was found during internal testing when the two servers in a failover
+ pair were repeatedly unable to communicate for longer than the
+ max-response-delay value. Eventually one of the pair attempted a
+ write() call at just the same time as the other server killed the
+ connection and caused an uncaught SIGPIPE signal which caused the
+ OS to kill the server.
+ This is a minor security issue. It is a security issue as it can
+ cause a server to stop. It is minor as the attacker would need to
+ be able to interrupt traffic between the partners in a failover
+ pair for max-response-delay seconds at will - in which case the
+ defender has bigger problems than the DHCP server being killed.
+ Using the NIST CVSS security vulnerability rating system this
+ issue scored 1.2, meaning it is not a major risk for users.
+ [ISC-Bugs #22269]
+
Changes since 4.1.1rc1
- When using 'ignore client-updates;', the FQDN returned to the client
diff --git a/client/dhclient.c b/client/dhclient.c
index 95d8854f..3ee32117 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -135,6 +135,14 @@ main(int argc, char **argv) {
setlogmask(LOG_UPTO(LOG_INFO));
#endif
+ /*
+ * Set up the signal handlers, currently we only
+ * have one to ignore sigpipe.
+ */
+ if (dhcp_handle_signal(SIGPIPE, SIG_IGN) != ISC_R_SUCCESS) {
+ log_fatal("Can't set up signal handler");
+ }
+
/* Set up the OMAPI. */
status = omapi_init();
if (status != ISC_R_SUCCESS)
diff --git a/common/socket.c b/common/socket.c
index 969b853a..f36e2b2a 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -45,6 +45,7 @@
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/uio.h>
+#include <signal.h>
#ifdef USE_SOCKET_FALLBACK
# if !defined (USE_SOCKET_SEND)
@@ -876,3 +877,26 @@ void maybe_setup_fallback ()
#endif
}
#endif /* USE_SOCKET_SEND */
+
+/*
+ * Code to set a handler for signals. This
+ * exists to allow us to ignore SIGPIPE signals
+ * but could be used for other purposes in the
+ * future.
+ */
+
+isc_result_t
+dhcp_handle_signal(int sig, void (*handler)(int)) {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handler;
+
+ if (sigfillset(&sa.sa_mask) != 0 ||
+ sigaction(sig, &sa, NULL) < 0) {
+ log_error("Unable to set up signal handler for %d, %m", sig);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index 2dbc33ba..b55fe722 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -2201,6 +2201,7 @@ ssize_t receive_packet6(struct interface_info *interface,
unsigned int *if_index);
void if_deregister6(struct interface_info *info);
+isc_result_t dhcp_handle_signal(int sig, void (*handler)(int));
/* bpf.c */
#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
diff --git a/omapip/connection.c b/omapip/connection.c
index 38020de8..5aac7b0f 100644
--- a/omapip/connection.c
+++ b/omapip/connection.c
@@ -3,7 +3,8 @@
Subroutines for dealing with connections. */
/*
- * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -209,6 +210,19 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
return ISC_R_UNEXPECTED;
}
+#ifdef SO_NOSIGPIPE
+ /*
+ * If available stop the OS from killing our
+ * program on a SIGPIPE failure
+ */
+ flag = 1;
+ if (setsockopt(obj->socket, SOL_SOCKET, SO_NOSIGPIPE,
+ (char *)&flag, sizeof(flag)) < 0) {
+ omapi_connection_dereference (&obj, MDL);
+ return ISC_R_UNEXPECTED;
+ }
+#endif
+
status = (omapi_register_io_object
((omapi_object_t *)obj,
0, omapi_connection_writefd,
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index be688d9a..6b328f71 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -35,6 +35,7 @@
#include "dhcpd.h"
#include <syslog.h>
#include <sys/time.h>
+#include <signal.h>
TIME default_lease_time = 43200; /* 12 hours... */
TIME max_lease_time = 86400; /* 24 hours... */
@@ -193,6 +194,14 @@ main(int argc, char **argv) {
setlogmask(LOG_UPTO(LOG_INFO));
#endif
+ /*
+ * Set up the signal handlers, currently we only
+ * have one to ignore sigpipe.
+ */
+ if (dhcp_handle_signal(SIGPIPE, SIG_IGN) != ISC_R_SUCCESS) {
+ log_fatal("Can't set up signal handler");
+ }
+
/* Set up the OMAPI. */
status = omapi_init();
if (status != ISC_R_SUCCESS)
diff --git a/server/dhcpd.c b/server/dhcpd.c
index d1b877e1..1fb23eb0 100644
--- a/server/dhcpd.c
+++ b/server/dhcpd.c
@@ -280,6 +280,14 @@ main(int argc, char **argv) {
/* Set up the client classification system. */
classification_setup ();
+ /*
+ * Set up the signal handlers, currently we only
+ * have one to ignore sigpipe.
+ */
+ if (dhcp_handle_signal(SIGPIPE, SIG_IGN) != ISC_R_SUCCESS) {
+ log_fatal("Can't set up signal handler");
+ }
+
/* Initialize the omapi system. */
result = omapi_init ();
if (result != ISC_R_SUCCESS)