Kernel: Don't leak file descriptors in sys$pipe()

If the final copy_to_user() call fails when writing the file descriptors
to the output array, we have to make sure the file descriptors don't
remain in the process file descriptor table. Otherwise they are
basically leaked, as userspace is not aware of them.

This matches the behavior of our sys$socketpair() implementation.
This commit is contained in:
Andreas Kling 2022-08-16 20:35:32 +02:00
parent 307932857e
commit b6d0636656
Notes: sideshowbarker 2024-07-17 08:11:29 +09:00
2 changed files with 12 additions and 5 deletions

View file

@ -355,7 +355,7 @@ public:
ErrorOr<FlatPtr> sys$sigtimedwait(Userspace<sigset_t const*>, Userspace<siginfo_t*>, Userspace<timespec const*>);
ErrorOr<FlatPtr> sys$getgroups(size_t, Userspace<gid_t*>);
ErrorOr<FlatPtr> sys$setgroups(size_t, Userspace<gid_t const*>);
ErrorOr<FlatPtr> sys$pipe(int pipefd[2], int flags);
ErrorOr<FlatPtr> sys$pipe(Userspace<int*>, int flags);
ErrorOr<FlatPtr> sys$killpg(pid_t pgrp, int sig);
ErrorOr<FlatPtr> sys$seteuid(UserID);
ErrorOr<FlatPtr> sys$setegid(GroupID);

View file

@ -9,7 +9,7 @@
namespace Kernel {
ErrorOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
ErrorOr<FlatPtr> Process::sys$pipe(Userspace<int*> pipefd, int flags)
{
VERIFY_NO_PROCESS_BIG_LOCK(this)
TRY(require_promise(Pledge::stdio));
@ -43,11 +43,18 @@ ErrorOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags);
fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags);
int fds_for_userspace[2] = {
reader_fd_allocation.fd,
writer_fd_allocation.fd,
};
if (copy_to_user(pipefd, fds_for_userspace, sizeof(fds_for_userspace)).is_error()) {
fds[reader_fd_allocation.fd] = {};
fds[writer_fd_allocation.fd] = {};
return EFAULT;
}
return {};
}));
TRY(copy_to_user(&pipefd[0], &reader_fd_allocation.fd));
TRY(copy_to_user(&pipefd[1], &writer_fd_allocation.fd));
return 0;
}