Fix memory leak due to not freeing each dirent pointer in the namelist array.
Signed-off-by: Tyler Hicks <[email protected]> --- libraries/libapparmor/src/private.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/libraries/libapparmor/src/private.c b/libraries/libapparmor/src/private.c index f164ccb..4769f34 100644 --- a/libraries/libapparmor/src/private.c +++ b/libraries/libapparmor/src/private.c @@ -207,7 +207,7 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data, { autofree struct dirent **namelist = NULL; autoclose int cb_dirfd = -1; - int i, ret; + int i, num_dirs, rc; if (!cb || !name) { errno = EINVAL; @@ -220,27 +220,34 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data, return -1; } - ret = scandirat(cb_dirfd, ".", &namelist, dot_or_dot_dot_filter, NULL); - if (ret == -1) { + num_dirs = scandirat(cb_dirfd, ".", &namelist, + dot_or_dot_dot_filter, NULL); + if (num_dirs == -1) { PDEBUG("scandirat of directory '%s' failed: %m\n", name); return -1; } - for (i = 0; i < ret; i++) { + for (rc = 0, i = 0; i < num_dirs; i++) { + /* Must cycle through all dirs so that each one is autofreed */ + autofree struct dirent *dir = namelist[i]; struct stat my_stat; - if (fstatat(cb_dirfd, namelist[i]->d_name, &my_stat, 0)) { - PDEBUG("stat failed for '%s': %m\n", - namelist[i]->d_name); - return -1; + if (rc) + continue; + + if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) { + PDEBUG("stat failed for '%s': %m\n", dir->d_name); + rc = -1; + continue; } - if (cb(cb_dirfd, namelist[i]->d_name, &my_stat, data)) { + if (cb(cb_dirfd, dir->d_name, &my_stat, data)) { PDEBUG("dir_for_each callback failed for '%s'\n", - namelist[i]->d_name); - return -1; + dir->d_name); + rc = -1; + continue; } } - return 0; + return rc; } -- 2.1.4 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
