Skip to content

Commit 25827cc

Browse files
authored
Fix two resource leak bugs (wasip2) (#635)
* scandir() wasn't closing its file descriptors * The remove_and_drop_directory_stream() function that's used in a few places was deleting the file descriptor from the table so that the underlying file handle wouldn't be closed
1 parent abb494e commit 25827cc

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

libc-bottom-half/cloudlibc/src/libc/dirent/scandirat.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
4040
if (fd == -1)
4141
return -1;
4242
DIR *dirp = fdopendir(fd);
43-
if (!dirp)
43+
if (!dirp) {
44+
close(fd);
4445
return -1;
46+
}
4547
fd = dirp->fd;
4648

4749
// Translate the file descriptor to an internal handle
@@ -50,6 +52,7 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
5052
read_directory_state_t state;
5153
if (!fd_to_directory_stream(fd, &stream, &parent_file_handle, &state)) {
5254
errno = EBADF;
55+
close(fd);
5356
return -1;
5457
}
5558

@@ -88,6 +91,8 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
8891
malloc(offsetof(struct dirent, d_name) + name_len + 1);
8992
if (dirent == NULL) {
9093
errno = EINVAL;
94+
remove_and_drop_directory_stream(fd);
95+
close(fd);
9196
return -1;
9297
}
9398
dirent->d_type = (handle_dot || handle_dot_dot) ? DT_DIR : dir_entry_type_to_d_type(dir_entry_optional.val.type);
@@ -103,6 +108,8 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
103108
// Do an `fstatat` to get the inode number.
104109
if (fstatat(fd, dirent->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) != 0) {
105110
errno = EBADF;
111+
remove_and_drop_directory_stream(fd);
112+
close(fd);
106113
return -1;
107114
}
108115
// Fill in the inode.
@@ -124,6 +131,8 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
124131
if (new_dirents == NULL) {
125132
free(dirent);
126133
free(dirents);
134+
remove_and_drop_directory_stream(fd);
135+
close(fd);
127136
errno = EBADF;
128137
return -1;
129138
}
@@ -137,10 +146,11 @@ int __wasilibc_nocwd_scandirat(int dirfd, const char *dir, struct dirent ***name
137146
}
138147

139148
// Sort results and return them
140-
filesystem_directory_entry_stream_drop_borrow(stream);
149+
remove_and_drop_directory_stream(fd);
141150
(qsort)(dirents, dirents_used, sizeof(*dirents),
142151
(int (*)(const void *, const void *))compar);
143152
*namelist = dirents;
153+
close(fd);
144154
return dirents_used;
145155
#else
146156
// Open the directory.

libc-bottom-half/headers/private/wasi/file_utils.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ static void remove_and_drop_directory_stream(int fd) {
6868

6969
if (entry->tag == DESCRIPTOR_TABLE_ENTRY_DIRECTORY_STREAM) {
7070
filesystem_directory_entry_stream_drop_own(entry->directory_stream_info.directory_stream);
71-
if (!descriptor_table_remove(fd, entry))
72-
return;
71+
filesystem_borrow_descriptor_t file_handle = entry->directory_stream_info.directory_file_handle;
72+
entry->tag = DESCRIPTOR_TABLE_ENTRY_FILE_HANDLE;
73+
entry->file.file_handle = file_handle;
74+
entry->file.readable = true;
75+
entry->file.writable = false;
7376
}
7477
}
7578

0 commit comments

Comments
 (0)