From db4e4aa2e429a070f30c5795300a77312144bc8f Mon Sep 17 00:00:00 2001 From: Thomas Markwalder Date: Fri, 12 Jan 2018 10:41:37 -0500 Subject: [master] Fixed relative file name crash Merges in rt46957 --- RELNOTES | 7 ++++++ client/dhclient.c | 10 ++------- common/print.c | 66 ++++++++++++++++++++++++++++++++++++++++++++----------- includes/dhcpd.h | 1 + server/dhcpd.c | 6 +---- 5 files changed, 64 insertions(+), 26 deletions(-) diff --git a/RELNOTES b/RELNOTES index 05d035bf..158b7e2f 100644 --- a/RELNOTES +++ b/RELNOTES @@ -103,6 +103,13 @@ by Eric Young (eay@cryptsoft.com). cannot rely on the results of executable statements. [ISC-Bugs #45451] +- Fixed a bug which causes dhcpd and dhclient to crash on certain + systems when given relative path names for lease or pid files on + the command line. Affected systems are those on which the C library + function, realpath() does not support a second parameter value of + NULL (see manpages for realpath(3)). + [ISC-Bugs #46957] + Changes since 4.4.0a1 (New Features) - Added experimental support for relay port (draft-ietf-dhc-relay-port-10.txt) diff --git a/client/dhclient.c b/client/dhclient.c index ac3cdbf8..825ab00f 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -639,17 +639,11 @@ main(int argc, char **argv) { * to be reopened after chdir() has been called */ if (path_dhclient_db[0] != '/') { - const char *old_path = path_dhclient_db; - path_dhclient_db = realpath(path_dhclient_db, NULL); - if (path_dhclient_db == NULL) - log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno)); + path_dhclient_db = absolute_path(path_dhclient_db); } if (path_dhclient_script[0] != '/') { - const char *old_path = path_dhclient_script; - path_dhclient_script = realpath(path_dhclient_script, NULL); - if (path_dhclient_script == NULL) - log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno)); + path_dhclient_script = absolute_path(path_dhclient_script); } /* diff --git a/common/print.c b/common/print.c index 5993c0e2..8727b4fa 100644 --- a/common/print.c +++ b/common/print.c @@ -3,7 +3,7 @@ Turn data structures into printable text. */ /* - * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004-2018 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1995-2003 by Internet Software Consortium * * This Source Code Form is subject to the terms of the Mozilla Public @@ -132,7 +132,7 @@ char *print_base64 (const unsigned char *buf, unsigned len, b = dmalloc (bl + 1, file, line); if (!b) return (char *)0; - + i = 0; s = b; while (i != len) { @@ -199,15 +199,15 @@ void print_lease (lease) log_debug (" Lease %s", piaddr (lease -> ip_addr)); - + t = gmtime (&lease -> starts); strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); log_debug (" start %s", tbuf); - + t = gmtime (&lease -> ends); strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); log_debug (" end %s", tbuf); - + if (lease -> hardware_addr.hlen) log_debug (" hardware addr = %s", print_hw_addr (lease -> hardware_addr.hbuf [0], @@ -215,7 +215,7 @@ void print_lease (lease) &lease -> hardware_addr.hbuf [1])); log_debug (" host %s ", lease -> host ? lease -> host -> name : ""); -} +} #if defined (DEBUG_PACKET) void dump_packet_option (struct option_cache *oc, @@ -301,7 +301,7 @@ void dump_raw (buf, len) /* 1 2 3 4 5 6 7 01234567890123456789012345678901234567890123456789012345678901234567890123 -280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. +280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. */ memset(lbuf, ' ', 79); @@ -446,7 +446,7 @@ void print_hex_or_string (len, data, limit, buf) /* * print a string as either hex or text * using static buffers to hold the output - * + * * len - length of data * data - input data * limit - length of buf @@ -499,7 +499,7 @@ char *print_dotted_quads (len, data) char *s; s = &dq_buf [0]; - + i = 0; /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe% @@ -554,7 +554,7 @@ static unsigned print_subexpression (expr, buf, len) return 3; } break; - + case expr_match: if (len > 7) { strcpy (buf, "(match)"); @@ -772,7 +772,7 @@ static unsigned print_subexpression (expr, buf, len) case expr_binary_xor: s = "^"; goto binop; - + case expr_not: if (len > 6) { rv = 5; @@ -1179,7 +1179,7 @@ void print_expression (name, expr) } int token_print_indent_concat (FILE *file, int col, int indent, - const char *prefix, + const char *prefix, const char *suffix, ...) { va_list list; @@ -1209,7 +1209,7 @@ int token_print_indent_concat (FILE *file, int col, int indent, s = va_arg (list, char *); } va_end (list); - + col = token_print_indent (file, col, indent, prefix, suffix, t); dfree (t, MDL); @@ -1439,3 +1439,43 @@ char *format_lease_id(const unsigned char *s, unsigned len, } return (idstr); } + +/* + * Convert a relative path name to an absolute path name + * + * Not all versions of realpath() support NULL for + * the second parameter and PATH_MAX isn't defined + * on all systems. For the latter, we'll make what + * ought to be a big enough buffer and let it fly. + * If passed an absolute path it should return it + * an allocated buffer. + */ +char *absolute_path(const char *orgpath) { + char *abspath = NULL; + if (orgpath) { +#ifdef PATH_MAX + char buf[PATH_MAX]; +#else + char buf[2048]; + int len; +#endif + errno = 0; + if (realpath(orgpath, buf) == NULL) { + const char* errmsg = strerror(errno); + log_fatal("Failed to get realpath for %s: %s", + orgpath, errmsg); + } + + /* dup the result into an allocated buffer */ + abspath = dmalloc(strlen(buf) + 1, MDL); + if (abspath == NULL) { + log_fatal("No memory for filename:%s\n", + buf); + } + + memcpy (abspath, buf, strlen(buf)); + abspath[strlen(buf)] = 0x0; + } + + return (abspath); +} diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 90456b76..24c8146f 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -2635,6 +2635,7 @@ char *buf_to_hex (const unsigned char *s, unsigned len, const char *file, int line); char *format_lease_id(const unsigned char *s, unsigned len, int format, const char *file, int line); +char *absolute_path(const char *orgpath); /* socket.c */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ || defined (USE_SOCKET_FALLBACK) diff --git a/server/dhcpd.c b/server/dhcpd.c index 4ac8bd75..55ffae70 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -607,11 +607,7 @@ main(int argc, char **argv) { * to be reopened after chdir() has been called */ if (have_dhcpd_db && path_dhcpd_db[0] != '/') { - const char *path = path_dhcpd_db; - path_dhcpd_db = realpath(path_dhcpd_db, NULL); - if (path_dhcpd_db == NULL) - log_fatal("Failed to get realpath for %s: %s", path, - strerror(errno)); + path_dhcpd_db = absolute_path(path_dhcpd_db); } if (!quiet) { -- cgit v1.2.1