1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-19 20:25:07 +00:00

Kernel+LibC+UserspaceEmulator: Bring back sys$dup2()

This is racy in userspace and non-racy in kernelspace so let's keep
it in kernelspace.

The behavior change where CLOEXEC is preserved when dup2() is called
with (old_fd == new_fd) was good though, let's keep that.
This commit is contained in:
Andreas Kling 2020-08-15 10:54:00 +02:00
parent bf247fb45f
commit 65f2270232
7 changed files with 59 additions and 14 deletions

View file

@ -253,6 +253,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
switch (function) {
case SC_chdir:
return virt$chdir(arg1, arg2);
case SC_dup2:
return virt$dup2(arg1, arg2);
case SC_access:
return virt$access(arg1, arg2, arg3);
case SC_waitid:
@ -1348,4 +1350,9 @@ int Emulator::virt$chdir(FlatPtr path, size_t path_length)
return syscall(SC_chdir, host_path.data(), host_path.size());
}
int Emulator::virt$dup2(int old_fd, int new_fd)
{
return syscall(SC_dup2, old_fd, new_fd);
}
}

View file

@ -138,6 +138,7 @@ private:
ssize_t virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned int flags);
int virt$sleep(unsigned);
int virt$chdir(FlatPtr, size_t);
int virt$dup2(int, int);
int virt$getpgrp();
int virt$getpgid(pid_t);
int virt$setpgid(pid_t pid, pid_t pgid);

View file

@ -86,6 +86,7 @@ namespace Kernel {
S(getpgrp) \
S(fork) \
S(execve) \
S(dup2) \
S(sigaction) \
S(umask) \
S(getgroups) \

View file

@ -100,6 +100,7 @@ set(KERNEL_SOURCES
Syscalls/clock.cpp
Syscalls/debug.cpp
Syscalls/disown.cpp
Syscalls/dup2.cpp
Syscalls/execve.cpp
Syscalls/exit.cpp
Syscalls/fcntl.cpp

View file

@ -258,6 +258,7 @@ public:
int sys$ptsname(int fd, Userspace<char*>, size_t);
pid_t sys$fork(RegisterState&);
int sys$execve(Userspace<const Syscall::SC_execve_params*>);
int sys$dup2(int old_fd, int new_fd);
int sys$sigaction(int signum, const sigaction* act, sigaction* old_act);
int sys$sigprocmask(int how, Userspace<const sigset_t*> set, Userspace<sigset_t*> old_set);
int sys$sigpending(Userspace<sigset_t*>);

46
Kernel/Syscalls/dup2.cpp Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Kernel/FileSystem/FileDescription.h>
#include <Kernel/Process.h>
namespace Kernel {
int Process::sys$dup2(int old_fd, int new_fd)
{
REQUIRE_PROMISE(stdio);
auto description = file_description(old_fd);
if (!description)
return -EBADF;
if (old_fd == new_fd)
return 0;
if (new_fd < 0 || new_fd >= m_max_open_file_descriptors)
return -EINVAL;
m_fds[new_fd].set(*description);
return new_fd;
}
}

View file

@ -415,20 +415,8 @@ int dup(int old_fd)
int dup2(int old_fd, int new_fd)
{
if (new_fd < 0) {
errno = EBADF;
return -1;
}
if (old_fd == new_fd)
return old_fd;
// Validate `old_fd` so we don't close `new_fd` and then fail the `F_DUPFD`.
if (fcntl(old_fd, F_GETFL) < 0)
return -1;
close(new_fd);
return fcntl(old_fd, F_DUPFD, new_fd);
int rc = syscall(SC_dup2, old_fd, new_fd);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int setgroups(size_t size, const gid_t* list)