From ad81d625737e1c096c154aedd8a1d161d3ee592e Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 26 Apr 2009 18:08:13 +0200 Subject: [PATCH 1/1] Fix an invalid free() in command handlers. 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 | 2 -- server.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/command.c b/command.c index d08a7181..698e2755 100644 --- 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; diff --git a/server.c b/server.c index 1e4caf08..a4115eb6 100644 --- 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(); -- 2.39.2