Fix double free and out of order delete session
authorDavid Goulet <dgoulet@efficios.com>
Tue, 17 Jan 2012 22:05:10 +0000 (17:05 -0500)
committerDavid Goulet <dgoulet@efficios.com>
Tue, 17 Jan 2012 22:05:10 +0000 (17:05 -0500)
Failing to create metadata, the data structure was freed but the pointer
was not set to NULL. When deleting the metadata of that session (that
has failed), the pointer was not NULL creating a "valid" pointer for the
check and creating a double free error. This failure happens when the
session daemon reached the maximum number of open files.

Also, on destroy trace, the ust app session was freed and deref. just
after creating an invalid pointer access.

Finally, set the started flag of a ust app session to 0 when stopping
the session.

Signed-off-by: David Goulet <dgoulet@efficios.com>
lttng-sessiond/ust-app.c

index a9c1c764c0359ca3a81dbb22aa088c093e456eda..5976270604cd0ffd9e271a38c669bbbe8f956c6f 100644 (file)
@@ -1177,8 +1177,15 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
 
                ret = open_ust_metadata(app, ua_sess);
                if (ret < 0) {
+                       DBG3("Opening metadata failed. Cleaning up memory");
+
                        /* Cleanup failed metadata struct */
                        free(ua_sess->metadata);
+                       /*
+                        * This is very important because delete_ust_app_session check if
+                        * the pointer is null or not in order to delete the metadata.
+                        */
+                       ua_sess->metadata = NULL;
                        goto error;
                }
 
@@ -1958,6 +1965,11 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
                goto error_rcu_unlock;
        }
 
+       /* Not started, continuing. */
+       if (ua_sess->started == 0) {
+               goto end;
+       }
+
        /* This inhibits UST tracing */
        ret = ustctl_stop_session(app->key.sock, ua_sess->handle);
        if (ret < 0) {
@@ -1973,9 +1985,8 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
                        node.node) {
                ret = ustctl_sock_flush_buffer(app->key.sock, ua_chan->obj);
                if (ret < 0) {
-                       ERR("UST app PID %d channel %s flush failed",
-                                       app->key.pid, ua_chan->name);
-                       ERR("Ended with ret %d", ret);
+                       ERR("UST app PID %d channel %s flush failed with ret %d",
+                                       app->key.pid, ua_chan->name, ret);
                        /* Continuing flushing all buffers */
                        continue;
                }
@@ -1984,12 +1995,14 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
        /* Flush all buffers before stopping */
        ret = ustctl_sock_flush_buffer(app->key.sock, ua_sess->metadata->obj);
        if (ret < 0) {
-               ERR("UST app PID %d metadata flush failed", app->key.pid);
-               ERR("Ended with ret %d", ret);
+               ERR("UST app PID %d metadata flush failed with ret %d", app->key.pid,
+                               ret);
        }
 
-       rcu_read_unlock();
+       ua_sess->started = 0;
 
+end:
+       rcu_read_unlock();
        return 0;
 
 error_rcu_unlock:
@@ -2021,13 +2034,14 @@ int ust_app_destroy_trace(struct ltt_ust_session *usess, struct ust_app *app)
        ua_sess = caa_container_of(node, struct ust_app_session, node);
        ret = lttng_ht_del(app->sessions, &iter);
        assert(!ret);
-       delete_ust_app_session(app->key.sock, ua_sess);
        obj.handle = ua_sess->handle;
        obj.shm_fd = -1;
        obj.wait_fd = -1;
        obj.memory_map_size = 0;
        ustctl_release_object(app->key.sock, &obj);
 
+       delete_ust_app_session(app->key.sock, ua_sess);
+
        rcu_read_unlock();
 
        /* Quiescent wait after stopping trace */
This page took 0.035986 seconds and 4 git commands to generate.