mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
libc: improve dup/dup2 in vfs_plugin
This patch replaces the naive dup2 implementation (that merely duplicated the context pointer) by the replication of the original FD state by re-opening the same file with the same flags and seek position. This prevents a potential double release of the VFS handle (the FD context). It also implements 'dup'. Fixes #3505 Fixes #3477
This commit is contained in:
parent
59c60b8031
commit
c8b7710e5d
@ -268,7 +268,7 @@ extern "C" int dup2(int libc_fd, int new_libc_fd)
|
||||
close(new_libc_fd);
|
||||
|
||||
new_fd = file_descriptor_allocator()->alloc(fd->plugin, 0, new_libc_fd);
|
||||
new_fd->path(fd->fd_path);
|
||||
|
||||
/* new_fd->context must be assigned by the plugin implementing 'dup2' */
|
||||
return fd->plugin->dup2(fd, new_fd);
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ class Libc::Vfs_plugin : public Plugin
|
||||
|
||||
int access(char const *, int) override;
|
||||
int close(File_descriptor *) override;
|
||||
File_descriptor *dup(File_descriptor *) override;
|
||||
int dup2(File_descriptor *, File_descriptor *) override;
|
||||
int fcntl(File_descriptor *, int, long) override;
|
||||
int fstat(File_descriptor *, struct stat *) override;
|
||||
|
@ -425,11 +425,55 @@ int Libc::Vfs_plugin::close(File_descriptor *fd)
|
||||
int Libc::Vfs_plugin::dup2(File_descriptor *fd,
|
||||
File_descriptor *new_fd)
|
||||
{
|
||||
new_fd->context = fd->context;
|
||||
Vfs::Vfs_handle *handle = nullptr;
|
||||
|
||||
typedef Vfs::Directory_service::Open_result Result;
|
||||
|
||||
if (VFS_THREAD_SAFE(_root_dir.open(fd->fd_path, fd->flags, &handle, _alloc))
|
||||
!= Result::OPEN_OK) {
|
||||
|
||||
warning("dup2 failed for path ", fd->fd_path);
|
||||
return Errno(EBADF);
|
||||
}
|
||||
|
||||
handle->seek(vfs_handle(fd)->seek());
|
||||
handle->handler(&_response_handler);
|
||||
|
||||
new_fd->context = vfs_context(handle);
|
||||
new_fd->flags = fd->flags;
|
||||
new_fd->path(fd->fd_path);
|
||||
|
||||
return new_fd->libc_fd;
|
||||
}
|
||||
|
||||
|
||||
Libc::File_descriptor *Libc::Vfs_plugin::dup(File_descriptor *fd)
|
||||
{
|
||||
Vfs::Vfs_handle *handle = nullptr;
|
||||
|
||||
typedef Vfs::Directory_service::Open_result Result;
|
||||
|
||||
if (VFS_THREAD_SAFE(_root_dir.open(fd->fd_path, fd->flags, &handle, _alloc))
|
||||
!= Result::OPEN_OK) {
|
||||
|
||||
warning("dup failed for path ", fd->fd_path);
|
||||
errno = EBADF;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
handle->seek(vfs_handle(fd)->seek());
|
||||
handle->handler(&_response_handler);
|
||||
|
||||
File_descriptor * const new_fd =
|
||||
file_descriptor_allocator()->alloc(this, vfs_context(handle));
|
||||
|
||||
new_fd->flags = fd->flags;
|
||||
new_fd->path(fd->fd_path);
|
||||
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
|
||||
int Libc::Vfs_plugin::fstat(File_descriptor *fd, struct stat *buf)
|
||||
{
|
||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||
@ -990,13 +1034,11 @@ int Libc::Vfs_plugin::fcntl(File_descriptor *fd, int cmd, long arg)
|
||||
file_descriptor_allocator()->alloc(this, 0);
|
||||
if (!new_fd) return Errno(EMFILE);
|
||||
|
||||
new_fd->path(fd->fd_path);
|
||||
|
||||
/*
|
||||
* Use new allocated number as name of file descriptor
|
||||
* duplicate.
|
||||
*/
|
||||
if (dup2(fd, new_fd) == -1) {
|
||||
if (Vfs_plugin::dup2(fd, new_fd) == -1) {
|
||||
error("Plugin::fcntl: dup2 unexpectedly failed");
|
||||
return Errno(EINVAL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user