shared: systemd: Fix use-after-free and double-free defects 74/120074/5
authorWook Song <wook16.song@samsung.com>
Tue, 21 Mar 2017 06:51:12 +0000 (15:51 +0900)
committerWook Song <wook16.song@samsung.com>
Mon, 27 Mar 2017 06:25:30 +0000 (15:25 +0900)
This patch fixes the following code-leve defects according to static
program analysis result:

1. USE_AFTER_FREE: A pointer variable is used after the referenced
memory was deallocated by calling function 'free'.
2. DOUBLE_FREE.EX: A pointer is passed to the function 'free' after the
referenced memory was deallocated.

Change-Id: Ieef15d3432fb72068b9186c5807fedd1685ee79a
Signed-off-by: Wook Song <wook16.song@samsung.com>
Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
src/shared/pass-systemd.c

index b3a3c1234f0e8ac473885251508627efa6164558..d43f7f602a6dfa9b6c1d9e1fe3d8339ca781fc3f 100644 (file)
@@ -155,15 +155,16 @@ int pass_systemd_stop_unit(char *name)
        return pass_systemd_start_or_stop_unit("StopUnit", name);
 }
 
-static char *pass_systemd_get_unit_dbus_path(const char *unit)
+static void pass_systemd_get_unit_dbus_path(const char *unit,
+               char *path, int max_path_len)
 {
-       char *path = NULL;
        int i;
        size_t p, k, prefix_len, unit_len = strlen(unit);
        size_t path_len, len, escape;
 
        assert(unit);
 
+       memset(path, '\0', sizeof(char) * max_path_len);
        for (escape = 0, p = 0; p < unit_len; escape++) {
                k = strcspn(unit+p, SYSTEMD_UNIT_ESCAPE_CHAR);
                if (p+k >= unit_len)
@@ -179,11 +180,11 @@ static char *pass_systemd_get_unit_dbus_path(const char *unit)
        * char('-') is changed to three of char("_2d"). So the total
        * length will be: */
        /* (PREFIX) + (unit - escape + 3*escape) + NULL */
-       path_len = prefix_len + (unit_len - escape)
-               + (escape * 3 * sizeof(char)) + 1;
-       path = (char *)calloc(path_len, sizeof(char));
-       if (!path)
-               return NULL;
+       path_len = prefix_len + (unit_len - escape) + (escape * 3) + 1;
+       if (max_path_len < path_len) {
+               path[0] = '\0';
+               return;
+       }
 
        strncpy(path, SYSTEMD_DBUS_UNIT_PATH, prefix_len + 1);
        for (i = 0, p = 0; i <= escape; i++) {
@@ -197,8 +198,6 @@ static char *pass_systemd_get_unit_dbus_path(const char *unit)
                        p += k+1;
                }
        }
-       free(path);
-       return path;
 }
 
 static int pass_systemd_get_property(const char *name,
@@ -246,45 +245,48 @@ int pass_systemd_get_unit_property(const char *unit,
                                      const char *property,
                                      GVariant **variant)
 {
-       int r;
-       char *escaped;
+       char path[PATH_MAX];
+       int ret;
 
        assert(unit);
        assert(property);
 
-       escaped = pass_systemd_get_unit_dbus_path(unit);
+       pass_systemd_get_unit_dbus_path(unit, path, PATH_MAX);
+       if (!strlen(path))
+               return -1;
 
-       r = pass_systemd_get_property(SYSTEMD_DBUS_DEST,
-                                        escaped,
-                                        DBUS_IFACE_DBUS_PROPERTIES,
-                                        "Get",
-                                        SYSTEMD_DBUS_IFACE_UNIT,
-                                        property,
-                                        variant);
-       free(escaped);
-       return r;
+       ret = pass_systemd_get_property(SYSTEMD_DBUS_DEST,
+                                       path,
+                                       DBUS_IFACE_DBUS_PROPERTIES,
+                                       "Get",
+                                       SYSTEMD_DBUS_IFACE_UNIT,
+                                       property,
+                                       variant);
+
+       return ret;
 }
 
 int pass_systemd_get_service_property(const char *unit,
                                         const char *property,
                                         GVariant **variant)
 {
+       char path[PATH_MAX];
        int ret;
-       char *escaped;
 
        assert(unit);
        assert(property);
 
-       escaped = pass_systemd_get_unit_dbus_path(unit);
+       pass_systemd_get_unit_dbus_path(unit, path, PATH_MAX);
+       if (!strlen(path))
+               return -1;
 
        ret = pass_systemd_get_property(SYSTEMD_DBUS_DEST,
-                                          escaped,
-                                          DBUS_IFACE_DBUS_PROPERTIES,
-                                          "Get",
-                                          SYSTEMD_DBUS_IFACE_SERVICE,
-                                          property,
-                                          variant);
-       free(escaped);
+                                       path,
+                                       DBUS_IFACE_DBUS_PROPERTIES,
+                                       "Get",
+                                       SYSTEMD_DBUS_IFACE_SERVICE,
+                                       property,
+                                       variant);
        return ret;
 }