kernel/fs: Consumers of context->fds[] must check O_DISCONNECTED.
Since these do not go through get_fd, which would check for them, we need to do these checks manually in the relevant locations. Some of these changes were broken out from axeld's original commit, and some were found by my own auditing.
This commit is contained in:
@@ -428,7 +428,8 @@ dup2_fd(int oldfd, int newfd, bool kernel)
|
||||
// the table size could be changed)
|
||||
if ((uint32)oldfd >= context->table_size
|
||||
|| (uint32)newfd >= context->table_size
|
||||
|| context->fds[oldfd] == NULL) {
|
||||
|| context->fds[oldfd] == NULL
|
||||
|| (context->fds[oldfd]->open_mode & O_DISCONNECTED) != 0) {
|
||||
mutex_unlock(&context->io_mutex);
|
||||
return B_FILE_ERROR;
|
||||
}
|
||||
|
||||
@@ -1955,21 +1955,23 @@ disconnect_mount_or_vnode_fds(struct fs_mount* mount,
|
||||
sRoot, false);
|
||||
|
||||
for (uint32 i = 0; i < context->table_size; i++) {
|
||||
if (struct file_descriptor* descriptor = context->fds[i]) {
|
||||
inc_fd_ref_count(descriptor);
|
||||
struct file_descriptor* descriptor = context->fds[i];
|
||||
if (descriptor == NULL || (descriptor->open_mode & O_DISCONNECTED) != 0)
|
||||
continue;
|
||||
|
||||
// if this descriptor points at this mount, we
|
||||
// need to disconnect it to be able to unmount
|
||||
struct vnode* vnode = fd_vnode(descriptor);
|
||||
if (vnodeToDisconnect != NULL) {
|
||||
if (vnode == vnodeToDisconnect)
|
||||
disconnect_fd(descriptor);
|
||||
} else if ((vnode != NULL && vnode->mount == mount)
|
||||
|| (vnode == NULL && descriptor->u.mount == mount))
|
||||
inc_fd_ref_count(descriptor);
|
||||
|
||||
// if this descriptor points at this mount, we
|
||||
// need to disconnect it to be able to unmount
|
||||
struct vnode* vnode = fd_vnode(descriptor);
|
||||
if (vnodeToDisconnect != NULL) {
|
||||
if (vnode == vnodeToDisconnect)
|
||||
disconnect_fd(descriptor);
|
||||
} else if ((vnode != NULL && vnode->mount == mount)
|
||||
|| (vnode == NULL && descriptor->u.mount == mount))
|
||||
disconnect_fd(descriptor);
|
||||
|
||||
put_fd(descriptor);
|
||||
}
|
||||
put_fd(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4990,7 +4992,8 @@ vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec)
|
||||
for (i = 0; i < tableSize; i++) {
|
||||
struct file_descriptor* descriptor = parentContext->fds[i];
|
||||
|
||||
if (descriptor != NULL) {
|
||||
if (descriptor != NULL
|
||||
&& (descriptor->open_mode & O_DISCONNECTED) == 0) {
|
||||
bool closeOnExec = fd_close_on_exec(parentContext, i);
|
||||
if (closeOnExec && purgeCloseOnExec)
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user