diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/handle.h | 4 | ||||
-rw-r--r-- | src/kernel/pipe.c | 18 | ||||
-rw-r--r-- | src/kernel/pipe.h | 3 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 19 |
4 files changed, 19 insertions, 25 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 3c16061..19d5953 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -19,12 +19,10 @@ struct handle { enum handle_type type; struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT void __user *file_id; // only applicable to HANDLE_FILE - // TODO readable/writeable could be reused for pipes - bool readable, writeable; /* currently only for HANDLE_FILE */ + bool readable, writeable; /* HANDLE_FILE | HANDLE_PIPE */ struct vfs_request *req; /* HANDLE_FS_REQ */ struct { struct process *queued; - bool write_end; struct handle *sister; // the other end, not included in refcount } pipe; diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c index bf775b8..d9dc8a7 100644 --- a/src/kernel/pipe.c +++ b/src/kernel/pipe.c @@ -5,14 +5,9 @@ static void pipe_trytransfer(struct handle *h); -void pipe_joinqueue(struct handle *h, bool wants_write, - struct process *proc, void __user *pbuf, size_t pbuflen) -{ +void pipe_joinqueue(struct handle *h, struct process *proc, void __user *pbuf, size_t pbuflen) { assert(h && h->type == HANDLE_PIPE); - if (wants_write == h->pipe.write_end) { - regs_savereturn(&proc->regs, -1); - return; - } + assert(h->readable ^ h->writeable); if (!h->pipe.sister) { regs_savereturn(&proc->regs, -1); return; @@ -37,21 +32,20 @@ static void pipe_trytransfer(struct handle *h) { struct process *rdr, *wtr; struct virt_cpy_error cpyerr; int len; - assert(h); + assert(h && h->type == HANDLE_PIPE); + assert(h->readable ^ h->writeable); if (!h->pipe.sister) { assert(!h->pipe.queued); return; } - rdr = h->pipe.write_end ? h->pipe.sister->pipe.queued : h->pipe.queued; - wtr = h->pipe.write_end ? h->pipe.queued : h->pipe.sister->pipe.queued; - + rdr = h->readable ? h->pipe.queued : h->pipe.sister->pipe.queued; + wtr = h->writeable ? h->pipe.queued : h->pipe.sister->pipe.queued; if (!(rdr && wtr)) return; assert(rdr->state == PS_WAITS4PIPE); assert(wtr->state == PS_WAITS4PIPE); len = min(rdr->waits4pipe.len, wtr->waits4pipe.len); - virt_cpy( rdr->pages, rdr->waits4pipe.buf, wtr->pages, wtr->waits4pipe.buf, diff --git a/src/kernel/pipe.h b/src/kernel/pipe.h index 2a90738..bcdfb86 100644 --- a/src/kernel/pipe.h +++ b/src/kernel/pipe.h @@ -3,7 +3,6 @@ #include <stdbool.h> /* eventually transitions to PS_RUNNING */ -void pipe_joinqueue(struct handle *h, bool wants_write, - struct process *proc, void __user *pbuf, size_t pbuflen); +void pipe_joinqueue(struct handle *h, struct process *proc, void __user *pbuf, size_t pbuflen); void pipe_invalidate_end(struct handle *h); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 6800138..88e98c6 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -187,13 +187,14 @@ static long simple_vfsop( || vfsop == VFSOP_WRITE || vfsop == VFSOP_GETSIZE); struct handle *h = process_handle_get(process_current, hid); - if (!h) SYSCALL_RETURN(-1); + if (!h) SYSCALL_RETURN(-EBADF); + // TODO those checks really need some comprehensive tests + if (vfsop == VFSOP_READ && !h->readable) + SYSCALL_RETURN(-EACCES); + if (vfsop == VFSOP_WRITE && !h->writeable) + SYSCALL_RETURN(-EACCES); + if (h->type == HANDLE_FILE) { - // TODO those checks really need some comprehensive tests - if (!h->readable && vfsop == VFSOP_READ) - SYSCALL_RETURN(-EACCES); - if (!h->writeable && vfsop == VFSOP_WRITE) - SYSCALL_RETURN(-EACCES); struct vfs_request req = (struct vfs_request){ .type = vfsop, .backend = h->backend, @@ -213,7 +214,8 @@ static long simple_vfsop( vfsreq_create(req); } else if (h->type == HANDLE_PIPE) { if (vfsop == VFSOP_READ || vfsop == VFSOP_WRITE) { - pipe_joinqueue(h, vfsop == VFSOP_READ, process_current, buf, len); + /* already checked if this is the correct pipe end */ + pipe_joinqueue(h, process_current, buf, len); } else SYSCALL_RETURN(-ENOSYS); } else SYSCALL_RETURN(-ENOSYS); return 0; @@ -353,9 +355,10 @@ long _syscall_pipe(handle_t __user user_ends[2], int flags) { process_handle_close(process_current, ends[1]); SYSCALL_RETURN(-EMFILE); } - wend->pipe.write_end = true; wend->pipe.sister = rend; rend->pipe.sister = wend; + wend->writeable = true; + rend->readable = true; virt_cpy_to(process_current->pages, user_ends, ends, sizeof ends); SYSCALL_RETURN(0); |