Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 May 2017 10:28:17 +0000 (UTC)
From:      Nick Hibma <n_hibma@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r318630 - stable/11/sbin/dhclient
Message-ID:  <201705221028.v4MASHNe041436@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: n_hibma
Date: Mon May 22 10:28:17 2017
New Revision: 318630
URL: https://svnweb.freebsd.org/changeset/base/318630

Log:
  MFC:
  
  	------------------------------------------------------------------------
  	r317923 | n_hibma | 2017-05-07 23:11:28 +0200 (Sun, 07 May 2017) | 8 lines
  
  	Fix the output of very large rebind, renew and lease time options in
  	lease file.
  
  	Some routers set very large values for rebind time (Netgear) and these
  	are erroneously reported as negative in the leasefile. This was due to a
  	wrong printf format specification of %ld for an unsigned long on 32-bit
  	platforms.
  
  	------------------------------------------------------------------------
  	r317915 | n_hibma | 2017-05-07 21:59:37 +0200 (Sun, 07 May 2017) | 16 lines
  
  	Fix handling of large DHCP expiry values.
  
  	They would overflow a signed 32-bit time_t on 32 bit architectures. This
  	was taken care of, but a compiler optimisation makes this behave
  	erratically. This could be resolved by adding a -fwrapv flag, but
  	instead we can check the value before adding the current timestamp to
  	it.
  
  	In the lease file values are still wrong though:
  
  		option dhcp-rebinding-time -644245096;
  
  PR:		218980

Modified:
  stable/11/sbin/dhclient/dhclient.c
  stable/11/sbin/dhclient/options.c

Modified: stable/11/sbin/dhclient/dhclient.c
==============================================================================
--- stable/11/sbin/dhclient/dhclient.c	Mon May 22 08:20:50 2017	(r318629)
+++ stable/11/sbin/dhclient/dhclient.c	Mon May 22 10:28:17 2017	(r318630)
@@ -107,7 +107,11 @@ struct pidfh *pidfile;
  */
 #define ASSERT_STATE(state_is, state_shouldbe) {}
 
-#define TIME_MAX 2147483647
+/*
+ * We need to check that the expiry, renewal and rebind times are not beyond
+ * the end of time (~2038 when a 32-bit time_t is being used).
+ */
+#define TIME_MAX        ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
 
 int		log_priority;
 int		no_daemon;
@@ -762,15 +766,17 @@ dhcpack(struct packet *packet)
 	else
 		ip->client->new->expiry = default_lease_time;
 	/* A number that looks negative here is really just very large,
-	   because the lease expiry offset is unsigned. */
-	if (ip->client->new->expiry < 0)
-		ip->client->new->expiry = TIME_MAX;
+	   because the lease expiry offset is unsigned. Also make sure that
+           the addition of cur_time below does not overflow (a 32 bit) time_t. */
+	if (ip->client->new->expiry < 0 ||
+            ip->client->new->expiry > TIME_MAX - cur_time)
+		ip->client->new->expiry = TIME_MAX - cur_time;
 	/* XXX should be fixed by resetting the client state */
 	if (ip->client->new->expiry < 60)
 		ip->client->new->expiry = 60;
 
         /* Unless overridden in the config, take the server-provided renewal
-         * time if there is one; otherwise figure it out according to the spec.
+         * time if there is one. Otherwise figure it out according to the spec.
          * Also make sure the renewal time does not exceed the expiry time.
          */
         if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
@@ -782,7 +788,8 @@ dhcpack(struct packet *packet)
 		    ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
 	else
 		ip->client->new->renewal = ip->client->new->expiry / 2;
-        if (ip->client->new->renewal > ip->client->new->expiry / 2)
+        if (ip->client->new->renewal < 0 ||
+            ip->client->new->renewal > ip->client->new->expiry / 2)
                 ip->client->new->renewal = ip->client->new->expiry / 2;
 
 	/* Same deal with the rebind time. */
@@ -794,20 +801,15 @@ dhcpack(struct packet *packet)
 		ip->client->new->rebind = getULong(
 		    ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
 	else
-		ip->client->new->rebind = ip->client->new->renewal * 7 / 4;
-        if (ip->client->new->rebind > ip->client->new->renewal * 7 / 4)
-                ip->client->new->rebind = ip->client->new->renewal * 7 / 4;
-
-	ip->client->new->expiry += cur_time;
-	/* Lease lengths can never be negative. */
-	if (ip->client->new->expiry < cur_time)
-		ip->client->new->expiry = TIME_MAX;
-	ip->client->new->renewal += cur_time;
-	if (ip->client->new->renewal < cur_time)
-		ip->client->new->renewal = TIME_MAX;
-	ip->client->new->rebind += cur_time;
-	if (ip->client->new->rebind < cur_time)
-		ip->client->new->rebind = TIME_MAX;
+		ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
+	if (ip->client->new->rebind < 0 ||
+            ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
+                ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
+
+        /* Convert the time offsets into seconds-since-the-epoch */
+        ip->client->new->expiry += cur_time;
+        ip->client->new->renewal += cur_time;
+        ip->client->new->rebind += cur_time;
 
 	bind_lease(ip);
 }

Modified: stable/11/sbin/dhclient/options.c
==============================================================================
--- stable/11/sbin/dhclient/options.c	Mon May 22 08:20:50 2017	(r318629)
+++ stable/11/sbin/dhclient/options.c	Mon May 22 10:28:17 2017	(r318630)
@@ -783,7 +783,7 @@ pretty_print_option(unsigned int code, u
 				dp += 4;
 				break;
 			case 'L':
-				opcount = snprintf(op, opleft, "%ld",
+				opcount = snprintf(op, opleft, "%lu",
 				    (unsigned long)getULong(dp));
 				if (opcount >= opleft || opcount == -1)
 					goto toobig;
@@ -799,7 +799,7 @@ pretty_print_option(unsigned int code, u
 				dp += 2;
 				break;
 			case 'S':
-				opcount = snprintf(op, opleft, "%d",
+				opcount = snprintf(op, opleft, "%u",
 				    getUShort(dp));
 				if (opcount >= opleft || opcount == -1)
 					goto toobig;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705221028.v4MASHNe041436>