diff options
author | Shawn Routhier <sar@isc.org> | 2010-10-06 00:32:52 +0000 |
---|---|---|
committer | Shawn Routhier <sar@isc.org> | 2010-10-06 00:32:52 +0000 |
commit | c5b80aeecd88132e2beee9a228b21b1b6d58a5c4 (patch) | |
tree | b24701d382b5e5365758cf7cb630604b14a61045 | |
parent | 0b57020efe8938c75bc48f046c667e2f28089134 (diff) | |
download | isc-dhcp-c5b80aeecd88132e2beee9a228b21b1b6d58a5c4.tar.gz |
Handle pipe failures better - ticket 22269
-rw-r--r-- | RELNOTES | 20 | ||||
-rw-r--r-- | client/dhclient.c | 8 | ||||
-rw-r--r-- | common/socket.c | 24 | ||||
-rw-r--r-- | includes/dhcpd.h | 1 | ||||
-rw-r--r-- | omapip/connection.c | 16 | ||||
-rw-r--r-- | relay/dhcrelay.c | 9 | ||||
-rw-r--r-- | server/dhcpd.c | 8 |
7 files changed, 85 insertions, 1 deletions
@@ -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) |