Path: blob/main/tools/regression/security/cap_test/cap_test_capabilities.c
48266 views
/*-1* Copyright (c) 2009-2011 Robert N. M. Watson2* Copyright (c) 2011 Jonathan Anderson3* Copyright (c) 2012 FreeBSD Foundation4* All rights reserved.5*6* Portions of this software were developed by Pawel Jakub Dawidek under7* sponsorship from the FreeBSD Foundation.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031/*32* Test whether various operations on capabilities are properly masked for33* various object types.34*/3536#include <sys/param.h>37#include <sys/capsicum.h>38#include <sys/errno.h>39#include <sys/mman.h>40#include <sys/mount.h>41#include <sys/stat.h>4243#include <err.h>44#include <fcntl.h>45#include <poll.h>46#include <stdint.h>47#include <stdio.h>48#include <stdlib.h>49#include <string.h>50#include <unistd.h>5152#include "cap_test.h"5354#define SYSCALL_FAIL(syscall, message) \55FAIL("%s:\t%s (rights 0x%jx)", #syscall, message, rights)5657/*58* Ensure that, if the capability had enough rights for the system call to59* pass, then it did. Otherwise, ensure that the errno is ENOTCAPABLE;60* capability restrictions should kick in before any other error logic.61*/62#define CHECK_RESULT(syscall, rights_needed, succeeded) do { \63if ((rights & (rights_needed)) == (rights_needed)) { \64if (succeeded) { \65if (success == -1) \66success = PASSED; \67} else { \68SYSCALL_FAIL(syscall, "failed"); \69} \70} else { \71if (succeeded) { \72FAILX("%s:\tsucceeded when it shouldn't have" \73" (rights 0x%jx)", #syscall, \74(uintmax_t)rights); \75} else if (errno != ENOTCAPABLE) { \76SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \77} \78} \79errno = 0; \80} while (0)8182/*83* As above, but for the special mmap() case: unmap after successful mmap().84*/85#define CHECK_MMAP_RESULT(rights_needed) do { \86if ((rights & (rights_needed)) == (rights_needed)) { \87if (p == MAP_FAILED) \88SYSCALL_FAIL(mmap, "failed"); \89else { \90(void)munmap(p, getpagesize()); \91if (success == -1) \92success = PASSED; \93} \94} else { \95if (p != MAP_FAILED) { \96FAILX("%s:\tsucceeded when it shouldn't have" \97" (rights 0x%jx)", "mmap", rights); \98(void)munmap(p, getpagesize()); \99} else if (errno != ENOTCAPABLE) \100SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \101} \102errno = 0; \103} while (0)104105/*106* Given a file descriptor, create a capability with specific rights and107* make sure only those rights work.108*/109static int110try_file_ops(int filefd, int dirfd, cap_rights_t rights)111{112struct stat sb;113struct statfs sf;114cap_rights_t erights;115int fd_cap, fd_capcap, dfd_cap;116ssize_t ssize, ssize2;117off_t off;118void *p;119char ch;120int ret, is_nfs;121struct pollfd pollfd;122int success = -1;123124REQUIRE(fstatfs(filefd, &sf));125is_nfs = (strcmp("nfs", sf.f_fstypename) == 0);126127REQUIRE(fd_cap = cap_new(filefd, rights));128CHECK(cap_getrights(fd_cap, &erights) == 0);129CHECK(rights == erights);130REQUIRE(fd_capcap = cap_new(fd_cap, rights));131CHECK(cap_getrights(fd_capcap, &erights) == 0);132CHECK(rights == erights);133CHECK(fd_capcap != fd_cap);134REQUIRE(dfd_cap = cap_new(dirfd, rights));135CHECK(cap_getrights(dfd_cap, &erights) == 0);136CHECK(rights == erights);137138ssize = read(fd_cap, &ch, sizeof(ch));139CHECK_RESULT(read, CAP_READ, ssize >= 0);140141ssize = write(fd_cap, &ch, sizeof(ch));142CHECK_RESULT(write, CAP_WRITE, ssize >= 0);143144off = lseek(fd_cap, 0, SEEK_SET);145CHECK_RESULT(lseek, CAP_SEEK, off >= 0);146147ssize = pread(fd_cap, &ch, sizeof(ch), 0);148ssize2 = pread(fd_cap, &ch, sizeof(ch), 0);149CHECK_RESULT(pread, CAP_PREAD, ssize >= 0);150CHECK(ssize == ssize2);151152ssize = pwrite(fd_cap, &ch, sizeof(ch), 0);153CHECK_RESULT(pwrite, CAP_PWRITE, ssize >= 0);154155p = mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, fd_cap, 0);156CHECK_MMAP_RESULT(CAP_MMAP);157158p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0);159CHECK_MMAP_RESULT(CAP_MMAP_R);160161p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0);162CHECK_MMAP_RESULT(CAP_MMAP_W);163164p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0);165CHECK_MMAP_RESULT(CAP_MMAP_X);166167p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED,168fd_cap, 0);169CHECK_MMAP_RESULT(CAP_MMAP_RW);170171p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED,172fd_cap, 0);173CHECK_MMAP_RESULT(CAP_MMAP_RX);174175p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED,176fd_cap, 0);177CHECK_MMAP_RESULT(CAP_MMAP_WX);178179p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,180MAP_SHARED, fd_cap, 0);181CHECK_MMAP_RESULT(CAP_MMAP_RWX);182183ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600);184CHECK_RESULT(openat(O_CREATE | O_RDONLY),185CAP_CREATE | CAP_READ | CAP_LOOKUP, ret >= 0);186CHECK(ret == -1 || close(ret) == 0);187CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);188ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND,1890600);190CHECK_RESULT(openat(O_CREATE | O_WRONLY | O_APPEND),191CAP_CREATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);192CHECK(ret == -1 || close(ret) == 0);193CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);194ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600);195CHECK_RESULT(openat(O_CREATE | O_RDWR | O_APPEND),196CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);197CHECK(ret == -1 || close(ret) == 0);198CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);199200ret = fsync(fd_cap);201CHECK_RESULT(fsync, CAP_FSYNC, ret == 0);202203ret = openat(dirfd, "cap_fsync", O_CREAT, 0600);204CHECK(ret >= 0);205CHECK(close(ret) == 0);206ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY);207CHECK_RESULT(openat(O_FSYNC | O_RDONLY),208CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);209CHECK(ret == -1 || close(ret) == 0);210ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND);211CHECK_RESULT(openat(O_FSYNC | O_WRONLY | O_APPEND),212CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);213CHECK(ret == -1 || close(ret) == 0);214ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND);215CHECK_RESULT(openat(O_FSYNC | O_RDWR | O_APPEND),216CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);217CHECK(ret == -1 || close(ret) == 0);218ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY);219CHECK_RESULT(openat(O_SYNC | O_RDONLY),220CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);221CHECK(ret == -1 || close(ret) == 0);222ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND);223CHECK_RESULT(openat(O_SYNC | O_WRONLY | O_APPEND),224CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);225CHECK(ret == -1 || close(ret) == 0);226ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND);227CHECK_RESULT(openat(O_SYNC | O_RDWR | O_APPEND),228CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);229CHECK(ret == -1 || close(ret) == 0);230CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0);231232ret = ftruncate(fd_cap, 0);233CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0);234235ret = openat(dirfd, "cap_ftruncate", O_CREAT, 0600);236CHECK(ret >= 0);237CHECK(close(ret) == 0);238ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY);239CHECK_RESULT(openat(O_TRUNC | O_RDONLY),240CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP, ret >= 0);241CHECK(ret == -1 || close(ret) == 0);242ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY);243CHECK_RESULT(openat(O_TRUNC | O_WRONLY),244CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);245CHECK(ret == -1 || close(ret) == 0);246ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR);247CHECK_RESULT(openat(O_TRUNC | O_RDWR),248CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);249CHECK(ret == -1 || close(ret) == 0);250CHECK(unlinkat(dirfd, "cap_ftruncate", 0) == 0);251252ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600);253CHECK_RESULT(openat(O_CREATE | O_WRONLY),254CAP_CREATE | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);255CHECK(ret == -1 || close(ret) == 0);256CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);257ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600);258CHECK_RESULT(openat(O_CREATE | O_RDWR),259CAP_CREATE | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP,260ret >= 0);261CHECK(ret == -1 || close(ret) == 0);262CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);263264ret = openat(dirfd, "cap_fsync", O_CREAT, 0600);265CHECK(ret >= 0);266CHECK(close(ret) == 0);267ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY);268CHECK_RESULT(openat(O_FSYNC | O_WRONLY),269CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);270CHECK(ret == -1 || close(ret) == 0);271ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR);272CHECK_RESULT(openat(O_FSYNC | O_RDWR),273CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);274CHECK(ret == -1 || close(ret) == 0);275ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY);276CHECK_RESULT(openat(O_SYNC | O_WRONLY),277CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);278CHECK(ret == -1 || close(ret) == 0);279ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR);280CHECK_RESULT(openat(O_SYNC | O_RDWR),281CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0);282CHECK(ret == -1 || close(ret) == 0);283CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0);284285/*286* Note: this is not expected to work over NFS.287*/288ret = fchflags(fd_cap, UF_NODUMP);289CHECK_RESULT(fchflags, CAP_FCHFLAGS,290ret == 0 || (is_nfs && errno == EOPNOTSUPP));291292ret = openat(dirfd, "cap_chflagsat", O_CREAT, 0600);293CHECK(ret >= 0);294CHECK(close(ret) == 0);295ret = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0);296CHECK_RESULT(chflagsat, CAP_CHFLAGSAT | CAP_LOOKUP, ret == 0);297CHECK(unlinkat(dirfd, "cap_chflagsat", 0) == 0);298299ret = fchown(fd_cap, -1, -1);300CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0);301302ret = openat(dirfd, "cap_fchownat", O_CREAT, 0600);303CHECK(ret >= 0);304CHECK(close(ret) == 0);305ret = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0);306CHECK_RESULT(fchownat, CAP_FCHOWN | CAP_LOOKUP, ret == 0);307CHECK(unlinkat(dirfd, "cap_fchownat", 0) == 0);308309ret = fchmod(fd_cap, 0644);310CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0);311312ret = openat(dirfd, "cap_fchmodat", O_CREAT, 0600);313CHECK(ret >= 0);314CHECK(close(ret) == 0);315ret = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0);316CHECK_RESULT(fchmodat, CAP_FCHMOD | CAP_LOOKUP, ret == 0);317CHECK(unlinkat(dirfd, "cap_fchmodat", 0) == 0);318319ret = fcntl(fd_cap, F_GETFL);320CHECK_RESULT(fcntl(F_GETFL), CAP_FCNTL, ret >= 0);321ret = fcntl(fd_cap, F_SETFL, ret);322CHECK_RESULT(fcntl(F_SETFL), CAP_FCNTL, ret == 0);323324/* XXX flock */325326ret = fstat(fd_cap, &sb);327CHECK_RESULT(fstat, CAP_FSTAT, ret == 0);328329ret = openat(dirfd, "cap_fstatat", O_CREAT, 0600);330CHECK(ret >= 0);331CHECK(close(ret) == 0);332ret = fstatat(dfd_cap, "cap_fstatat", &sb, 0);333CHECK_RESULT(fstatat, CAP_FSTAT | CAP_LOOKUP, ret == 0);334CHECK(unlinkat(dirfd, "cap_fstatat", 0) == 0);335336ret = fstatfs(fd_cap, &sf);337CHECK_RESULT(fstatfs, CAP_FSTATFS, ret == 0);338339ret = fpathconf(fd_cap, _PC_NAME_MAX);340CHECK_RESULT(fpathconf, CAP_FPATHCONF, ret >= 0);341342ret = futimes(fd_cap, NULL);343CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0);344345ret = openat(dirfd, "cap_futimesat", O_CREAT, 0600);346CHECK(ret >= 0);347CHECK(close(ret) == 0);348ret = futimesat(dfd_cap, "cap_futimesat", NULL);349CHECK_RESULT(futimesat, CAP_FUTIMES | CAP_LOOKUP, ret == 0);350CHECK(unlinkat(dirfd, "cap_futimesat", 0) == 0);351352ret = openat(dirfd, "cap_linkat_src", O_CREAT, 0600);353CHECK(ret >= 0);354CHECK(close(ret) == 0);355ret = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0);356CHECK_RESULT(linkat, CAP_LINKAT | CAP_LOOKUP, ret == 0);357CHECK(unlinkat(dirfd, "cap_linkat_src", 0) == 0);358CHECK(ret == -1 || unlinkat(dirfd, "cap_linkat_dst", 0) == 0);359360ret = mkdirat(dfd_cap, "cap_mkdirat", 0700);361CHECK_RESULT(mkdirat, CAP_MKDIRAT | CAP_LOOKUP, ret == 0);362CHECK(ret == -1 || unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR) == 0);363364ret = mkfifoat(dfd_cap, "cap_mkfifoat", 0600);365CHECK_RESULT(mkfifoat, CAP_MKFIFOAT | CAP_LOOKUP, ret == 0);366CHECK(ret == -1 || unlinkat(dirfd, "cap_mkfifoat", 0) == 0);367368ret = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0);369CHECK_RESULT(mknodat, CAP_MKNODAT | CAP_LOOKUP, ret == 0);370CHECK(ret == -1 || unlinkat(dirfd, "cap_mknodat", 0) == 0);371372/* TODO: renameat(2) */373374ret = symlinkat("test", dfd_cap, "cap_symlinkat");375CHECK_RESULT(symlinkat, CAP_SYMLINKAT | CAP_LOOKUP, ret == 0);376CHECK(ret == -1 || unlinkat(dirfd, "cap_symlinkat", 0) == 0);377378ret = openat(dirfd, "cap_unlinkat", O_CREAT, 0600);379CHECK(ret >= 0);380CHECK(close(ret) == 0);381ret = unlinkat(dfd_cap, "cap_unlinkat", 0);382CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);383CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", 0) == 0);384ret = mkdirat(dirfd, "cap_unlinkat", 0700);385CHECK(ret == 0);386ret = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR);387CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);388CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR) == 0);389390pollfd.fd = fd_cap;391pollfd.events = POLLIN | POLLERR | POLLHUP;392pollfd.revents = 0;393394ret = poll(&pollfd, 1, 0);395if (rights & CAP_EVENT)396CHECK((pollfd.revents & POLLNVAL) == 0);397else398CHECK((pollfd.revents & POLLNVAL) != 0);399400/* XXX: select, kqueue */401402close(fd_cap);403close(fd_capcap);404405if (success == -1) {406fprintf(stderr, "No tests for rights 0x%jx.\n",407(uintmax_t)rights);408success = FAILED;409}410return (success);411}412413#define TRY(rights) \414do { \415if (success == PASSED) \416success = try_file_ops(filefd, dirfd, (rights)); \417else \418/* We've already failed, but try the test anyway. */ \419try_file_ops(filefd, dirfd, (rights)); \420} while (0)421422#define KEEP_ERRNO(...) do { \423int _saved_errno = errno; \424__VA_ARGS__; \425errno = _saved_errno; \426} while (0);427428int429test_capabilities(void)430{431int filefd, dirfd, tmpfd;432int success = PASSED;433char file[] = "/tmp/cap_test.XXXXXXXXXX";434char dir[] = "/tmp/cap_test.XXXXXXXXXX";435436filefd = mkstemp(file);437if (filefd < 0)438err(-1, "mkstemp");439if (mkdtemp(dir) == NULL) {440KEEP_ERRNO(unlink(file));441err(-1, "mkdtemp");442}443dirfd = open(dir, O_RDONLY | O_DIRECTORY);444if (dirfd == -1) {445KEEP_ERRNO(unlink(file));446KEEP_ERRNO(rmdir(dir));447err(-1, "open");448}449tmpfd = open("/tmp", O_RDONLY | O_DIRECTORY);450if (tmpfd == -1) {451KEEP_ERRNO(unlink(file));452KEEP_ERRNO(rmdir(dir));453err(-1, "open");454}455456if (cap_enter() == -1) {457KEEP_ERRNO(unlink(file));458KEEP_ERRNO(rmdir(dir));459err(-1, "cap_enter");460}461462TRY(CAP_READ);463TRY(CAP_WRITE);464TRY(CAP_SEEK);465TRY(CAP_PREAD);466TRY(CAP_PWRITE);467TRY(CAP_READ | CAP_WRITE);468TRY(CAP_PREAD | CAP_PWRITE);469TRY(CAP_MMAP);470TRY(CAP_MMAP_R);471TRY(CAP_MMAP_W);472TRY(CAP_MMAP_X);473TRY(CAP_MMAP_RW);474TRY(CAP_MMAP_RX);475TRY(CAP_MMAP_WX);476TRY(CAP_MMAP_RWX);477TRY(CAP_CREATE | CAP_READ | CAP_LOOKUP);478TRY(CAP_CREATE | CAP_WRITE | CAP_LOOKUP);479TRY(CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);480#ifdef TODO481TRY(CAP_FEXECVE);482#endif483TRY(CAP_FSYNC);484TRY(CAP_FSYNC | CAP_READ | CAP_LOOKUP);485TRY(CAP_FSYNC | CAP_WRITE | CAP_LOOKUP);486TRY(CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP);487TRY(CAP_FTRUNCATE);488TRY(CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP);489TRY(CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP);490TRY(CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);491#ifdef TODO492TRY(CAP_FCHDIR);493#endif494TRY(CAP_FCHFLAGS);495TRY(CAP_FCHOWN);496TRY(CAP_FCHOWN | CAP_LOOKUP);497TRY(CAP_FCHMOD | CAP_LOOKUP);498TRY(CAP_FCNTL);499#ifdef TODO500TRY(CAP_FLOCK);501#endif502TRY(CAP_FPATHCONF);503#ifdef TODO504TRY(CAP_FSCK);505#endif506TRY(CAP_FSTAT | CAP_LOOKUP);507TRY(CAP_FSTATFS);508TRY(CAP_FUTIMES | CAP_LOOKUP);509TRY(CAP_LINKAT | CAP_LOOKUP);510TRY(CAP_MKDIRAT | CAP_LOOKUP);511TRY(CAP_MKFIFOAT | CAP_LOOKUP);512TRY(CAP_MKNODAT | CAP_LOOKUP);513TRY(CAP_SYMLINKAT | CAP_LOOKUP);514TRY(CAP_UNLINKAT | CAP_LOOKUP);515/* Rename needs CAP_RENAMEAT on source directory and CAP_LINKAT on destination directory. */516TRY(CAP_RENAMEAT | CAP_UNLINKAT | CAP_LOOKUP);517#ifdef TODO518TRY(CAP_LOOKUP);519TRY(CAP_EXTATTR_DELETE);520TRY(CAP_EXTATTR_GET);521TRY(CAP_EXTATTR_LIST);522TRY(CAP_EXTATTR_SET);523TRY(CAP_ACL_CHECK);524TRY(CAP_ACL_DELETE);525TRY(CAP_ACL_GET);526TRY(CAP_ACL_SET);527TRY(CAP_ACCEPT);528TRY(CAP_BIND);529TRY(CAP_CONNECT);530TRY(CAP_GETPEERNAME);531TRY(CAP_GETSOCKNAME);532TRY(CAP_GETSOCKOPT);533TRY(CAP_LISTEN);534TRY(CAP_PEELOFF);535TRY(CAP_RECV);536TRY(CAP_SEND);537TRY(CAP_SETSOCKOPT);538TRY(CAP_SHUTDOWN);539TRY(CAP_MAC_GET);540TRY(CAP_MAC_SET);541TRY(CAP_SEM_GETVALUE);542TRY(CAP_SEM_POST);543TRY(CAP_SEM_WAIT);544TRY(CAP_POST_EVENT);545TRY(CAP_EVENT);546TRY(CAP_IOCTL);547TRY(CAP_TTYHOOK);548TRY(CAP_PDGETPID);549TRY(CAP_PDWAIT);550TRY(CAP_PDKILL);551#endif552553(void)unlinkat(tmpfd, file + strlen("/tmp/"), 0);554(void)unlinkat(tmpfd, dir + strlen("/tmp/"), AT_REMOVEDIR);555556return (success);557}558559560