Path: blob/main/contrib/capsicum-test/capability-fd-pair.cc
39475 views
// Tests involving 2 capability file descriptors.1#include <sys/types.h>2#include <sys/socket.h>3#include <fcntl.h>45#include "capsicum.h"6#include "syscalls.h"7#include "capsicum-test.h"89TEST(CapabilityPair, sendfile) {10int in_fd = open(TmpFile("cap_sendfile_in"), O_CREAT|O_RDWR, 0644);11EXPECT_OK(write(in_fd, "1234", 4));12// Output fd for sendfile must be a stream socket in FreeBSD.13int sock_fds[2];14EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));1516cap_rights_t r_rs;17cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);18cap_rights_t r_ws;19cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK);2021int cap_in_ro = dup(in_fd);22EXPECT_OK(cap_in_ro);23EXPECT_OK(cap_rights_limit(cap_in_ro, &r_rs));24int cap_in_wo = dup(in_fd);25EXPECT_OK(cap_in_wo);26EXPECT_OK(cap_rights_limit(cap_in_wo, &r_ws));27int cap_out_ro = dup(sock_fds[0]);28EXPECT_OK(cap_out_ro);29EXPECT_OK(cap_rights_limit(cap_out_ro, &r_rs));30int cap_out_wo = dup(sock_fds[0]);31EXPECT_OK(cap_out_wo);32EXPECT_OK(cap_rights_limit(cap_out_wo, &r_ws));3334off_t offset = 0;35EXPECT_NOTCAPABLE(sendfile_(cap_out_ro, cap_in_ro, &offset, 4));36EXPECT_NOTCAPABLE(sendfile_(cap_out_wo, cap_in_wo, &offset, 4));37EXPECT_OK(sendfile_(cap_out_wo, cap_in_ro, &offset, 4));3839close(cap_in_ro);40close(cap_in_wo);41close(cap_out_ro);42close(cap_out_wo);43close(in_fd);44close(sock_fds[0]);45close(sock_fds[1]);46unlink(TmpFile("cap_sendfile_in"));47}4849#ifdef HAVE_TEE50TEST(CapabilityPair, tee) {51int pipe1_fds[2];52EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK));53int pipe2_fds[2];54EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK));5556// Put some data into pipe1.57unsigned char buffer[4] = {1, 2, 3, 4};58EXPECT_OK(write(pipe1_fds[1], buffer, 4));5960cap_rights_t r_ro;61cap_rights_init(&r_ro, CAP_READ);62cap_rights_t r_wo;63cap_rights_init(&r_wo, CAP_WRITE);64cap_rights_t r_rw;65cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);6667// Various attempts to tee into pipe2.68int cap_in_wo = dup(pipe1_fds[0]);69EXPECT_OK(cap_in_wo);70EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo));71int cap_in_rw = dup(pipe1_fds[0]);72EXPECT_OK(cap_in_rw);73EXPECT_OK(cap_rights_limit(cap_in_rw, &r_rw));74int cap_out_ro = dup(pipe2_fds[1]);75EXPECT_OK(cap_out_ro);76EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro));77int cap_out_rw = dup(pipe2_fds[1]);78EXPECT_OK(cap_out_rw);79EXPECT_OK(cap_rights_limit(cap_out_rw, &r_rw));8081EXPECT_NOTCAPABLE(tee(cap_in_wo, cap_out_rw, 4, SPLICE_F_NONBLOCK));82EXPECT_NOTCAPABLE(tee(cap_in_rw, cap_out_ro, 4, SPLICE_F_NONBLOCK));83EXPECT_OK(tee(cap_in_rw, cap_out_rw, 4, SPLICE_F_NONBLOCK));8485close(cap_in_wo);86close(cap_in_rw);87close(cap_out_ro);88close(cap_out_rw);89close(pipe1_fds[0]);90close(pipe1_fds[1]);91close(pipe2_fds[0]);92close(pipe2_fds[1]);93}94#endif9596#ifdef HAVE_SPLICE97TEST(CapabilityPair, splice) {98int pipe1_fds[2];99EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK));100int pipe2_fds[2];101EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK));102103// Put some data into pipe1.104unsigned char buffer[4] = {1, 2, 3, 4};105EXPECT_OK(write(pipe1_fds[1], buffer, 4));106107cap_rights_t r_ro;108cap_rights_init(&r_ro, CAP_READ);109cap_rights_t r_wo;110cap_rights_init(&r_wo, CAP_WRITE);111cap_rights_t r_rs;112cap_rights_init(&r_rs, CAP_READ, CAP_SEEK);113cap_rights_t r_ws;114cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK);115116// Various attempts to splice.117int cap_in_wo = dup(pipe1_fds[0]);118EXPECT_OK(cap_in_wo);119EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo));120int cap_in_ro = dup(pipe1_fds[0]);121EXPECT_OK(cap_in_ro);122EXPECT_OK(cap_rights_limit(cap_in_ro, &r_ro));123int cap_in_ro_seek = dup(pipe1_fds[0]);124EXPECT_OK(cap_in_ro_seek);125EXPECT_OK(cap_rights_limit(cap_in_ro_seek, &r_rs));126int cap_out_wo = dup(pipe2_fds[1]);127EXPECT_OK(cap_out_wo);128EXPECT_OK(cap_rights_limit(cap_out_wo, &r_wo));129int cap_out_ro = dup(pipe2_fds[1]);130EXPECT_OK(cap_out_ro);131EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro));132int cap_out_wo_seek = dup(pipe2_fds[1]);133EXPECT_OK(cap_out_wo_seek);134EXPECT_OK(cap_rights_limit(cap_out_wo_seek, &r_ws));135136EXPECT_NOTCAPABLE(splice(cap_in_ro, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));137EXPECT_NOTCAPABLE(splice(cap_in_wo, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));138EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_ro, NULL, 4, SPLICE_F_NONBLOCK));139EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_wo, NULL, 4, SPLICE_F_NONBLOCK));140EXPECT_OK(splice(cap_in_ro_seek, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK));141142close(cap_in_wo);143close(cap_in_ro);144close(cap_in_ro_seek);145close(cap_out_wo);146close(cap_out_ro);147close(cap_out_wo_seek);148close(pipe1_fds[0]);149close(pipe1_fds[1]);150close(pipe2_fds[0]);151close(pipe2_fds[1]);152}153#endif154155#ifdef HAVE_VMSPLICE156// Although it only involves a single file descriptor, test vmsplice(2) here too.157TEST(CapabilityPair, vmsplice) {158int pipe_fds[2];159EXPECT_OK(pipe2(pipe_fds, O_NONBLOCK));160161cap_rights_t r_ro;162cap_rights_init(&r_ro, CAP_READ);163cap_rights_t r_rw;164cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);165166int cap_ro = dup(pipe_fds[1]);167EXPECT_OK(cap_ro);168EXPECT_OK(cap_rights_limit(cap_ro, &r_ro));169int cap_rw = dup(pipe_fds[1]);170EXPECT_OK(cap_rw);171EXPECT_OK(cap_rights_limit(cap_rw, &r_rw));172173unsigned char buffer[4] = {1, 2, 3, 4};174struct iovec iov;175memset(&iov, 0, sizeof(iov));176iov.iov_base = buffer;177iov.iov_len = sizeof(buffer);178179EXPECT_NOTCAPABLE(vmsplice(cap_ro, &iov, 1, SPLICE_F_NONBLOCK));180EXPECT_OK(vmsplice(cap_rw, &iov, 1, SPLICE_F_NONBLOCK));181182close(cap_ro);183close(cap_rw);184close(pipe_fds[0]);185close(pipe_fds[1]);186}187#endif188189190