dcavalca / rpms / systemd

Forked from rpms/systemd 4 months ago
Clone
Zbigniew Jędrzejewski-Szmek 62fe94
From 28efac0d37ceb5093a804da6a00c620034c5484f Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Wed, 3 Sep 2014 10:28:24 -0400
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] localed: double free in error path and modernization
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
Very unlikely to trigger, but in principle strv_free
Zbigniew Jędrzejewski-Szmek 62fe94
could be called twice: once explictly, and once from cleanup.
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/locale/localed.c | 66 +++++++++++++++++-----------------------------------
Zbigniew Jędrzejewski-Szmek 62fe94
 1 file changed, 21 insertions(+), 45 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/locale/localed.c b/src/locale/localed.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 4d22568787..c9f7105bb3 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/locale/localed.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/locale/localed.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -208,7 +208,7 @@ static int vconsole_read_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int x11_read_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
-        FILE *f;
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_fclose_ FILE *f;
Zbigniew Jędrzejewski-Szmek 62fe94
         char line[LINE_MAX];
Zbigniew Jędrzejewski-Szmek 62fe94
         bool in_section = false;
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -229,13 +229,11 @@ static int x11_read_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         continue;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (in_section && first_word(l, "Option")) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        char **a;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        _cleanup_strv_free_ char **a = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         r = strv_split_quoted(&a, l);
Zbigniew Jędrzejewski-Szmek 62fe94
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                                fclose(f);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                                 return r;
Zbigniew Jędrzejewski-Szmek 62fe94
-                        }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (strv_length(a) == 3) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 if (streq(a[1], "XkbLayout")) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -253,27 +251,20 @@ static int x11_read_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 }
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        strv_free(a);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 } else if (!in_section && first_word(l, "Section")) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        char **a;
Zbigniew Jędrzejewski-Szmek 62fe94
+                        _cleanup_strv_free_ char **a = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         r = strv_split_quoted(&a, l);
Zbigniew Jędrzejewski-Szmek 62fe94
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                                fclose(f);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                                 return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
-                        }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (strv_length(a) == 2 && streq(a[1], "InputClass"))
Zbigniew Jędrzejewski-Szmek 62fe94
                                 in_section = true;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        strv_free(a);
Zbigniew Jędrzejewski-Szmek 62fe94
                 } else if (in_section && first_word(l, "EndSection"))
Zbigniew Jędrzejewski-Szmek 62fe94
                         in_section = false;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        fclose(f);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
         return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -289,14 +280,15 @@ static int context_read_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int locale_write_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
         int r, p;
Zbigniew Jędrzejewski-Szmek 62fe94
-        char **l = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_strv_free_ char **l = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         r = load_env_file(NULL, "/etc/locale.conf", NULL, &l);
Zbigniew Jędrzejewski-Szmek 62fe94
         if (r < 0 && r != -ENOENT)
Zbigniew Jędrzejewski-Szmek 62fe94
                 return r;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         for (p = 0; p < _LOCALE_MAX; p++) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                char *t, **u;
Zbigniew Jędrzejewski-Szmek 62fe94
+                _cleanup_free_ char *t = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                char **u;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 assert(names[p]);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -305,34 +297,25 @@ static int locale_write_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         continue;
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
-                }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 u = strv_env_set(l, t);
Zbigniew Jędrzejewski-Szmek 62fe94
-                free(t);
Zbigniew Jędrzejewski-Szmek 62fe94
-                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (!u)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
                 l = u;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (strv_isempty(l)) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (unlink("/etc/locale.conf") < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return errno == ENOENT ? 0 : -errno;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        r = write_env_file_label("/etc/locale.conf", l);
Zbigniew Jędrzejewski-Szmek 62fe94
-        strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return write_env_file_label("/etc/locale.conf", l);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int locale_update_system_manager(Context *c, sd_bus *bus) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -403,38 +386,36 @@ static int vconsole_write_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
         if (isempty(c->vc_keymap))
Zbigniew Jędrzejewski-Szmek 62fe94
                 l = strv_env_unset(l, "KEYMAP");
Zbigniew Jędrzejewski-Szmek 62fe94
         else {
Zbigniew Jędrzejewski-Szmek 62fe94
-                char *s, **u;
Zbigniew Jędrzejewski-Szmek 62fe94
+                _cleanup_free_ char *s = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                char **u;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 s = strappend("KEYMAP=", c->vc_keymap);
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (!s)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 u = strv_env_set(l, s);
Zbigniew Jędrzejewski-Szmek 62fe94
-                free(s);
Zbigniew Jędrzejewski-Szmek 62fe94
-                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (!u)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
                 l = u;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (isempty(c->vc_keymap_toggle))
Zbigniew Jędrzejewski-Szmek 62fe94
                 l = strv_env_unset(l, "KEYMAP_TOGGLE");
Zbigniew Jędrzejewski-Szmek 62fe94
         else  {
Zbigniew Jędrzejewski-Szmek 62fe94
-                char *s, **u;
Zbigniew Jędrzejewski-Szmek 62fe94
+                _cleanup_free_ char *s = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+                char **u;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (!s)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 u = strv_env_set(l, s);
Zbigniew Jędrzejewski-Szmek 62fe94
-                free(s);
Zbigniew Jędrzejewski-Szmek 62fe94
-                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (!u)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+                strv_free(l);
Zbigniew Jędrzejewski-Szmek 62fe94
                 l = u;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -445,8 +426,7 @@ static int vconsole_write_data(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        r = write_env_file_label("/etc/vconsole.conf", l);
Zbigniew Jędrzejewski-Szmek 62fe94
-        return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+        return write_env_file_label("/etc/vconsole.conf", l);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int write_data_x11(Context *c) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -868,13 +848,12 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         /* Check whether a variable is unset */
Zbigniew Jędrzejewski-Szmek 62fe94
-        if (!modified)  {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!modified)
Zbigniew Jędrzejewski-Szmek 62fe94
                 for (p = 0; p < _LOCALE_MAX; p++)
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (!isempty(c->locale[p]) && !passed[p]) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 modified = true;
Zbigniew Jędrzejewski-Szmek 62fe94
                                 break;
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94
-        }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (modified) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 r = bus_verify_polkit_async(m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-locale", interactive, &c->polkit_registry, error);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -883,7 +862,7 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
Zbigniew Jędrzejewski-Szmek 62fe94
                 if (r == 0)
Zbigniew Jędrzejewski-Szmek 62fe94
                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                STRV_FOREACH(i, l) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                STRV_FOREACH(i, l)
Zbigniew Jędrzejewski-Szmek 62fe94
                         for (p = 0; p < _LOCALE_MAX; p++) {
Zbigniew Jędrzejewski-Szmek 62fe94
                                 size_t k;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -900,7 +879,6 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
Zbigniew Jędrzejewski-Szmek 62fe94
                                         break;
Zbigniew Jędrzejewski-Szmek 62fe94
                                 }
Zbigniew Jędrzejewski-Szmek 62fe94
                         }
Zbigniew Jędrzejewski-Szmek 62fe94
-                }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 for (p = 0; p < _LOCALE_MAX; p++) {
Zbigniew Jędrzejewski-Szmek 62fe94
                         if (passed[p])
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1112,7 +1090,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
-        Context context = {};
Zbigniew Jędrzejewski-Szmek 62fe94
+        _cleanup_(context_free) Context context = {};
Zbigniew Jędrzejewski-Szmek 62fe94
         _cleanup_event_unref_ sd_event *event = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1155,7 +1133,5 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 finish:
Zbigniew Jędrzejewski-Szmek 62fe94
-        context_free(&context);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Zbigniew Jędrzejewski-Szmek 62fe94
 }