Blame SOURCES/0008-dhcp-client-id-rh1531173.patch

c48088
From ce8c21737b1b952044219111b2358b1602983138 Mon Sep 17 00:00:00 2001
c48088
From: Thomas Haller <thaller@redhat.com>
c48088
Date: Thu, 4 Jan 2018 16:12:40 +0100
c48088
Subject: [PATCH 1/2] dhcp: cleanup handling of ipv4.dhcp-client-id and avoid
c48088
 assertion failure
c48088
c48088
The internal client asserts that the length of the client ID is not more
c48088
than MAX_CLIENT_ID_LEN. Avoid that assert by truncating the string.
c48088
c48088
Also add new nm_dhcp_client_set_client_id_*() setters, that either
c48088
set the ID based on a string (in our common dhclient specific
c48088
format), or based on the binary data (as obtained from systemd client).
c48088
c48088
Also, add checks and assertions that the client ID which is
c48088
set via nm_dhcp_client_set_client_id() is always of length
c48088
of at least 2 (as required by rfc2132, section-9.14).
c48088
c48088
(cherry picked from commit 686afe531ab3774cd818feda8361de74101971f5)
c48088
(cherry picked from commit 41a89aeebac146000de97b778800e755db29568f)
c48088
---
c48088
 libnm-core/nm-setting-ip4-config.c                 |  2 +-
c48088
 src/dhcp/nm-dhcp-client.c                          | 67 ++++++++++++++++++----
c48088
 src/dhcp/nm-dhcp-client.h                          |  9 ++-
c48088
 src/dhcp/nm-dhcp-dhclient-utils.c                  |  8 ++-
c48088
 src/dhcp/nm-dhcp-systemd.c                         | 18 ++----
c48088
 src/dhcp/nm-dhcp-utils.c                           |  9 ++-
c48088
 src/nm-types.h                                     |  2 +
c48088
 .../src/libsystemd-network/sd-dhcp-client.c        |  1 +
c48088
 8 files changed, 88 insertions(+), 28 deletions(-)
c48088
c48088
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
c48088
index 26e7f5056..d9c0cbb14 100644
c48088
--- a/libnm-core/nm-setting-ip4-config.c
c48088
+++ b/libnm-core/nm-setting-ip4-config.c
c48088
@@ -191,7 +191,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
c48088
 		return FALSE;
c48088
 	}
c48088
 
c48088
-	if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) {
c48088
+	if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) {
c48088
 		g_set_error_literal (error,
c48088
 		                     NM_CONNECTION_ERROR,
c48088
 		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
c48088
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c
c48088
index 20ea092f0..1f19db148 100644
c48088
--- a/src/dhcp/nm-dhcp-client.c
c48088
+++ b/src/dhcp/nm-dhcp-client.c
c48088
@@ -186,19 +186,69 @@ nm_dhcp_client_get_client_id (NMDhcpClient *self)
c48088
 	return NM_DHCP_CLIENT_GET_PRIVATE (self)->client_id;
c48088
 }
c48088
 
c48088
+static void
c48088
+_set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take)
c48088
+{
c48088
+	NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
c48088
+
c48088
+	nm_assert (!client_id || g_bytes_get_size (client_id) >= 2);
c48088
+
c48088
+	if (   priv->client_id == client_id
c48088
+	    || (   priv->client_id
c48088
+	        && g_bytes_equal (priv->client_id, client_id))) {
c48088
+		if (take && client_id)
c48088
+			g_bytes_unref (client_id);
c48088
+		return;
c48088
+	}
c48088
+
c48088
+	if (priv->client_id)
c48088
+		g_bytes_unref (priv->client_id);
c48088
+	priv->client_id = client_id;
c48088
+	if (!take && client_id)
c48088
+		g_bytes_ref (client_id);
c48088
+}
c48088
+
c48088
 void
c48088
 nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id)
c48088
 {
c48088
-	NMDhcpClientPrivate *priv;
c48088
+	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
c48088
+	g_return_if_fail (!client_id || g_bytes_get_size (client_id) >= 2);
c48088
+
c48088
+	_set_client_id (self, client_id, FALSE);
c48088
+}
c48088
+
c48088
+void
c48088
+nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
c48088
+                                  guint8 type,
c48088
+                                  const guint8 *client_id,
c48088
+                                  gsize len)
c48088
+{
c48088
+	guint8 *buf;
c48088
+	GBytes *b;
c48088
 
c48088
 	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
c48088
+	g_return_if_fail (client_id);
c48088
+	g_return_if_fail (len > 0);
c48088
+
c48088
+	buf = g_malloc (len + 1);
c48088
+	buf[0] = type;
c48088
+	memcpy (buf + 1, client_id, len);
c48088
+	b = g_bytes_new_take (buf, len + 1);
c48088
+	_set_client_id (self, b, TRUE);
c48088
+}
c48088
 
c48088
-	priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
c48088
+void
c48088
+nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
c48088
+                                  const char *dhcp_client_id)
c48088
+{
c48088
+	g_return_if_fail (NM_IS_DHCP_CLIENT (self));
c48088
+	g_return_if_fail (!dhcp_client_id || dhcp_client_id[0]);
c48088
 
c48088
-	if (priv->client_id && client_id && g_bytes_equal (priv->client_id, client_id))
c48088
-		return;
c48088
-	g_clear_pointer (&priv->client_id, g_bytes_unref);
c48088
-	priv->client_id = client_id ? g_bytes_ref (client_id) : NULL;
c48088
+	_set_client_id (self,
c48088
+	                dhcp_client_id
c48088
+	                  ? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id)
c48088
+	                  : NULL,
c48088
+	                TRUE);
c48088
 }
c48088
 
c48088
 const char *
c48088
@@ -448,7 +498,6 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
c48088
                           const char *last_ip4_address)
c48088
 {
c48088
 	NMDhcpClientPrivate *priv;
c48088
-	gs_unref_bytes GBytes *tmp = NULL;
c48088
 
c48088
 	g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
c48088
 
c48088
@@ -462,9 +511,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
c48088
 	else
c48088
 		_LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
c48088
 
c48088
-	if (dhcp_client_id)
c48088
-		tmp = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id);
c48088
-	nm_dhcp_client_set_client_id (self, tmp);
c48088
+	nm_dhcp_client_set_client_id_str (self, dhcp_client_id);
c48088
 
c48088
 	g_clear_pointer (&priv->hostname, g_free);
c48088
 	priv->hostname = g_strdup (hostname);
c48088
diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h
c48088
index 02804002f..2c6341682 100644
c48088
--- a/src/dhcp/nm-dhcp-client.h
c48088
+++ b/src/dhcp/nm-dhcp-client.h
c48088
@@ -173,7 +173,14 @@ gboolean nm_dhcp_client_handle_event (gpointer unused,
c48088
                                       const char *reason,
c48088
                                       NMDhcpClient *self);
c48088
 
c48088
-void nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id);
c48088
+void nm_dhcp_client_set_client_id (NMDhcpClient *self,
c48088
+                                   GBytes *client_id);
c48088
+void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
c48088
+                                       guint8 type,
c48088
+                                       const guint8 *client_id,
c48088
+                                       gsize len);
c48088
+void nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
c48088
+                                       const char *dhcp_client_id);
c48088
 
c48088
 /*****************************************************************************
c48088
  * Client data
c48088
diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c
c48088
index e63e6a869..4df90d76a 100644
c48088
--- a/src/dhcp/nm-dhcp-dhclient-utils.c
c48088
+++ b/src/dhcp/nm-dhcp-dhclient-utils.c
c48088
@@ -178,7 +178,7 @@ read_client_id (const char *str)
c48088
 	gs_free char *s = NULL;
c48088
 	char *p;
c48088
 
c48088
-	g_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
c48088
+	nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
c48088
 
c48088
 	str += NM_STRLEN (CLIENTID_TAG);
c48088
 	while (g_ascii_isspace (*str))
c48088
@@ -198,6 +198,9 @@ read_client_id (const char *str)
c48088
 	if (s[strlen (s) - 1] == ';')
c48088
 		s[strlen (s) - 1] = '\0';
c48088
 
c48088
+	if (!s[0])
c48088
+		return NULL;
c48088
+
c48088
 	return nm_dhcp_utils_client_id_string_to_bytes (s);
c48088
 }
c48088
 
c48088
@@ -329,8 +332,7 @@ nm_dhcp_dhclient_create_config (const char *interface,
c48088
 					continue;
c48088
 
c48088
 				/* Otherwise capture and return the existing client id */
c48088
-				if (out_new_client_id)
c48088
-					*out_new_client_id = read_client_id (p);
c48088
+				NM_SET_OUT (out_new_client_id, read_client_id (p));
c48088
 			}
c48088
 
c48088
 			/* Override config file hostname and use one from the connection */
c48088
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
c48088
index 9b1a44332..f79b7cb1e 100644
c48088
--- a/src/dhcp/nm-dhcp-systemd.c
c48088
+++ b/src/dhcp/nm-dhcp-systemd.c
c48088
@@ -489,19 +489,13 @@ _save_client_id (NMDhcpSystemd *self,
c48088
                  const uint8_t *client_id,
c48088
                  size_t len)
c48088
 {
c48088
-	gs_unref_bytes GBytes *b = NULL;
c48088
-	gs_free char *buf = NULL;
c48088
-
c48088
 	g_return_if_fail (self != NULL);
c48088
 	g_return_if_fail (client_id != NULL);
c48088
 	g_return_if_fail (len > 0);
c48088
 
c48088
 	if (!nm_dhcp_client_get_client_id (NM_DHCP_CLIENT (self))) {
c48088
-		buf = g_malloc (len + 1);
c48088
-		buf[0] = type;
c48088
-		memcpy (buf + 1, client_id, len);
c48088
-		b = g_bytes_new (buf, len + 1);
c48088
-		nm_dhcp_client_set_client_id (NM_DHCP_CLIENT (self), b);
c48088
+		nm_dhcp_client_set_client_id_bin (NM_DHCP_CLIENT (self),
c48088
+		                                  type, client_id, len);
c48088
 	}
c48088
 }
c48088
 
c48088
@@ -543,7 +537,7 @@ bound4_handle (NMDhcpSystemd *self)
c48088
 		add_requests_to_options (options, dhcp4_requests);
c48088
 		dhcp_lease_save (lease, priv->lease_file);
c48088
 
c48088
-		sd_dhcp_client_get_client_id(priv->client4, &type, &client_id, &client_id_len);
c48088
+		sd_dhcp_client_get_client_id (priv->client4, &type, &client_id, &client_id_len);
c48088
 		if (client_id)
c48088
 			_save_client_id (self, type, client_id, client_id_len);
c48088
 
c48088
@@ -691,14 +685,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
c48088
 	override_client_id = nm_dhcp_client_get_client_id (client);
c48088
 	if (override_client_id) {
c48088
 		client_id = g_bytes_get_data (override_client_id, &client_id_len);
c48088
-		g_assert (client_id && client_id_len);
c48088
+		nm_assert (client_id && client_id_len >= 2);
c48088
 		sd_dhcp_client_set_client_id (priv->client4,
c48088
 		                              client_id[0],
c48088
 		                              client_id + 1,
c48088
-		                              client_id_len - 1);
c48088
+		                              NM_MIN (client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN));
c48088
 	} else if (lease) {
c48088
 		r = sd_dhcp_lease_get_client_id (lease, (const void **) &client_id, &client_id_len);
c48088
-		if (r == 0 && client_id_len) {
c48088
+		if (r == 0 && client_id_len >= 2) {
c48088
 			sd_dhcp_client_set_client_id (priv->client4,
c48088
 			                              client_id[0],
c48088
 			                              client_id + 1,
c48088
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
c48088
index 4b2d57b90..50ca2abe2 100644
c48088
--- a/src/dhcp/nm-dhcp-utils.c
c48088
+++ b/src/dhcp/nm-dhcp-utils.c
c48088
@@ -750,8 +750,15 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id)
c48088
 	g_return_val_if_fail (client_id && client_id[0], NULL);
c48088
 
c48088
 	/* Try as hex encoded */
c48088
-	if (strchr (client_id, ':'))
c48088
+	if (strchr (client_id, ':')) {
c48088
 		bytes = nm_utils_hexstr2bin (client_id);
c48088
+
c48088
+		/* the result must be at least two bytes long,
c48088
+		 * because @client_id contains a delimiter
c48088
+		 * but nm_utils_hexstr2bin() does not allow
c48088
+		 * leading nor trailing delimiters. */
c48088
+		nm_assert (!bytes || g_bytes_get_size (bytes) >= 2);
c48088
+	}
c48088
 	if (!bytes) {
c48088
 		/* Fall back to string */
c48088
 		len = strlen (client_id);
c48088
diff --git a/src/nm-types.h b/src/nm-types.h
c48088
index cc657397e..02163f87e 100644
c48088
--- a/src/nm-types.h
c48088
+++ b/src/nm-types.h
c48088
@@ -25,6 +25,8 @@
c48088
 #error "nm-utils-private.h" must not be used outside of libnm-core/. Do you want "nm-core-internal.h"?
c48088
 #endif
c48088
 
c48088
+#define _NM_SD_MAX_CLIENT_ID_LEN (sizeof (guint32) + 128)
c48088
+
c48088
 /* core */
c48088
 typedef struct _NMExportedObject     NMExportedObject;
c48088
 typedef struct _NMActiveConnection   NMActiveConnection;
c48088
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
c48088
index fc6ad422d..5eab00502 100644
c48088
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
c48088
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
c48088
@@ -311,6 +311,7 @@ int sd_dhcp_client_set_client_id(
c48088
         assert_return(client, -EINVAL);
c48088
         assert_return(data, -EINVAL);
c48088
         assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
c48088
+        G_STATIC_ASSERT_EXPR (_NM_SD_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN);
c48088
 
c48088
         switch (type) {
c48088
 
c48088
-- 
c48088
2.14.3
c48088
c48088
c48088
From 161a554575f0e043ecf2d50b6108fa102fa9a982 Mon Sep 17 00:00:00 2001
c48088
From: Thomas Haller <thaller@redhat.com>
c48088
Date: Tue, 9 Jan 2018 15:55:23 +0100
c48088
Subject: [PATCH 2/2] dhcp: fix check for client-id in _set_client_id()
c48088
c48088
Fixes: 686afe531ab3774cd818feda8361de74101971f5
c48088
(cherry picked from commit 0e1fb1dbd282f546820c1ab8326cf4cf550ae2ae)
c48088
(cherry picked from commit 8998ce629da8954a15c3cfc9aadb0d74bbcc116b)
c48088
---
c48088
 src/dhcp/nm-dhcp-client.c | 1 +
c48088
 1 file changed, 1 insertion(+)
c48088
c48088
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c
c48088
index 1f19db148..ea3938d63 100644
c48088
--- a/src/dhcp/nm-dhcp-client.c
c48088
+++ b/src/dhcp/nm-dhcp-client.c
c48088
@@ -195,6 +195,7 @@ _set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take)
c48088
 
c48088
 	if (   priv->client_id == client_id
c48088
 	    || (   priv->client_id
c48088
+	        && client_id
c48088
 	        && g_bytes_equal (priv->client_id, client_id))) {
c48088
 		if (take && client_id)
c48088
 			g_bytes_unref (client_id);
c48088
-- 
c48088
2.14.3
c48088