summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Process.cpp11
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Libraries/LibC/unistd.cpp7
-rw-r--r--Libraries/LibC/unistd.h1
5 files changed, 17 insertions, 6 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index a428b026ff..6e7f0f73ba 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -1194,20 +1194,25 @@ int Process::alloc_fd(int first_candidate_fd)
return fd;
}
-int Process::sys$pipe(int pipefd[2])
+int Process::sys$pipe(int pipefd[2], int flags)
{
if (!validate_write_typed(pipefd))
return -EFAULT;
if (number_of_open_file_descriptors() + 2 > max_open_file_descriptors())
return -EMFILE;
+ // Reject flags other than O_CLOEXEC.
+ if ((flags & O_CLOEXEC) != flags)
+ return -EINVAL;
+
+ u32 fd_flags = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
auto fifo = FIFO::create(m_uid);
int reader_fd = alloc_fd();
- m_fds[reader_fd].set(fifo->open_direction(FIFO::Direction::Reader));
+ m_fds[reader_fd].set(fifo->open_direction(FIFO::Direction::Reader), fd_flags);
pipefd[0] = reader_fd;
int writer_fd = alloc_fd();
- m_fds[writer_fd].set(fifo->open_direction(FIFO::Direction::Writer));
+ m_fds[writer_fd].set(fifo->open_direction(FIFO::Direction::Writer), fd_flags);
pipefd[1] = writer_fd;
return 0;
diff --git a/Kernel/Process.h b/Kernel/Process.h
index dfbbfc4771..6c94322a7f 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -168,7 +168,7 @@ public:
int sys$sigpending(sigset_t*);
int sys$getgroups(ssize_t, gid_t*);
int sys$setgroups(ssize_t, const gid_t*);
- int sys$pipe(int* pipefd);
+ int sys$pipe(int pipefd[2], int flags);
int sys$killpg(int pgrp, int sig);
int sys$setgid(gid_t);
int sys$setuid(uid_t);
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index b378367ea2..48b9313a92 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -189,7 +189,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
case Syscall::SC_sigprocmask:
return current->process().sys$sigprocmask((int)arg1, (const sigset_t*)arg2, (sigset_t*)arg3);
case Syscall::SC_pipe:
- return current->process().sys$pipe((int*)arg1);
+ return current->process().sys$pipe((int*)arg1, (int) arg2);
case Syscall::SC_killpg:
return current->process().sys$killpg((int)arg1, (int)arg2);
case Syscall::SC_setuid:
diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp
index 5d9e9bb97d..59207b097d 100644
--- a/Libraries/LibC/unistd.cpp
+++ b/Libraries/LibC/unistd.cpp
@@ -366,7 +366,12 @@ int getgroups(int size, gid_t list[])
int pipe(int pipefd[2])
{
- int rc = syscall(SC_pipe, pipefd);
+ return pipe2(pipefd, 0);
+}
+
+int pipe2(int pipefd[2], int flags)
+{
+ int rc = syscall(SC_pipe, pipefd, flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h
index 567f098c82..00cedd489e 100644
--- a/Libraries/LibC/unistd.h
+++ b/Libraries/LibC/unistd.h
@@ -86,6 +86,7 @@ int getdtablesize();
int dup(int old_fd);
int dup2(int old_fd, int new_fd);
int pipe(int pipefd[2]);
+int pipe2(int pipefd[2], int flags);
unsigned int alarm(unsigned int seconds);
int access(const char* pathname, int mode);
int isatty(int fd);