Path: blob/main/tools/regression/capsicum/syscalls/cap_fcntls_limit.c
48255 views
/*-1* Copyright (c) 2012 The FreeBSD Foundation2*3* This software was developed by Pawel Jakub Dawidek under sponsorship from4* the FreeBSD Foundation.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/types.h>29#include <sys/capsicum.h>30#include <sys/procdesc.h>31#include <sys/socket.h>32#include <sys/wait.h>3334#include <err.h>35#include <errno.h>36#include <stdio.h>37#include <stdlib.h>38#include <unistd.h>3940#include "misc.h"4142static void43fcntl_tests_0(int fd)44{45uint32_t fcntlrights;4647fcntlrights = 0;48CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);49CHECK(fcntlrights == CAP_FCNTL_ALL);5051CHECK(fcntl(fd, F_GETFD) == 0);52CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);53CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);54CHECK(fcntl(fd, F_SETFD, 0) == 0);55CHECK(fcntl(fd, F_GETFD) == 0);5657CHECK(fcntl(fd, F_GETFL) == O_RDWR);58CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);59CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));60CHECK(fcntl(fd, F_SETFL, 0) == 0);61CHECK(fcntl(fd, F_GETFL) == O_RDWR);6263errno = 0;64CHECK(cap_fcntls_limit(fd, ~CAP_FCNTL_ALL) == -1);65CHECK(errno == EINVAL);66CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);67fcntlrights = 0;68CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);69CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));70CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);71fcntlrights = 0;72CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);73CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));7475CHECK(fcntl(fd, F_GETFD) == 0);76CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);77CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);78CHECK(fcntl(fd, F_SETFD, 0) == 0);79CHECK(fcntl(fd, F_GETFD) == 0);8081CHECK(fcntl(fd, F_GETFL) == O_RDWR);82CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);83CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));84CHECK(fcntl(fd, F_SETFL, 0) == 0);85CHECK(fcntl(fd, F_GETFL) == O_RDWR);8687CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);88fcntlrights = 0;89CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);90CHECK(fcntlrights == CAP_FCNTL_GETFL);91errno = 0;92CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);93CHECK(errno == ENOTCAPABLE);94fcntlrights = 0;95CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);96CHECK(fcntlrights == CAP_FCNTL_GETFL);9798CHECK(fcntl(fd, F_GETFD) == 0);99CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);100CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);101CHECK(fcntl(fd, F_SETFD, 0) == 0);102CHECK(fcntl(fd, F_GETFD) == 0);103104CHECK(fcntl(fd, F_GETFL) == O_RDWR);105errno = 0;106CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);107CHECK(errno == ENOTCAPABLE);108CHECK(fcntl(fd, F_GETFL) == O_RDWR);109errno = 0;110CHECK(fcntl(fd, F_SETFL, 0) == -1);111CHECK(errno == ENOTCAPABLE);112CHECK(fcntl(fd, F_GETFL) == O_RDWR);113114CHECK(cap_fcntls_limit(fd, 0) == 0);115fcntlrights = CAP_FCNTL_ALL;116CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);117CHECK(fcntlrights == 0);118errno = 0;119CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);120CHECK(errno == ENOTCAPABLE);121fcntlrights = CAP_FCNTL_ALL;122CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);123CHECK(fcntlrights == 0);124errno = 0;125CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);126CHECK(errno == ENOTCAPABLE);127fcntlrights = CAP_FCNTL_ALL;128CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);129CHECK(fcntlrights == 0);130131CHECK(fcntl(fd, F_GETFD) == 0);132CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);133CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);134CHECK(fcntl(fd, F_SETFD, 0) == 0);135CHECK(fcntl(fd, F_GETFD) == 0);136137errno = 0;138CHECK(fcntl(fd, F_GETFL) == -1);139CHECK(errno == ENOTCAPABLE);140errno = 0;141CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);142CHECK(errno == ENOTCAPABLE);143errno = 0;144CHECK(fcntl(fd, F_SETFL, 0) == -1);145CHECK(errno == ENOTCAPABLE);146errno = 0;147CHECK(fcntl(fd, F_GETFL) == -1);148CHECK(errno == ENOTCAPABLE);149}150151static void152fcntl_tests_1(int fd)153{154uint32_t fcntlrights;155cap_rights_t rights;156157CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);158fcntlrights = 0;159CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);160CHECK(fcntlrights == CAP_FCNTL_GETFL);161162CAP_ALL(&rights);163cap_rights_clear(&rights, CAP_FCNTL);164CHECK(cap_rights_limit(fd, &rights) == 0);165166fcntlrights = CAP_FCNTL_ALL;167CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);168CHECK(fcntlrights == 0);169170errno = 0;171CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);172CHECK(errno == ENOTCAPABLE);173fcntlrights = CAP_FCNTL_ALL;174CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);175CHECK(fcntlrights == 0);176errno = 0;177CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);178CHECK(errno == ENOTCAPABLE);179fcntlrights = CAP_FCNTL_ALL;180CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);181CHECK(fcntlrights == 0);182183CHECK(fcntl(fd, F_GETFD) == 0);184CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);185CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);186CHECK(fcntl(fd, F_SETFD, 0) == 0);187CHECK(fcntl(fd, F_GETFD) == 0);188189errno = 0;190CHECK(fcntl(fd, F_GETFL) == -1);191CHECK(errno == ENOTCAPABLE);192errno = 0;193CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);194CHECK(errno == ENOTCAPABLE);195errno = 0;196CHECK(fcntl(fd, F_SETFL, 0) == -1);197CHECK(errno == ENOTCAPABLE);198errno = 0;199CHECK(fcntl(fd, F_GETFL) == -1);200CHECK(errno == ENOTCAPABLE);201}202203static void204fcntl_tests_2(int fd)205{206uint32_t fcntlrights;207cap_rights_t rights;208209CAP_ALL(&rights);210cap_rights_clear(&rights, CAP_FCNTL);211CHECK(cap_rights_limit(fd, &rights) == 0);212213fcntlrights = CAP_FCNTL_ALL;214CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);215CHECK(fcntlrights == 0);216217errno = 0;218CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);219CHECK(errno == ENOTCAPABLE);220fcntlrights = CAP_FCNTL_ALL;221CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);222CHECK(fcntlrights == 0);223errno = 0;224CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);225CHECK(errno == ENOTCAPABLE);226fcntlrights = CAP_FCNTL_ALL;227CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);228CHECK(fcntlrights == 0);229230CHECK(fcntl(fd, F_GETFD) == 0);231CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);232CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);233CHECK(fcntl(fd, F_SETFD, 0) == 0);234CHECK(fcntl(fd, F_GETFD) == 0);235236errno = 0;237CHECK(fcntl(fd, F_GETFL) == -1);238CHECK(errno == ENOTCAPABLE);239errno = 0;240CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);241CHECK(errno == ENOTCAPABLE);242errno = 0;243CHECK(fcntl(fd, F_SETFL, 0) == -1);244CHECK(errno == ENOTCAPABLE);245errno = 0;246CHECK(fcntl(fd, F_GETFL) == -1);247CHECK(errno == ENOTCAPABLE);248}249250static void251fcntl_tests_send_0(int sock)252{253int fd;254255CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);256CHECK(descriptor_send(sock, fd) == 0);257CHECK(close(fd) == 0);258259CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);260CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);261CHECK(descriptor_send(sock, fd) == 0);262CHECK(close(fd) == 0);263264CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);265CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);266CHECK(descriptor_send(sock, fd) == 0);267CHECK(close(fd) == 0);268269CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);270CHECK(cap_fcntls_limit(fd, 0) == 0);271CHECK(descriptor_send(sock, fd) == 0);272CHECK(close(fd) == 0);273}274275static void276fcntl_tests_recv_0(int sock)277{278uint32_t fcntlrights;279int fd;280281CHECK(descriptor_recv(sock, &fd) == 0);282283fcntlrights = 0;284CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);285CHECK(fcntlrights == CAP_FCNTL_ALL);286287CHECK(fcntl(fd, F_GETFD) == 0);288CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);289CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);290CHECK(fcntl(fd, F_SETFD, 0) == 0);291CHECK(fcntl(fd, F_GETFD) == 0);292293CHECK(fcntl(fd, F_GETFL) == O_RDWR);294CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);295CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));296CHECK(fcntl(fd, F_SETFL, 0) == 0);297CHECK(fcntl(fd, F_GETFL) == O_RDWR);298299CHECK(close(fd) == 0);300301CHECK(descriptor_recv(sock, &fd) == 0);302303fcntlrights = 0;304CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);305CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));306CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);307fcntlrights = 0;308CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);309CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));310311CHECK(fcntl(fd, F_GETFD) == 0);312CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);313CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);314CHECK(fcntl(fd, F_SETFD, 0) == 0);315CHECK(fcntl(fd, F_GETFD) == 0);316317CHECK(fcntl(fd, F_GETFL) == O_RDWR);318CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);319CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));320CHECK(fcntl(fd, F_SETFL, 0) == 0);321CHECK(fcntl(fd, F_GETFL) == O_RDWR);322323CHECK(close(fd) == 0);324325CHECK(descriptor_recv(sock, &fd) == 0);326327fcntlrights = 0;328CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);329CHECK(fcntlrights == CAP_FCNTL_GETFL);330errno = 0;331CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);332CHECK(errno == ENOTCAPABLE);333fcntlrights = 0;334CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);335CHECK(fcntlrights == CAP_FCNTL_GETFL);336CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);337fcntlrights = 0;338CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);339CHECK(fcntlrights == CAP_FCNTL_GETFL);340341CHECK(fcntl(fd, F_GETFD) == 0);342CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);343CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);344CHECK(fcntl(fd, F_SETFD, 0) == 0);345CHECK(fcntl(fd, F_GETFD) == 0);346347CHECK(fcntl(fd, F_GETFL) == O_RDWR);348errno = 0;349CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);350CHECK(errno == ENOTCAPABLE);351CHECK(fcntl(fd, F_GETFL) == O_RDWR);352errno = 0;353CHECK(fcntl(fd, F_SETFL, 0) == -1);354CHECK(errno == ENOTCAPABLE);355CHECK(fcntl(fd, F_GETFL) == O_RDWR);356357CHECK(close(fd) == 0);358359CHECK(descriptor_recv(sock, &fd) == 0);360361fcntlrights = 0;362CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);363CHECK(fcntlrights == 0);364errno = 0;365CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);366CHECK(errno == ENOTCAPABLE);367fcntlrights = 0;368CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);369CHECK(fcntlrights == 0);370errno = 0;371CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);372CHECK(errno == ENOTCAPABLE);373fcntlrights = 0;374CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);375CHECK(fcntlrights == 0);376errno = 0;377CHECK(cap_fcntls_limit(fd, CAP_FCNTL_SETFL) == -1);378CHECK(errno == ENOTCAPABLE);379fcntlrights = 0;380CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);381CHECK(fcntlrights == 0);382383CHECK(fcntl(fd, F_GETFD) == 0);384CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);385CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);386CHECK(fcntl(fd, F_SETFD, 0) == 0);387CHECK(fcntl(fd, F_GETFD) == 0);388389errno = 0;390CHECK(fcntl(fd, F_GETFL) == -1);391CHECK(errno == ENOTCAPABLE);392errno = 0;393CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);394CHECK(errno == ENOTCAPABLE);395errno = 0;396CHECK(fcntl(fd, F_SETFL, 0) == -1);397CHECK(errno == ENOTCAPABLE);398errno = 0;399CHECK(fcntl(fd, F_GETFL) == -1);400CHECK(errno == ENOTCAPABLE);401402CHECK(close(fd) == 0);403}404405int406main(void)407{408int fd, pfd, sp[2];409pid_t pid;410411printf("1..870\n");412413CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);414fcntl_tests_0(fd);415CHECK(close(fd) == 0);416417CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);418fcntl_tests_1(fd);419CHECK(close(fd) == 0);420421CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);422fcntl_tests_2(fd);423CHECK(close(fd) == 0);424425/* Child inherits descriptor and operates on it first. */426CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);427CHECK((pid = fork()) >= 0);428if (pid == 0) {429fcntl_tests_0(fd);430CHECK(close(fd) == 0);431exit(0);432} else {433CHECK(waitpid(pid, NULL, 0) == pid);434fcntl_tests_0(fd);435}436CHECK(close(fd) == 0);437438/* Child inherits descriptor, but operates on it after parent. */439CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);440CHECK((pid = fork()) >= 0);441if (pid == 0) {442sleep(1);443fcntl_tests_0(fd);444CHECK(close(fd) == 0);445exit(0);446} else {447fcntl_tests_0(fd);448CHECK(waitpid(pid, NULL, 0) == pid);449}450CHECK(close(fd) == 0);451452/* Child inherits descriptor and operates on it first. */453CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);454CHECK((pid = pdfork(&pfd, 0)) >= 0);455if (pid == 0) {456fcntl_tests_1(fd);457exit(0);458} else {459CHECK(pdwait(pfd) == 0);460/*461It fails with EBADF, which I believe is a bug.462CHECK(close(pfd) == 0);463*/464fcntl_tests_1(fd);465}466CHECK(close(fd) == 0);467468/* Child inherits descriptor, but operates on it after parent. */469CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);470CHECK((pid = pdfork(&pfd, 0)) >= 0);471if (pid == 0) {472sleep(1);473fcntl_tests_1(fd);474exit(0);475} else {476fcntl_tests_1(fd);477CHECK(pdwait(pfd) == 0);478/*479It fails with EBADF, which I believe is a bug.480CHECK(close(pfd) == 0);481*/482}483CHECK(close(fd) == 0);484485/* Child inherits descriptor and operates on it first. */486CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);487CHECK((pid = fork()) >= 0);488if (pid == 0) {489fcntl_tests_2(fd);490exit(0);491} else {492CHECK(waitpid(pid, NULL, 0) == pid);493fcntl_tests_2(fd);494}495CHECK(close(fd) == 0);496497/* Child inherits descriptor, but operates on it after parent. */498CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);499CHECK((pid = fork()) >= 0);500if (pid == 0) {501sleep(1);502fcntl_tests_2(fd);503exit(0);504} else {505fcntl_tests_2(fd);506CHECK(waitpid(pid, NULL, 0) == pid);507}508CHECK(close(fd) == 0);509510/* Send descriptors from parent to child. */511CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);512CHECK((pid = fork()) >= 0);513if (pid == 0) {514CHECK(close(sp[0]) == 0);515fcntl_tests_recv_0(sp[1]);516CHECK(close(sp[1]) == 0);517exit(0);518} else {519CHECK(close(sp[1]) == 0);520fcntl_tests_send_0(sp[0]);521CHECK(waitpid(pid, NULL, 0) == pid);522CHECK(close(sp[0]) == 0);523}524525/* Send descriptors from child to parent. */526CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);527CHECK((pid = fork()) >= 0);528if (pid == 0) {529CHECK(close(sp[0]) == 0);530fcntl_tests_send_0(sp[1]);531CHECK(close(sp[1]) == 0);532exit(0);533} else {534CHECK(close(sp[1]) == 0);535fcntl_tests_recv_0(sp[0]);536CHECK(waitpid(pid, NULL, 0) == pid);537CHECK(close(sp[0]) == 0);538}539540exit(0);541}542543544