]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Make pipes in CloudABI work.
authored <ed@FreeBSD.org>
Wed, 29 Jul 2015 17:18:27 +0000 (17:18 +0000)
committered <ed@FreeBSD.org>
Wed, 29 Jul 2015 17:18:27 +0000 (17:18 +0000)
Summary:
Pipes in CloudABI are unidirectional. The reason for this is that
CloudABI attempts to provide a uniform runtime environment across
different flavours of UNIX.

Instead of implementing a custom pipe that is unidirectional, we can
simply reuse Capsicum permission bits to support this. This is nice,
because CloudABI already attempts to restrict permission bits to
correspond with the operations that apply to a certain file descriptor.

Replace kern_pipe() and kern_pipe2() by a single kern_pipe() that takes
a pair of filecaps. These filecaps are passed to the newly introduced
falloc_caps() function that creates the descriptors with rights in
place.

Test Plan:
CloudABI pipes seem to be created with proper rights in place:

https://github.com/NuxiNL/cloudlibc/blob/master/src/libc/unistd/pipe_test.c#L44

Reviewers: jilles, mjg

Reviewed By: mjg

Subscribers: imp

Differential Revision: https://reviews.freebsd.org/D3236

sys/compat/cloudabi/cloudabi_fd.c
sys/compat/linux/linux_file.c
sys/kern/sys_pipe.c
sys/sys/syscallsubr.h

index 1b3aa0f0ce09c78740b09817d9d90f0a060a7c5d..5a58cb312d981e70099b1e3df782b63dfa499a53 100644 (file)
@@ -120,10 +120,24 @@ int
 cloudabi_sys_fd_create2(struct thread *td,
     struct cloudabi_sys_fd_create2_args *uap)
 {
+       struct filecaps fcaps1 = {}, fcaps2 = {};
        int fds[2];
        int error;
 
        switch (uap->type) {
+       case CLOUDABI_FILETYPE_FIFO:
+               /*
+                * CloudABI pipes are unidirectional. Restrict rights on
+                * the pipe to simulate this.
+                */
+               cap_rights_init(&fcaps1.fc_rights, CAP_EVENT, CAP_FCNTL,
+                   CAP_FSTAT, CAP_READ);
+               fcaps1.fc_fcntls = CAP_FCNTL_SETFL;
+               cap_rights_init(&fcaps2.fc_rights, CAP_EVENT, CAP_FCNTL,
+                   CAP_FSTAT, CAP_WRITE);
+               fcaps2.fc_fcntls = CAP_FCNTL_SETFL;
+               error = kern_pipe(td, fds, 0, &fcaps1, &fcaps2);
+               break;
        case CLOUDABI_FILETYPE_SOCKET_DGRAM:
                error = kern_socketpair(td, AF_UNIX, SOCK_DGRAM, 0, fds);
                break;
index 1e5e37a2db76a2ade936a0934e3c638026e71eee..489dc1e458dce8a25e9e5046f06927c231067766 100644 (file)
@@ -1582,7 +1582,7 @@ linux_pipe(struct thread *td, struct linux_pipe_args *args)
                printf(ARGS(pipe, "*"));
 #endif
 
-       error = kern_pipe2(td, fildes, 0);
+       error = kern_pipe(td, fildes, 0, NULL, NULL);
        if (error)
                return (error);
 
@@ -1609,7 +1609,7 @@ linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
                flags |= O_NONBLOCK;
        if ((args->flags & LINUX_O_CLOEXEC) != 0)
                flags |= O_CLOEXEC;
-       error = kern_pipe2(td, fildes, flags);
+       error = kern_pipe(td, fildes, flags, NULL, NULL);
        if (error)
                return (error);
 
index 70e76ad39952eab2bc9b60461237873abadbcf85..a81c9dee055fbbdb85c0d39dcaf04e081d40999a 100644 (file)
@@ -397,14 +397,8 @@ pipe_dtor(struct pipe *dpipe)
  * the zone pick up the pieces via pipeclose().
  */
 int
-kern_pipe(struct thread *td, int fildes[2])
-{
-
-       return (kern_pipe2(td, fildes, 0));
-}
-
-int
-kern_pipe2(struct thread *td, int fildes[2], int flags)
+kern_pipe(struct thread *td, int fildes[2], int flags, struct filecaps *fcaps1,
+    struct filecaps *fcaps2)
 {
        struct file *rf, *wf;
        struct pipe *rpipe, *wpipe;
@@ -414,13 +408,13 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
        pipe_paircreate(td, &pp);
        rpipe = &pp->pp_rpipe;
        wpipe = &pp->pp_wpipe;
-       error = falloc(td, &rf, &fd, flags);
+       error = falloc_caps(td, &rf, &fd, flags, fcaps1);
        if (error) {
                pipeclose(rpipe);
                pipeclose(wpipe);
                return (error);
        }
-       /* An extra reference on `rf' has been held for us by falloc(). */
+       /* An extra reference on `rf' has been held for us by falloc_caps(). */
        fildes[0] = fd;
 
        fflags = FREAD | FWRITE;
@@ -434,7 +428,7 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
         * side while we are blocked trying to allocate the write side.
         */
        finit(rf, fflags, DTYPE_PIPE, rpipe, &pipeops);
-       error = falloc(td, &wf, &fd, flags);
+       error = falloc_caps(td, &wf, &fd, flags, fcaps2);
        if (error) {
                fdclose(td, rf, fildes[0]);
                fdrop(rf, td);
@@ -442,7 +436,7 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
                pipeclose(wpipe);
                return (error);
        }
-       /* An extra reference on `wf' has been held for us by falloc(). */
+       /* An extra reference on `wf' has been held for us by falloc_caps(). */
        finit(wf, fflags, DTYPE_PIPE, wpipe, &pipeops);
        fdrop(wf, td);
        fildes[1] = fd;
@@ -458,7 +452,7 @@ sys_pipe(struct thread *td, struct pipe_args *uap)
        int error;
        int fildes[2];
 
-       error = kern_pipe(td, fildes);
+       error = kern_pipe(td, fildes, 0, NULL, NULL);
        if (error)
                return (error);
 
@@ -475,7 +469,7 @@ sys_pipe2(struct thread *td, struct pipe2_args *uap)
 
        if (uap->flags & ~(O_CLOEXEC | O_NONBLOCK))
                return (EINVAL);
-       error = kern_pipe2(td, fildes, uap->flags);
+       error = kern_pipe(td, fildes, uap->flags, NULL, NULL);
        if (error)
                return (error);
        error = copyout(fildes, uap->fildes, 2 * sizeof(int));
index d22c349bb67841023e8493b8833331dfbcaa60b7..f6f851b60a526553cb090d1419bcd67259d30960 100644 (file)
@@ -35,6 +35,7 @@
 #include <sys/mount.h>
 
 struct file;
+struct filecaps;
 enum idtype;
 struct itimerval;
 struct image_args;
@@ -150,8 +151,8 @@ int kern_openat(struct thread *td, int fd, char *path,
            enum uio_seg pathseg, int flags, int mode);
 int    kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg,
            int name, u_long flags);
-int    kern_pipe(struct thread *td, int fildes[2]);
-int    kern_pipe2(struct thread *td, int fildes[2], int flags);
+int    kern_pipe(struct thread *td, int fildes[2], int flags,
+           struct filecaps *fcaps1, struct filecaps *fcaps2);
 int    kern_poll(struct thread *td, struct pollfd *fds, u_int nfds,
            struct timespec *tsp, sigset_t *uset);
 int    kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,