From e7e55dbdc38f929805ab2407fbd50886043a9e7c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 14 Jun 2015 15:08:52 +0200 Subject: tree-wide: fix memory leaks in users of bus_map_all_properties() If you use bus_map_all_properties(), you must be aware that it might touch output variables even though it may fail. This is, because we parse many different bus-properties and cannot tell how to clean them up, in case we fail deep down in the parser. Fix all callers of bus_map_all_properties() to correctly cleanup any context structures at all times. --- src/locale/localectl.c | 35 +++++++++------ src/login/loginctl.c | 105 +++++++++++++++++++++++++++++---------------- src/machine/machinectl.c | 48 ++++++++++++++------- src/systemctl/systemctl.c | 21 +++++---- src/timedate/timedatectl.c | 17 +++++--- 5 files changed, 144 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 8c60339e3e..601839d5dc 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -69,14 +69,27 @@ static void polkit_agent_open_if_enabled(void) { typedef struct StatusInfo { char **locale; - const char *vconsole_keymap; - const char *vconsole_keymap_toggle; - const char *x11_layout; - const char *x11_model; - const char *x11_variant; - const char *x11_options; + char *vconsole_keymap; + char *vconsole_keymap_toggle; + char *x11_layout; + char *x11_model; + char *x11_variant; + char *x11_options; } StatusInfo; +static void status_info_clear(StatusInfo *info) { + if (info) { + strv_free(info->locale); + free(info->vconsole_keymap); + free(info->vconsole_keymap_toggle); + free(info->x11_layout); + free(info->x11_model); + free(info->x11_variant); + free(info->x11_options); + zero(*info); + } +} + static void print_overridden_variables(void) { int r; char *variables[_VARIABLE_LC_MAX] = {}; @@ -150,7 +163,7 @@ static void print_status_info(StatusInfo *i) { } static int show_status(sd_bus *bus, char **args, unsigned n) { - StatusInfo info = {}; + _cleanup_(status_info_clear) StatusInfo info = {}; static const struct bus_properties_map map[] = { { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) }, { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) }, @@ -171,16 +184,12 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { "/org/freedesktop/locale1", map, &info); - if (r < 0) { - log_error_errno(r, "Could not get properties: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Could not get properties: %m"); print_overridden_variables(); print_status_info(&info); -fail: - strv_free(info.locale); return r; } diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 02d240c704..06208bc4b3 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -277,42 +277,81 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit } typedef struct SessionStatusInfo { - const char *id; + char *id; uid_t uid; - const char *name; + char *name; struct dual_timestamp timestamp; unsigned int vtnr; - const char *seat; - const char *tty; - const char *display; + char *seat; + char *tty; + char *display; bool remote; - const char *remote_host; - const char *remote_user; - const char *service; + char *remote_host; + char *remote_user; + char *service; pid_t leader; - const char *type; - const char *class; - const char *state; - const char *scope; - const char *desktop; + char *type; + char *class; + char *state; + char *scope; + char *desktop; } SessionStatusInfo; typedef struct UserStatusInfo { uid_t uid; - const char *name; + char *name; struct dual_timestamp timestamp; - const char *state; + char *state; char **sessions; - const char *display; - const char *slice; + char *display; + char *slice; } UserStatusInfo; typedef struct SeatStatusInfo { - const char *id; - const char *active_session; + char *id; + char *active_session; char **sessions; } SeatStatusInfo; +static void session_status_info_clear(SessionStatusInfo *info) { + if (info) { + free(info->id); + free(info->name); + free(info->seat); + free(info->tty); + free(info->display); + free(info->remote_host); + free(info->remote_user); + free(info->service); + free(info->type); + free(info->class); + free(info->state); + free(info->scope); + free(info->desktop); + zero(*info); + } +} + +static void user_status_info_clear(UserStatusInfo *info) { + if (info) { + free(info->name); + free(info->state); + strv_free(info->sessions); + free(info->display); + free(info->slice); + zero(*info); + } +} + +static void seat_status_info_clear(SeatStatusInfo *info) { + if (info) { + free(info->id); + free(info->active_session); + strv_free(info->sessions); + zero(*info); + } +} + static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { const char *contents; int r; @@ -404,7 +443,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; - SessionStatusInfo i = {}; + _cleanup_(session_status_info_clear) SessionStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); @@ -532,14 +571,12 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; - UserStatusInfo i = {}; + _cleanup_(user_status_info_clear) UserStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); - if (r < 0) { - log_error_errno(r, "Could not get properties: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); @@ -594,10 +631,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) NULL); } -finish: - strv_free(i.sessions); - - return r; + return 0; } static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) { @@ -609,14 +643,12 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) {} }; - SeatStatusInfo i = {}; + _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; int r; r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &i); - if (r < 0) { - log_error_errno(r, "Could not get properties: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not get properties: %m"); if (*new_line) printf("\n"); @@ -653,10 +685,7 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) show_sysfs(i.id, "\t\t ", c); } -finish: - strv_free(i.sessions); - - return r; + return 0; } static int show_properties(sd_bus *bus, const char *path, bool *new_line) { diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index c86c36c2de..719eb10932 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -500,6 +500,18 @@ typedef struct MachineStatusInfo { unsigned n_netif; } MachineStatusInfo; +static void machine_status_info_clear(MachineStatusInfo *info) { + if (info) { + free(info->name); + free(info->class); + free(info->service); + free(info->unit); + free(info->root_directory); + free(info->netif); + zero(*info); + } +} + static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; @@ -636,7 +648,7 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo {} }; - MachineStatusInfo info = {}; + _cleanup_(machine_status_info_clear) MachineStatusInfo info = {}; int r; assert(verb); @@ -658,13 +670,6 @@ static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bo print_machine_status_info(bus, &info); - free(info.name); - free(info.class); - free(info.service); - free(info.unit); - free(info.root_directory); - free(info.netif); - return r; } @@ -753,6 +758,15 @@ typedef struct ImageStatusInfo { uint64_t limit_exclusive; } ImageStatusInfo; +static void image_status_info_clear(ImageStatusInfo *info) { + if (info) { + free(info->name); + free(info->path); + free(info->type); + zero(*info); + } +} + static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) { char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2; @@ -823,7 +837,7 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { {} }; - ImageStatusInfo info = {}; + _cleanup_(image_status_info_clear) ImageStatusInfo info = {}; int r; assert(bus); @@ -844,10 +858,6 @@ static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { print_image_status_info(bus, &info); - free(info.name); - free(info.path); - free(info.type); - return r; } @@ -857,6 +867,15 @@ typedef struct PoolStatusInfo { uint64_t limit; } PoolStatusInfo; +static void pool_status_info_clear(PoolStatusInfo *info) { + if (info) { + free(info->path); + zero(*info); + info->usage = -1; + info->limit = -1; + } +} + static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) { char bs[FORMAT_BYTES_MAX], *s; @@ -881,7 +900,7 @@ static int show_pool_info(sd_bus *bus) { {} }; - PoolStatusInfo info = { + _cleanup_(pool_status_info_clear) PoolStatusInfo info = { .usage = (uint64_t) -1, .limit = (uint64_t) -1, }; @@ -899,7 +918,6 @@ static int show_pool_info(sd_bus *bus) { print_pool_status_info(bus, &info); - free(info.path); return 0; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 5075e4e176..a2eb435fce 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1678,17 +1678,23 @@ static const struct bus_properties_map machine_info_property_map[] = { {} }; +static void machine_info_clear(struct machine_info *info) { + if (info) { + free(info->name); + free(info->state); + free(info->control_group); + zero(*info); + } +} + static void free_machines_list(struct machine_info *machine_infos, int n) { int i; if (!machine_infos) return; - for (i = 0; i < n; i++) { - free(machine_infos[i].name); - free(machine_infos[i].state); - free(machine_infos[i].control_group); - } + for (i = 0; i < n; i++) + machine_info_clear(&machine_infos[i]); free(machine_infos); } @@ -4402,7 +4408,7 @@ static int show_all( static int show_system_status(sd_bus *bus) { char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX]; _cleanup_free_ char *hn = NULL; - struct machine_info mi = {}; + _cleanup_(machine_info_clear) struct machine_info mi = {}; const char *on, *off; int r; @@ -4449,9 +4455,6 @@ static int show_system_status(sd_bus *bus) { show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags()); } - free(mi.state); - free(mi.control_group); - return 0; } diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 61b6e765c7..195d5f3892 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -73,6 +73,13 @@ typedef struct StatusInfo { bool ntp_synced; } StatusInfo; +static void status_info_clear(StatusInfo *info) { + if (info) { + free(info->timezone); + zero(*info); + } +} + static void print_status_info(const StatusInfo *i) { char a[FORMAT_TIMESTAMP_MAX]; struct tm tm; @@ -155,7 +162,7 @@ static void print_status_info(const StatusInfo *i) { } static int show_status(sd_bus *bus, char **args, unsigned n) { - StatusInfo info = {}; + _cleanup_(status_info_clear) StatusInfo info = {}; static const struct bus_properties_map map[] = { { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, @@ -175,15 +182,11 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { "/org/freedesktop/timedate1", map, &info); - if (r < 0) { - log_error_errno(r, "Failed to query server: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to query server: %m"); print_status_info(&info); -fail: - free(info.timezone); return r; } -- cgit v1.2.3-54-g00ecf