Fix memory leak in idmapd.
authorKevin Coffman <kwc@citi.umich.edu>
Thu, 8 Feb 2007 22:27:14 +0000 (17:27 -0500)
committerNeil Brown <neilb@suse.de>
Fri, 9 Feb 2007 00:42:19 +0000 (11:42 +1100)
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
There is a pretty nasty memory leak in idmapd in dirscancb(). Some of
our customers have reported that idmapd can eat gigabytes of memory on
machines with a large number of mounts and unmounts and a long uptime.

That function uses scandir(), which malloc's an array of strings, but
dirscancb() never frees the strings or the array. The following patch
should correct this, but I've not yet tested it on 1.0.10 (only on the
RHEL4 1.0.6 version). Still, the code is very similar and I'm fairly
certain the problem exists in both versions.
Signed-off-by: Neil Brown <neilb@suse.de>
utils/idmapd/idmapd.c

index 19bf7a6..cbb0b6a 100644 (file)
@@ -464,7 +464,7 @@ dirscancb(int fd, short which, void *data)
                                goto next;
 
                        if ((ic = calloc(1, sizeof(*ic))) == NULL)
-                               return;
+                               goto out;
                        strlcpy(ic->ic_clid, ents[i]->d_name + 4,
                            sizeof(ic->ic_clid));
                        path[0] = '\0';
@@ -474,7 +474,7 @@ dirscancb(int fd, short which, void *data)
                        if ((ic->ic_dirfd = open(path, O_RDONLY, 0)) == -1) {
                                idmapd_warn("dirscancb: open(%s)", path);
                                free(ic);
-                               return;
+                               goto out;
                        }
 
                        strlcat(path, "/idmap", sizeof(path));
@@ -486,7 +486,7 @@ dirscancb(int fd, short which, void *data)
                        if (nfsopen(ic) == -1) {
                                close(ic->ic_dirfd);
                                free(ic);
-                               return;
+                               goto out;
                        }
 
                        ic->ic_id = "Client";
@@ -512,6 +512,11 @@ dirscancb(int fd, short which, void *data)
                } else
                        ic->ic_scanned = 0;
        }
+
+out:
+       for (i = 0;  i < nent; i++)
+               free(ents[i]);
+       free(ents);
        return;
 }