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