X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fhostname%2Fhostnamed.c;h=25e154b224870f1e54feb531a20e869fe7f9c3d8;hp=7dab5f40df14a7db591a655e6afa36a5ac52a87c;hb=c6a818c82035da91e;hpb=669241a076108e0483d7d8475beaa506106d077e diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 7dab5f40d..25e154b22 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -32,6 +32,9 @@ #include "polkit.h" #include "def.h" #include "virt.h" +#include "env-util.h" +#include "fileio-label.h" +#include "label.h" #define INTERFACE \ " \n" \ @@ -39,6 +42,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -55,6 +59,10 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" #define INTROSPECTION \ @@ -77,6 +85,7 @@ enum { PROP_STATIC_HOSTNAME, PROP_PRETTY_HOSTNAME, PROP_ICON_NAME, + PROP_CHASSIS, _PROP_MAX }; @@ -84,6 +93,7 @@ static char *data[_PROP_MAX] = { NULL, NULL, NULL, + NULL, NULL }; @@ -114,6 +124,7 @@ static int read_data(void) { r = parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME], "ICON_NAME", &data[PROP_ICON_NAME], + "CHASSIS", &data[PROP_CHASSIS], NULL); if (r < 0 && r != -ENOENT) return r; @@ -122,10 +133,10 @@ static int read_data(void) { } static bool check_nss(void) { - void *dl; - if ((dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY))) { + dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY); + if (dl) { dlclose(dl); return true; } @@ -133,25 +144,90 @@ static bool check_nss(void) { return false; } -static const char* fallback_icon_name(void) { +static bool valid_chassis(const char *chassis) { + + assert(chassis); + + return nulstr_contains( + "vm\0" + "container\0" + "desktop\0" + "laptop\0" + "server\0" + "tablet\0" + "handset\0", + chassis); +} + +static bool pretty_string_is_safe(const char *p) { + const char *t; + + assert(p); + + for (t = p; *t; t++) { + if (*t >= '\0' && *t < ' ') + return false; + } + + return true; +} -#if defined(__i386__) || defined(__x86_64__) +static const char* fallback_chassis(void) { int r; char *type; unsigned t; -#endif + Virtualization v; + + v = detect_virtualization(NULL); + + if (v == VIRTUALIZATION_VM) + return "vm"; + if (v == VIRTUALIZATION_CONTAINER) + return "container"; + + r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); + if (r < 0) + goto try_dmi; + + r = safe_atou(type, &t); + free(type); + if (r < 0) + goto try_dmi; + + /* We only list the really obvious cases here as the ACPI data + * is not really super reliable. + * + * See the ACPI 5.0 Spec Section 5.2.9.1 for details: + * + * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf + */ + + switch(t) { + + case 1: + case 3: + case 6: + return "desktop"; + + case 2: + return "laptop"; - if (detect_virtualization(NULL) > 0) - return "computer-vm"; + case 4: + case 5: + case 7: + return "server"; -#if defined(__i386__) || defined(__x86_64__) + case 8: + return "tablet"; + } + +try_dmi: r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); if (r < 0) return NULL; r = safe_atou(type, &t); free(type); - if (r < 0) return NULL; @@ -171,22 +247,38 @@ static const char* fallback_icon_name(void) { case 0x4: case 0x6: case 0x7: - return "computer-desktop"; + return "desktop"; + case 0x8: case 0x9: case 0xA: case 0xE: - return "computer-laptop"; + return "laptop"; + + case 0xB: + return "handset"; case 0x11: case 0x1C: - return "computer-server"; + return "server"; } -#endif return NULL; } +static char* fallback_icon_name(void) { + const char *chassis; + + if (!isempty(data[PROP_CHASSIS])) + return strappend("computer-", data[PROP_CHASSIS]); + + chassis = fallback_chassis(); + if (chassis) + return strappend("computer-", chassis); + + return strdup("computer"); +} + static int write_data_hostname(void) { const char *hn; @@ -210,15 +302,15 @@ static int write_data_static_hostname(void) { return 0; } - - return write_one_line_file_atomic("/etc/hostname", data[PROP_STATIC_HOSTNAME]); + return write_one_line_file_atomic_label("/etc/hostname", data[PROP_STATIC_HOSTNAME]); } static int write_data_other(void) { static const char * const name[_PROP_MAX] = { [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME", - [PROP_ICON_NAME] = "ICON_NAME" + [PROP_ICON_NAME] = "ICON_NAME", + [PROP_CHASSIS] = "CHASSIS" }; char **l = NULL; @@ -260,7 +352,7 @@ static int write_data_other(void) { return 0; } - r = write_env_file("/etc/machine-info", l); + r = write_env_file_label("/etc/machine-info", l); strv_free(l); return r; @@ -268,23 +360,39 @@ static int write_data_other(void) { static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) { const char *name; + _cleanup_free_ char *n = NULL; assert(i); assert(property); if (isempty(data[PROP_ICON_NAME])) - name = fallback_icon_name(); + name = n = fallback_icon_name(); else name = data[PROP_ICON_NAME]; return bus_property_append_string(i, property, (void*) name); } +static int bus_hostname_append_chassis(DBusMessageIter *i, const char *property, void *userdata) { + const char *name; + + assert(i); + assert(property); + + if (isempty(data[PROP_CHASSIS])) + name = fallback_chassis(); + else + name = data[PROP_CHASSIS]; + + return bus_property_append_string(i, property, (void*) name); +} + static const BusProperty bus_hostname_properties[] = { { "Hostname", bus_property_append_string, "s", sizeof(data[0])*PROP_HOSTNAME, true }, { "StaticHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_STATIC_HOSTNAME, true }, { "PrettyHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_PRETTY_HOSTNAME, true }, { "IconName", bus_hostname_append_icon_name, "s", sizeof(data[0])*PROP_ICON_NAME, true }, + { "Chassis", bus_hostname_append_chassis, "s", sizeof(data[0])*PROP_CHASSIS, true }, { NULL, } }; @@ -414,7 +522,8 @@ static DBusHandlerResult hostname_message_handler( } } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") || - dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) { + dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName") || + dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetChassis")) { const char *name; dbus_bool_t interactive; @@ -431,7 +540,8 @@ static DBusHandlerResult hostname_message_handler( if (isempty(name)) name = NULL; - k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME; + k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : + streq(dbus_message_get_member(message), "SetChassis") ? PROP_CHASSIS : PROP_ICON_NAME; if (!streq_ptr(name, data[k])) { @@ -451,6 +561,16 @@ static DBusHandlerResult hostname_message_handler( } else { char *h; + /* The icon name might ultimately be + * used as file name, so better be + * safe than sorry */ + if (k == PROP_ICON_NAME && !filename_is_safe(name)) + return bus_send_error_reply(connection, message, NULL, -EINVAL); + if (k == PROP_PRETTY_HOSTNAME && !pretty_string_is_safe(name)) + return bus_send_error_reply(connection, message, NULL, -EINVAL); + if (k == PROP_CHASSIS && !valid_chassis(name)) + return bus_send_error_reply(connection, message, NULL, -EINVAL); + h = strdup(name); if (!h) goto oom; @@ -465,12 +585,15 @@ static DBusHandlerResult hostname_message_handler( return bus_send_error_reply(connection, message, NULL, r); } - log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", strempty(data[k])); + log_info("Changed %s to '%s'", + k == PROP_PRETTY_HOSTNAME ? "pretty host name" : + k == PROP_CHASSIS ? "chassis" : "icon name", strempty(data[k])); changed = bus_properties_changed_new( "/org/freedesktop/hostname1", "org.freedesktop.hostname1", - k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0"); + k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : + k == PROP_CHASSIS ? "Chassis\0" : "IconName\0"); if (!changed) goto oom; } @@ -478,10 +601,11 @@ static DBusHandlerResult hostname_message_handler( } else return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps); - if (!(reply = dbus_message_new_method_return(message))) + reply = dbus_message_new_method_return(message); + if (!reply) goto oom; - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; dbus_message_unref(reply); @@ -532,8 +656,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } @@ -574,6 +697,7 @@ int main(int argc, char *argv[]) { log_open(); umask(0022); + label_init("/etc"); if (argc == 2 && streq(argv[1], "--introspect")) { fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE