From f94c3736cd1c84aacaea1879154a0acdb58667d0 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 18 Feb 2016 18:19:30 +0100 Subject: [PATCH 1/3] core: use hostnamed to set the transient hostname In commit 6dc35e66d45e ("settings: add hostnamed support") we started to use systemd-hostnamed for setting the system static hostname (i.e. the one written to /etc/hostname), but nm-policy.c still called sethostname() to set the transient (dynamic) hostname when this needs to be changed, for example after a reverse lookup of our dynamic IP address. Thus, when using systemd the hostname change failed because process' capabilities are restricted and sethostname() requires CAP_SYS_ADMIN. We should set also the transient hostname through hostnamed when this is available. https://bugzilla.redhat.com/show_bug.cgi?id=1308974 --- src/nm-policy.c | 45 ++++++++++++++++++++++++----------- src/settings/nm-settings.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/settings/nm-settings.h | 7 ++++++ 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/src/nm-policy.c b/src/nm-policy.c index 68e50a1..cfb140f 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -118,9 +118,32 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) #define FALLBACK_HOSTNAME4 "localhost.localdomain" -static gboolean -set_system_hostname (const char *new_hostname, const char *msg) +static void settings_set_hostname_cb (const char *hostname, + gboolean result, + gpointer user_data) { + int ret = 0; + + if (!result) { + ret = sethostname (hostname, strlen (hostname)); + if (ret != 0) { + int errsv = errno; + + nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", + hostname, errsv, strerror (errsv)); + if (errsv == EPERM) + nm_log_warn (LOGD_DNS, "you should use hostnamed when systemd hardening is in effect!"); + } + } + + if (!ret) + nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); +} + +static void +set_system_hostname (NMPolicy *self, const char *new_hostname, const char *msg) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); char old_hostname[HOST_NAME_MAX + 1]; const char *name; int ret; @@ -138,21 +161,16 @@ set_system_hostname (const char *new_hostname, const char *msg) /* Don't set the hostname if it isn't actually changing */ if ( (new_hostname && !strcmp (old_hostname, new_hostname)) || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) - return FALSE; + return; } name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg); - ret = sethostname (name, strlen (name)); - if (ret != 0) { - int errsv = errno; - - nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s", - name, errsv, strerror (errsv)); - if (errsv == EPERM) - nm_log_warn (LOGD_DNS, "You should use hostnamed when systemd hardening is in effect!"); - } + nm_settings_set_transient_hostname (priv->settings, + name, + settings_set_hostname_cb, + NULL); return (ret == 0); } @@ -196,8 +214,7 @@ _set_hostname (NMPolicy *policy, nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname); - if (set_system_hostname (priv->cur_hostname, msg)) - nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL); + set_system_hostname (policy, priv->cur_hostname, msg); } static void diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index ee48e71..f79bbfa 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1525,6 +1525,65 @@ impl_settings_reload_connections (NMSettings *self, g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE)); } +typedef struct { + char *hostname; + NMSettingsSetHostnameCb cb; + gpointer user_data; +} SetHostnameInfo; + +static void +set_transient_hostname_done (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GDBusProxy *proxy = G_DBUS_PROXY (object); + gs_free SetHostnameInfo *info = user_data; + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; + + result = g_dbus_proxy_call_finish (proxy, res, &error); + + if (error) { + nm_log_warn (LOGD_SETTINGS, "couldn't set the system hostname to '%s' using hostnamed: %s", + info->hostname, error->message); + } + + info->cb (info->hostname, !error, info->user_data); + g_free (info->hostname); +} + +void +nm_settings_set_transient_hostname (NMSettings *self, + const char *hostname, + NMSettingsSetHostnameCb cb, + gpointer user_data) +{ + NMSettingsPrivate *priv; + SetHostnameInfo *info; + + g_return_if_fail (NM_IS_SETTINGS (self)); + priv = NM_SETTINGS_GET_PRIVATE (self); + + if (!priv->hostname.hostnamed_proxy) { + cb (hostname, FALSE, user_data); + return; + } + + info = g_new0 (SetHostnameInfo, 1); + info->hostname = g_strdup (hostname); + info->cb = cb; + info->user_data = user_data; + + g_dbus_proxy_call (priv->hostname.hostnamed_proxy, + "SetHostname", + g_variant_new ("(sb)", hostname, FALSE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + set_transient_hostname_done, + info); +} + static gboolean write_hostname (NMSettingsPrivate *priv, const char *hostname) { diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 923b164..051c209 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -71,6 +71,8 @@ typedef struct { void (*agent_registered) (NMSettings *self, NMSecretAgent *agent); } NMSettingsClass; +typedef void (*NMSettingsSetHostnameCb) (const char *name, gboolean result, gpointer user_data); + GType nm_settings_get_type (void); NMSettings *nm_settings_new (void); @@ -127,4 +129,9 @@ gint nm_settings_sort_connections (gconstpointer a, gconstpointer b); gboolean nm_settings_get_startup_complete (NMSettings *self); +void nm_settings_set_transient_hostname (NMSettings *self, + const char *hostname, + NMSettingsSetHostnameCb cb, + gpointer user_data); + #endif /* __NM_SETTINGS_H__ */ -- 2.5.0