]> git.tue.mpg.de Git - paraslash.git/commitdiff
Fix an invalid free() in command handlers.
authorAndre Noll <maan@systemlinux.org>
Sun, 26 Apr 2009 16:08:13 +0000 (18:08 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 26 Apr 2009 16:08:13 +0000 (18:08 +0200)
The chunk table and the info_string are pointers located in the mmd
struct that point to dynamically allocated memory that must be freed
by the parent and the child. However, as the mmd struct is in a shared
memory area, there's no guarantee that after the fork these pointers
are still valid in child context. As these two pointers are not used
in the child anyway, we save them to local variables and free the
memory via that copy in the child.

This gets rid of

*** glibc detected *** para_server (serving 127.0.0.1#53650): double free or corruption (!prev): 0x08086fe0 ***

command.c
server.c

index d08a71818cfb437c5cd6c02a13d6a7c2f3e56893..698e2755f6cf2dbc1835fe60d56129d50d1d8985 100644 (file)
--- a/command.c
+++ b/command.c
@@ -792,8 +792,6 @@ __noreturn void handle_connect(int fd, const char *peername)
        ret = cmd->handler(fd, argc, argv);
        mutex_lock(mmd_mutex);
        mmd->num_commands++;
-       free(mmd->afd.afhi.info_string);
-       free(mmd->afd.afhi.chunk_table);
        mutex_unlock(mmd_mutex);
        if (ret >= 0)
                goto out;
index 1e4caf08c90d0e04233a987f6e520e19850c20c5..a4115eb65734391128481f6fa421d548aba78e20 100644 (file)
--- a/server.c
+++ b/server.c
@@ -352,6 +352,8 @@ static void command_post_select(struct sched *s, struct task *t)
        int new_fd, ret, i;
        char *peer_name;
        pid_t child_pid;
+       uint32_t *chunk_table;
+       char *info_string;
 
        if (!FD_ISSET(sct->listen_fd, &s->rfds))
                return;
@@ -364,6 +366,16 @@ static void command_post_select(struct sched *s, struct task *t)
        mmd->num_connects++;
        mmd->active_connections++;
        random();
+       /* The chunk table and the info_string are pointers located in the
+        * mmd struct that point to dynamically allocated memory that must be
+        * freed by the parent and the child. However, as the mmd struct is in
+        * a shared memory area, there's no guarantee that after the fork these
+        * pointers are still valid in child context. As these two pointers are
+        * not used in the child anyway, we save them to local variables and
+        * free the memory via that copy in the child.
+        */
+       info_string = mmd->afd.afhi.info_string;
+       chunk_table = mmd->afd.afhi.chunk_table;
        child_pid = fork();
        if (child_pid < 0) {
                ret = -ERRNO_TO_PARA_ERROR(errno);
@@ -374,6 +386,9 @@ static void command_post_select(struct sched *s, struct task *t)
                /* parent keeps accepting connections */
                return;
        }
+       /* mmd might already have changed at this point */
+       free(info_string);
+       free(chunk_table);
        alarm(ALARM_TIMEOUT);
        close_listed_fds();
        para_signal_shutdown();