kernel: Fix unbalanced release of sync object in FD select race.
When a file descriptor is closed between being selected and adding the select info to its IO context, the select info needs to be cleaned up. This is done by deselect_select_infos() which unconditionally also put the select_sync associated with the infos. In this special case we do not yet hold a reference to the select_sync however, so avoid putting the corresponding sync object. Fixes #11098, #10763 and #10230.
This commit is contained in:
parent
a88f2beb0f
commit
831abecd6a
@ -41,7 +41,7 @@ static struct file_descriptor* get_fd_locked(struct io_context* context,
|
||||
int fd);
|
||||
static struct file_descriptor* remove_fd(struct io_context* context, int fd);
|
||||
static void deselect_select_infos(file_descriptor* descriptor,
|
||||
select_info* infos);
|
||||
select_info* infos, bool putSyncObjects);
|
||||
|
||||
|
||||
struct FDGetterLocking {
|
||||
@ -367,7 +367,7 @@ remove_fd(struct io_context* context, int fd)
|
||||
mutex_unlock(&context->io_mutex);
|
||||
|
||||
if (selectInfos != NULL)
|
||||
deselect_select_infos(descriptor, selectInfos);
|
||||
deselect_select_infos(descriptor, selectInfos, true);
|
||||
|
||||
return disconnected ? NULL : descriptor;
|
||||
}
|
||||
@ -457,7 +457,7 @@ dup2_fd(int oldfd, int newfd, bool kernel)
|
||||
|
||||
// Say bye bye to the evicted fd
|
||||
if (evicted) {
|
||||
deselect_select_infos(evicted, selectInfos);
|
||||
deselect_select_infos(evicted, selectInfos, true);
|
||||
close_fd(evicted);
|
||||
put_fd(evicted);
|
||||
}
|
||||
@ -525,7 +525,8 @@ fd_ioctl(bool kernelFD, int fd, uint32 op, void* buffer, size_t length)
|
||||
|
||||
|
||||
static void
|
||||
deselect_select_infos(file_descriptor* descriptor, select_info* infos)
|
||||
deselect_select_infos(file_descriptor* descriptor, select_info* infos,
|
||||
bool putSyncObjects)
|
||||
{
|
||||
TRACE(("deselect_select_infos(%p, %p)\n", descriptor, infos));
|
||||
|
||||
@ -546,6 +547,8 @@ deselect_select_infos(file_descriptor* descriptor, select_info* infos)
|
||||
|
||||
notify_select_events(info, B_EVENT_INVALID);
|
||||
info = info->next;
|
||||
|
||||
if (putSyncObjects)
|
||||
put_select_sync(sync);
|
||||
}
|
||||
}
|
||||
@ -601,7 +604,7 @@ select_fd(int32 fd, struct select_info* info, bool kernel)
|
||||
// Someone close()d the index in the meantime. deselect() all
|
||||
// events.
|
||||
info->next = NULL;
|
||||
deselect_select_infos(descriptor, info);
|
||||
deselect_select_infos(descriptor, info, false);
|
||||
|
||||
// Release our open reference of the descriptor.
|
||||
close_fd(descriptor);
|
||||
|
Loading…
Reference in New Issue
Block a user