1da749672SJonathan Anderson /*- 2da749672SJonathan Anderson * Copyright (c) 2009-2011 Robert N. M. Watson 3da749672SJonathan Anderson * Copyright (c) 2011 Jonathan Anderson 4f2908898SPawel Jakub Dawidek * Copyright (c) 2012 FreeBSD Foundation 5da749672SJonathan Anderson * All rights reserved. 6da749672SJonathan Anderson * 7f2908898SPawel Jakub Dawidek * Portions of this software were developed by Pawel Jakub Dawidek under 8f2908898SPawel Jakub Dawidek * sponsorship from the FreeBSD Foundation. 9f2908898SPawel Jakub Dawidek * 10da749672SJonathan Anderson * Redistribution and use in source and binary forms, with or without 11da749672SJonathan Anderson * modification, are permitted provided that the following conditions 12da749672SJonathan Anderson * are met: 13da749672SJonathan Anderson * 1. Redistributions of source code must retain the above copyright 14da749672SJonathan Anderson * notice, this list of conditions and the following disclaimer. 15da749672SJonathan Anderson * 2. Redistributions in binary form must reproduce the above copyright 16da749672SJonathan Anderson * notice, this list of conditions and the following disclaimer in the 17da749672SJonathan Anderson * documentation and/or other materials provided with the distribution. 18da749672SJonathan Anderson * 19da749672SJonathan Anderson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20da749672SJonathan Anderson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21da749672SJonathan Anderson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22da749672SJonathan Anderson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23da749672SJonathan Anderson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24da749672SJonathan Anderson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25da749672SJonathan Anderson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26da749672SJonathan Anderson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27da749672SJonathan Anderson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28da749672SJonathan Anderson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29da749672SJonathan Anderson * SUCH DAMAGE. 30da749672SJonathan Anderson */ 31da749672SJonathan Anderson 32da749672SJonathan Anderson /* 33da749672SJonathan Anderson * Test whether various operations on capabilities are properly masked for 34da749672SJonathan Anderson * various object types. 35da749672SJonathan Anderson */ 36da749672SJonathan Anderson 37da749672SJonathan Anderson #include <sys/cdefs.h> 38da749672SJonathan Anderson __FBSDID("$FreeBSD$"); 39da749672SJonathan Anderson 40da749672SJonathan Anderson #include <sys/param.h> 41da749672SJonathan Anderson #include <sys/capability.h> 42da749672SJonathan Anderson #include <sys/errno.h> 43da749672SJonathan Anderson #include <sys/mman.h> 44da749672SJonathan Anderson #include <sys/mount.h> 45da749672SJonathan Anderson #include <sys/stat.h> 46da749672SJonathan Anderson 47da749672SJonathan Anderson #include <err.h> 48da749672SJonathan Anderson #include <fcntl.h> 49d6f72489SJonathan Anderson #include <poll.h> 50f2908898SPawel Jakub Dawidek #include <stdint.h> 51da749672SJonathan Anderson #include <stdio.h> 52da749672SJonathan Anderson #include <stdlib.h> 53b7f2d66aSJonathan Anderson #include <string.h> 54da749672SJonathan Anderson #include <unistd.h> 55da749672SJonathan Anderson 56da749672SJonathan Anderson #include "cap_test.h" 57da749672SJonathan Anderson 58da749672SJonathan Anderson #define SYSCALL_FAIL(syscall, message) \ 59da749672SJonathan Anderson FAIL("%s:\t%s (rights 0x%jx)", #syscall, message, rights) 60da749672SJonathan Anderson 61da749672SJonathan Anderson /* 62da749672SJonathan Anderson * Ensure that, if the capability had enough rights for the system call to 63da749672SJonathan Anderson * pass, then it did. Otherwise, ensure that the errno is ENOTCAPABLE; 64da749672SJonathan Anderson * capability restrictions should kick in before any other error logic. 65da749672SJonathan Anderson */ 66da749672SJonathan Anderson #define CHECK_RESULT(syscall, rights_needed, succeeded) do { \ 67da749672SJonathan Anderson if ((rights & (rights_needed)) == (rights_needed)) { \ 68f2908898SPawel Jakub Dawidek if (succeeded) { \ 69f2908898SPawel Jakub Dawidek if (success == -1) \ 70f2908898SPawel Jakub Dawidek success = PASSED; \ 71da749672SJonathan Anderson } else { \ 72f2908898SPawel Jakub Dawidek SYSCALL_FAIL(syscall, "failed"); \ 73f2908898SPawel Jakub Dawidek } \ 74f2908898SPawel Jakub Dawidek } else { \ 75f2908898SPawel Jakub Dawidek if (succeeded) { \ 76da749672SJonathan Anderson FAILX("%s:\tsucceeded when it shouldn't have" \ 77f2908898SPawel Jakub Dawidek " (rights 0x%jx)", #syscall, \ 78f2908898SPawel Jakub Dawidek (uintmax_t)rights); \ 79f2908898SPawel Jakub Dawidek } else if (errno != ENOTCAPABLE) { \ 80da749672SJonathan Anderson SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \ 81da749672SJonathan Anderson } \ 82f2908898SPawel Jakub Dawidek } \ 83d6f72489SJonathan Anderson errno = 0; \ 84da749672SJonathan Anderson } while (0) 85da749672SJonathan Anderson 86da749672SJonathan Anderson /* 87da749672SJonathan Anderson * As above, but for the special mmap() case: unmap after successful mmap(). 88da749672SJonathan Anderson */ 89da749672SJonathan Anderson #define CHECK_MMAP_RESULT(rights_needed) do { \ 90da749672SJonathan Anderson if ((rights & (rights_needed)) == (rights_needed)) { \ 91da749672SJonathan Anderson if (p == MAP_FAILED) \ 92da749672SJonathan Anderson SYSCALL_FAIL(mmap, "failed"); \ 93f2908898SPawel Jakub Dawidek else { \ 94da749672SJonathan Anderson (void)munmap(p, getpagesize()); \ 95f2908898SPawel Jakub Dawidek if (success == -1) \ 96f2908898SPawel Jakub Dawidek success = PASSED; \ 97f2908898SPawel Jakub Dawidek } \ 98da749672SJonathan Anderson } else { \ 99da749672SJonathan Anderson if (p != MAP_FAILED) { \ 100da749672SJonathan Anderson FAILX("%s:\tsucceeded when it shouldn't have" \ 101da749672SJonathan Anderson " (rights 0x%jx)", "mmap", rights); \ 102da749672SJonathan Anderson (void)munmap(p, getpagesize()); \ 103da749672SJonathan Anderson } else if (errno != ENOTCAPABLE) \ 104da749672SJonathan Anderson SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE"); \ 105da749672SJonathan Anderson } \ 106d6f72489SJonathan Anderson errno = 0; \ 107da749672SJonathan Anderson } while (0) 108da749672SJonathan Anderson 109da749672SJonathan Anderson /* 110da749672SJonathan Anderson * Given a file descriptor, create a capability with specific rights and 111da749672SJonathan Anderson * make sure only those rights work. 112da749672SJonathan Anderson */ 113da749672SJonathan Anderson static int 114f2908898SPawel Jakub Dawidek try_file_ops(int filefd, int dirfd, cap_rights_t rights) 115da749672SJonathan Anderson { 116da749672SJonathan Anderson struct stat sb; 117da749672SJonathan Anderson struct statfs sf; 118f2908898SPawel Jakub Dawidek cap_rights_t erights; 119f2908898SPawel Jakub Dawidek int fd_cap, fd_capcap, dfd_cap; 120da749672SJonathan Anderson ssize_t ssize, ssize2; 121da749672SJonathan Anderson off_t off; 122da749672SJonathan Anderson void *p; 123da749672SJonathan Anderson char ch; 124b7f2d66aSJonathan Anderson int ret, is_nfs; 125d6f72489SJonathan Anderson struct pollfd pollfd; 126f2908898SPawel Jakub Dawidek int success = -1; 127da749672SJonathan Anderson 128f2908898SPawel Jakub Dawidek REQUIRE(fstatfs(filefd, &sf)); 129f2908898SPawel Jakub Dawidek is_nfs = (strcmp("nfs", sf.f_fstypename) == 0); 130b7f2d66aSJonathan Anderson 131f2908898SPawel Jakub Dawidek REQUIRE(fd_cap = cap_new(filefd, rights)); 132f2908898SPawel Jakub Dawidek CHECK(cap_getrights(fd_cap, &erights) == 0); 133f2908898SPawel Jakub Dawidek CHECK(rights == erights); 134da749672SJonathan Anderson REQUIRE(fd_capcap = cap_new(fd_cap, rights)); 135f2908898SPawel Jakub Dawidek CHECK(cap_getrights(fd_capcap, &erights) == 0); 136f2908898SPawel Jakub Dawidek CHECK(rights == erights); 137da749672SJonathan Anderson CHECK(fd_capcap != fd_cap); 138f2908898SPawel Jakub Dawidek REQUIRE(dfd_cap = cap_new(dirfd, rights)); 139f2908898SPawel Jakub Dawidek CHECK(cap_getrights(dfd_cap, &erights) == 0); 140f2908898SPawel Jakub Dawidek CHECK(rights == erights); 141d6f72489SJonathan Anderson 142da749672SJonathan Anderson ssize = read(fd_cap, &ch, sizeof(ch)); 143f2908898SPawel Jakub Dawidek CHECK_RESULT(read, CAP_READ, ssize >= 0); 144da749672SJonathan Anderson 145da749672SJonathan Anderson ssize = write(fd_cap, &ch, sizeof(ch)); 146f2908898SPawel Jakub Dawidek CHECK_RESULT(write, CAP_WRITE, ssize >= 0); 147da749672SJonathan Anderson 148da749672SJonathan Anderson off = lseek(fd_cap, 0, SEEK_SET); 149da749672SJonathan Anderson CHECK_RESULT(lseek, CAP_SEEK, off >= 0); 150da749672SJonathan Anderson 151f2908898SPawel Jakub Dawidek ssize = pread(fd_cap, &ch, sizeof(ch), 0); 152f2908898SPawel Jakub Dawidek ssize2 = pread(fd_cap, &ch, sizeof(ch), 0); 153f2908898SPawel Jakub Dawidek CHECK_RESULT(pread, CAP_PREAD, ssize >= 0); 154f2908898SPawel Jakub Dawidek CHECK(ssize == ssize2); 155f2908898SPawel Jakub Dawidek 156f2908898SPawel Jakub Dawidek ssize = pwrite(fd_cap, &ch, sizeof(ch), 0); 157f2908898SPawel Jakub Dawidek CHECK_RESULT(pwrite, CAP_PWRITE, ssize >= 0); 158f2908898SPawel Jakub Dawidek 159f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, fd_cap, 0); 160f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP); 161f2908898SPawel Jakub Dawidek 162f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0); 163f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_R); 164f2908898SPawel Jakub Dawidek 165f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0); 166f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_W); 167f2908898SPawel Jakub Dawidek 168f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0); 169f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_X); 170f2908898SPawel Jakub Dawidek 171f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, 172f2908898SPawel Jakub Dawidek fd_cap, 0); 173f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_RW); 174f2908898SPawel Jakub Dawidek 175f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED, 176f2908898SPawel Jakub Dawidek fd_cap, 0); 177f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_RX); 178f2908898SPawel Jakub Dawidek 179f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED, 180f2908898SPawel Jakub Dawidek fd_cap, 0); 181f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_WX); 182f2908898SPawel Jakub Dawidek 183f2908898SPawel Jakub Dawidek p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, 184f2908898SPawel Jakub Dawidek MAP_SHARED, fd_cap, 0); 185f2908898SPawel Jakub Dawidek CHECK_MMAP_RESULT(CAP_MMAP_RWX); 186f2908898SPawel Jakub Dawidek 187f2908898SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600); 188f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_CREATE | O_RDONLY), 189f2908898SPawel Jakub Dawidek CAP_CREATE | CAP_READ | CAP_LOOKUP, ret >= 0); 190f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 191f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0); 192b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY | O_APPEND, 193b48fdae1SPawel Jakub Dawidek 0600); 194b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_CREATE | O_WRONLY | O_APPEND), 195f2908898SPawel Jakub Dawidek CAP_CREATE | CAP_WRITE | CAP_LOOKUP, ret >= 0); 196f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 197f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0); 198b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR | O_APPEND, 0600); 199b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_CREATE | O_RDWR | O_APPEND), 200f2908898SPawel Jakub Dawidek CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0); 201f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 202f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0); 203f2908898SPawel Jakub Dawidek 204f2908898SPawel Jakub Dawidek ret = fsync(fd_cap); 205f2908898SPawel Jakub Dawidek CHECK_RESULT(fsync, CAP_FSYNC, ret == 0); 206f2908898SPawel Jakub Dawidek 207f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_fsync", O_CREAT, 0600); 208f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 209f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 210ac978022SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY); 211f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_FSYNC | O_RDONLY), 212f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0); 213f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 214b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY | O_APPEND); 215b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_FSYNC | O_WRONLY | O_APPEND), 216f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0); 217f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 218b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR | O_APPEND); 219b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_FSYNC | O_RDWR | O_APPEND), 220f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0); 221f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 222ac978022SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY); 223f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_SYNC | O_RDONLY), 224f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0); 225f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 226b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY | O_APPEND); 227b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_SYNC | O_WRONLY | O_APPEND), 228f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0); 229f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 230b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR | O_APPEND); 231b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_SYNC | O_RDWR | O_APPEND), 232f2908898SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0); 233f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 234f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0); 235f2908898SPawel Jakub Dawidek 236f2908898SPawel Jakub Dawidek ret = ftruncate(fd_cap, 0); 237f2908898SPawel Jakub Dawidek CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0); 238f2908898SPawel Jakub Dawidek 239f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_ftruncate", O_CREAT, 0600); 240f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 241f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 242f2908898SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY); 243f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_TRUNC | O_RDONLY), 244f2908898SPawel Jakub Dawidek CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP, ret >= 0); 245f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 246f2908898SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY); 247f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_TRUNC | O_WRONLY), 248f2908898SPawel Jakub Dawidek CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP, ret >= 0); 249f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 250f2908898SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR); 251f2908898SPawel Jakub Dawidek CHECK_RESULT(openat(O_TRUNC | O_RDWR), 252f2908898SPawel Jakub Dawidek CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0); 253f2908898SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 254f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_ftruncate", 0) == 0); 255f2908898SPawel Jakub Dawidek 256b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600); 257b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_CREATE | O_WRONLY), 258b48fdae1SPawel Jakub Dawidek CAP_CREATE | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0); 259b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 260b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0); 261b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600); 262b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_CREATE | O_RDWR), 263b48fdae1SPawel Jakub Dawidek CAP_CREATE | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, 264b48fdae1SPawel Jakub Dawidek ret >= 0); 265b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 266b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0); 267b48fdae1SPawel Jakub Dawidek 268b48fdae1SPawel Jakub Dawidek ret = openat(dirfd, "cap_fsync", O_CREAT, 0600); 269b48fdae1SPawel Jakub Dawidek CHECK(ret >= 0); 270b48fdae1SPawel Jakub Dawidek CHECK(close(ret) == 0); 271b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY); 272b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_FSYNC | O_WRONLY), 273b48fdae1SPawel Jakub Dawidek CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0); 274b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 275b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR); 276b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_FSYNC | O_RDWR), 277b48fdae1SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0); 278b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 279b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY); 280b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_SYNC | O_WRONLY), 281b48fdae1SPawel Jakub Dawidek CAP_FSYNC | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0); 282b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 283b48fdae1SPawel Jakub Dawidek ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR); 284b48fdae1SPawel Jakub Dawidek CHECK_RESULT(openat(O_SYNC | O_RDWR), 285b48fdae1SPawel Jakub Dawidek CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP, ret >= 0); 286b48fdae1SPawel Jakub Dawidek CHECK(ret == -1 || close(ret) == 0); 287b48fdae1SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0); 288b48fdae1SPawel Jakub Dawidek 289b7f2d66aSJonathan Anderson /* 290b7f2d66aSJonathan Anderson * Note: this is not expected to work over NFS. 291b7f2d66aSJonathan Anderson */ 292da749672SJonathan Anderson ret = fchflags(fd_cap, UF_NODUMP); 293b7f2d66aSJonathan Anderson CHECK_RESULT(fchflags, CAP_FCHFLAGS, 294f2908898SPawel Jakub Dawidek ret == 0 || (is_nfs && errno == EOPNOTSUPP)); 295da749672SJonathan Anderson 296ff964674SPawel Jakub Dawidek ret = openat(dirfd, "cap_chflagsat", O_CREAT, 0600); 297f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 298f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 299ff964674SPawel Jakub Dawidek ret = chflagsat(dfd_cap, "cap_chflagsat", UF_NODUMP, 0); 300ff964674SPawel Jakub Dawidek CHECK_RESULT(chflagsat, CAP_CHFLAGSAT | CAP_LOOKUP, ret == 0); 301ff964674SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_chflagsat", 0) == 0); 302da749672SJonathan Anderson 303da749672SJonathan Anderson ret = fchown(fd_cap, -1, -1); 304da749672SJonathan Anderson CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0); 305da749672SJonathan Anderson 306f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_fchownat", O_CREAT, 0600); 307f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 308f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 309f2908898SPawel Jakub Dawidek ret = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0); 310f2908898SPawel Jakub Dawidek CHECK_RESULT(fchownat, CAP_FCHOWN | CAP_LOOKUP, ret == 0); 311f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_fchownat", 0) == 0); 312f2908898SPawel Jakub Dawidek 313da749672SJonathan Anderson ret = fchmod(fd_cap, 0644); 314da749672SJonathan Anderson CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0); 315da749672SJonathan Anderson 316f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_fchmodat", O_CREAT, 0600); 317f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 318f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 319f2908898SPawel Jakub Dawidek ret = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0); 320f2908898SPawel Jakub Dawidek CHECK_RESULT(fchmodat, CAP_FCHMOD | CAP_LOOKUP, ret == 0); 321f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_fchmodat", 0) == 0); 322f2908898SPawel Jakub Dawidek 323f2908898SPawel Jakub Dawidek ret = fcntl(fd_cap, F_GETFL); 324f2908898SPawel Jakub Dawidek CHECK_RESULT(fcntl(F_GETFL), CAP_FCNTL, ret >= 0); 325f2908898SPawel Jakub Dawidek ret = fcntl(fd_cap, F_SETFL, ret); 326f2908898SPawel Jakub Dawidek CHECK_RESULT(fcntl(F_SETFL), CAP_FCNTL, ret == 0); 327f2908898SPawel Jakub Dawidek 328da749672SJonathan Anderson /* XXX flock */ 329da749672SJonathan Anderson 330f2908898SPawel Jakub Dawidek ret = fstat(fd_cap, &sb); 331f2908898SPawel Jakub Dawidek CHECK_RESULT(fstat, CAP_FSTAT, ret == 0); 332f2908898SPawel Jakub Dawidek 333f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_fstatat", O_CREAT, 0600); 334f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 335f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 336f2908898SPawel Jakub Dawidek ret = fstatat(dfd_cap, "cap_fstatat", &sb, 0); 337f2908898SPawel Jakub Dawidek CHECK_RESULT(fstatat, CAP_FSTAT | CAP_LOOKUP, ret == 0); 338f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_fstatat", 0) == 0); 339da749672SJonathan Anderson 340da749672SJonathan Anderson ret = fstatfs(fd_cap, &sf); 341da749672SJonathan Anderson CHECK_RESULT(fstatfs, CAP_FSTATFS, ret == 0); 342da749672SJonathan Anderson 343da749672SJonathan Anderson ret = fpathconf(fd_cap, _PC_NAME_MAX); 344da749672SJonathan Anderson CHECK_RESULT(fpathconf, CAP_FPATHCONF, ret >= 0); 345da749672SJonathan Anderson 346da749672SJonathan Anderson ret = futimes(fd_cap, NULL); 347da749672SJonathan Anderson CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0); 348da749672SJonathan Anderson 349f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_futimesat", O_CREAT, 0600); 350f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 351f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 352f2908898SPawel Jakub Dawidek ret = futimesat(dfd_cap, "cap_futimesat", NULL); 353f2908898SPawel Jakub Dawidek CHECK_RESULT(futimesat, CAP_FUTIMES | CAP_LOOKUP, ret == 0); 354f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_futimesat", 0) == 0); 355f2908898SPawel Jakub Dawidek 356f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_linkat_src", O_CREAT, 0600); 357f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 358f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 359f2908898SPawel Jakub Dawidek ret = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0); 360f2908898SPawel Jakub Dawidek CHECK_RESULT(linkat, CAP_LINKAT | CAP_LOOKUP, ret == 0); 361f2908898SPawel Jakub Dawidek CHECK(unlinkat(dirfd, "cap_linkat_src", 0) == 0); 362f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_linkat_dst", 0) == 0); 363f2908898SPawel Jakub Dawidek 364f2908898SPawel Jakub Dawidek ret = mkdirat(dfd_cap, "cap_mkdirat", 0700); 365f2908898SPawel Jakub Dawidek CHECK_RESULT(mkdirat, CAP_MKDIRAT | CAP_LOOKUP, ret == 0); 366f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR) == 0); 367f2908898SPawel Jakub Dawidek 368f2908898SPawel Jakub Dawidek ret = mkfifoat(dfd_cap, "cap_mkfifoat", 0600); 369f2908898SPawel Jakub Dawidek CHECK_RESULT(mkfifoat, CAP_MKFIFOAT | CAP_LOOKUP, ret == 0); 370f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_mkfifoat", 0) == 0); 371f2908898SPawel Jakub Dawidek 372f2908898SPawel Jakub Dawidek ret = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0); 373f2908898SPawel Jakub Dawidek CHECK_RESULT(mknodat, CAP_MKNODAT | CAP_LOOKUP, ret == 0); 374f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_mknodat", 0) == 0); 375f2908898SPawel Jakub Dawidek 376f2908898SPawel Jakub Dawidek /* TODO: renameat(2) */ 377f2908898SPawel Jakub Dawidek 378f2908898SPawel Jakub Dawidek ret = symlinkat("test", dfd_cap, "cap_symlinkat"); 379f2908898SPawel Jakub Dawidek CHECK_RESULT(symlinkat, CAP_SYMLINKAT | CAP_LOOKUP, ret == 0); 380f2908898SPawel Jakub Dawidek CHECK(ret == -1 || unlinkat(dirfd, "cap_symlinkat", 0) == 0); 381f2908898SPawel Jakub Dawidek 382f2908898SPawel Jakub Dawidek ret = openat(dirfd, "cap_unlinkat", O_CREAT, 0600); 383f2908898SPawel Jakub Dawidek CHECK(ret >= 0); 384f2908898SPawel Jakub Dawidek CHECK(close(ret) == 0); 385f2908898SPawel Jakub Dawidek ret = unlinkat(dfd_cap, "cap_unlinkat", 0); 386f2908898SPawel Jakub Dawidek CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0); 387f2908898SPawel Jakub Dawidek CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", 0) == 0); 388f2908898SPawel Jakub Dawidek ret = mkdirat(dirfd, "cap_unlinkat", 0700); 389f2908898SPawel Jakub Dawidek CHECK(ret == 0); 390f2908898SPawel Jakub Dawidek ret = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR); 391f2908898SPawel Jakub Dawidek CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0); 392f2908898SPawel Jakub Dawidek CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR) == 0); 393f2908898SPawel Jakub Dawidek 394f2908898SPawel Jakub Dawidek pollfd.fd = fd_cap; 395f2908898SPawel Jakub Dawidek pollfd.events = POLLIN | POLLERR | POLLHUP; 396f2908898SPawel Jakub Dawidek pollfd.revents = 0; 397f2908898SPawel Jakub Dawidek 398d6f72489SJonathan Anderson ret = poll(&pollfd, 1, 0); 399d6f72489SJonathan Anderson if (rights & CAP_POLL_EVENT) 400d6f72489SJonathan Anderson CHECK((pollfd.revents & POLLNVAL) == 0); 401d6f72489SJonathan Anderson else 402d6f72489SJonathan Anderson CHECK((pollfd.revents & POLLNVAL) != 0); 403d6f72489SJonathan Anderson 404d6f72489SJonathan Anderson /* XXX: select, kqueue */ 405da749672SJonathan Anderson 406da749672SJonathan Anderson close(fd_cap); 407f2908898SPawel Jakub Dawidek close(fd_capcap); 408f2908898SPawel Jakub Dawidek 409f2908898SPawel Jakub Dawidek if (success == -1) { 410f2908898SPawel Jakub Dawidek fprintf(stderr, "No tests for rights 0x%jx.\n", 411f2908898SPawel Jakub Dawidek (uintmax_t)rights); 412f2908898SPawel Jakub Dawidek success = FAILED; 413f2908898SPawel Jakub Dawidek } 414da749672SJonathan Anderson return (success); 415da749672SJonathan Anderson } 416da749672SJonathan Anderson 417f2908898SPawel Jakub Dawidek #define TRY(rights) \ 418da749672SJonathan Anderson do { \ 419da749672SJonathan Anderson if (success == PASSED) \ 420f2908898SPawel Jakub Dawidek success = try_file_ops(filefd, dirfd, (rights)); \ 421da749672SJonathan Anderson else \ 422da749672SJonathan Anderson /* We've already failed, but try the test anyway. */ \ 423f2908898SPawel Jakub Dawidek try_file_ops(filefd, dirfd, (rights)); \ 424da749672SJonathan Anderson } while (0) 425da749672SJonathan Anderson 426f2908898SPawel Jakub Dawidek #define KEEP_ERRNO(...) do { \ 427f2908898SPawel Jakub Dawidek int _saved_errno = errno; \ 428f2908898SPawel Jakub Dawidek __VA_ARGS__; \ 429f2908898SPawel Jakub Dawidek errno = _saved_errno; \ 430f2908898SPawel Jakub Dawidek } while (0); 431f2908898SPawel Jakub Dawidek 432da749672SJonathan Anderson int 433da749672SJonathan Anderson test_capabilities(void) 434da749672SJonathan Anderson { 435f2908898SPawel Jakub Dawidek int filefd, dirfd, tmpfd; 436da749672SJonathan Anderson int success = PASSED; 437f2908898SPawel Jakub Dawidek char file[] = "/tmp/cap_test.XXXXXXXXXX"; 438f2908898SPawel Jakub Dawidek char dir[] = "/tmp/cap_test.XXXXXXXXXX"; 439da749672SJonathan Anderson 440f2908898SPawel Jakub Dawidek filefd = mkstemp(file); 441f2908898SPawel Jakub Dawidek if (filefd < 0) 442f2908898SPawel Jakub Dawidek err(-1, "mkstemp"); 443f2908898SPawel Jakub Dawidek if (mkdtemp(dir) == NULL) { 444f2908898SPawel Jakub Dawidek KEEP_ERRNO(unlink(file)); 445f2908898SPawel Jakub Dawidek err(-1, "mkdtemp"); 446f2908898SPawel Jakub Dawidek } 447f2908898SPawel Jakub Dawidek dirfd = open(dir, O_RDONLY | O_DIRECTORY); 448f2908898SPawel Jakub Dawidek if (dirfd == -1) { 449f2908898SPawel Jakub Dawidek KEEP_ERRNO(unlink(file)); 450f2908898SPawel Jakub Dawidek KEEP_ERRNO(rmdir(dir)); 451da749672SJonathan Anderson err(-1, "open"); 452f2908898SPawel Jakub Dawidek } 453f2908898SPawel Jakub Dawidek tmpfd = open("/tmp", O_RDONLY | O_DIRECTORY); 454f2908898SPawel Jakub Dawidek if (tmpfd == -1) { 455f2908898SPawel Jakub Dawidek KEEP_ERRNO(unlink(file)); 456f2908898SPawel Jakub Dawidek KEEP_ERRNO(rmdir(dir)); 457f2908898SPawel Jakub Dawidek err(-1, "open"); 458f2908898SPawel Jakub Dawidek } 459da749672SJonathan Anderson 460f2908898SPawel Jakub Dawidek if (cap_enter() == -1) { 461f2908898SPawel Jakub Dawidek KEEP_ERRNO(unlink(file)); 462f2908898SPawel Jakub Dawidek KEEP_ERRNO(rmdir(dir)); 463da749672SJonathan Anderson err(-1, "cap_enter"); 464f2908898SPawel Jakub Dawidek } 465da749672SJonathan Anderson 466f2908898SPawel Jakub Dawidek TRY(CAP_READ); 467f2908898SPawel Jakub Dawidek TRY(CAP_WRITE); 468f2908898SPawel Jakub Dawidek TRY(CAP_SEEK); 469f2908898SPawel Jakub Dawidek TRY(CAP_PREAD); 470f2908898SPawel Jakub Dawidek TRY(CAP_PWRITE); 471f2908898SPawel Jakub Dawidek TRY(CAP_READ | CAP_WRITE); 472f2908898SPawel Jakub Dawidek TRY(CAP_PREAD | CAP_PWRITE); 473f2908898SPawel Jakub Dawidek TRY(CAP_MMAP); 474f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_R); 475f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_W); 476f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_X); 477f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_RW); 478f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_RX); 479f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_WX); 480f2908898SPawel Jakub Dawidek TRY(CAP_MMAP_RWX); 481f2908898SPawel Jakub Dawidek TRY(CAP_CREATE | CAP_READ | CAP_LOOKUP); 482f2908898SPawel Jakub Dawidek TRY(CAP_CREATE | CAP_WRITE | CAP_LOOKUP); 483f2908898SPawel Jakub Dawidek TRY(CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP); 484f2908898SPawel Jakub Dawidek #ifdef TODO 485f2908898SPawel Jakub Dawidek TRY(CAP_FEXECVE); 486f2908898SPawel Jakub Dawidek #endif 487f2908898SPawel Jakub Dawidek TRY(CAP_FSYNC); 488f2908898SPawel Jakub Dawidek TRY(CAP_FSYNC | CAP_READ | CAP_LOOKUP); 489f2908898SPawel Jakub Dawidek TRY(CAP_FSYNC | CAP_WRITE | CAP_LOOKUP); 490f2908898SPawel Jakub Dawidek TRY(CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP); 491f2908898SPawel Jakub Dawidek TRY(CAP_FTRUNCATE); 492f2908898SPawel Jakub Dawidek TRY(CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP); 493f2908898SPawel Jakub Dawidek TRY(CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP); 494f2908898SPawel Jakub Dawidek TRY(CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP); 495f2908898SPawel Jakub Dawidek #ifdef TODO 496f2908898SPawel Jakub Dawidek TRY(CAP_FCHDIR); 497f2908898SPawel Jakub Dawidek #endif 498f2908898SPawel Jakub Dawidek TRY(CAP_FCHFLAGS); 499f2908898SPawel Jakub Dawidek TRY(CAP_FCHOWN); 500f2908898SPawel Jakub Dawidek TRY(CAP_FCHOWN | CAP_LOOKUP); 501f2908898SPawel Jakub Dawidek TRY(CAP_FCHMOD | CAP_LOOKUP); 502f2908898SPawel Jakub Dawidek TRY(CAP_FCNTL); 503f2908898SPawel Jakub Dawidek #ifdef TODO 504f2908898SPawel Jakub Dawidek TRY(CAP_FLOCK); 505f2908898SPawel Jakub Dawidek #endif 506f2908898SPawel Jakub Dawidek TRY(CAP_FPATHCONF); 507f2908898SPawel Jakub Dawidek #ifdef TODO 508f2908898SPawel Jakub Dawidek TRY(CAP_FSCK); 509f2908898SPawel Jakub Dawidek #endif 510f2908898SPawel Jakub Dawidek TRY(CAP_FSTAT | CAP_LOOKUP); 511f2908898SPawel Jakub Dawidek TRY(CAP_FSTATFS); 512f2908898SPawel Jakub Dawidek TRY(CAP_FUTIMES | CAP_LOOKUP); 513f2908898SPawel Jakub Dawidek TRY(CAP_LINKAT | CAP_LOOKUP); 514f2908898SPawel Jakub Dawidek TRY(CAP_MKDIRAT | CAP_LOOKUP); 515f2908898SPawel Jakub Dawidek TRY(CAP_MKFIFOAT | CAP_LOOKUP); 516f2908898SPawel Jakub Dawidek TRY(CAP_MKNODAT | CAP_LOOKUP); 517f2908898SPawel Jakub Dawidek TRY(CAP_SYMLINKAT | CAP_LOOKUP); 518f2908898SPawel Jakub Dawidek TRY(CAP_UNLINKAT | CAP_LOOKUP); 519f2908898SPawel Jakub Dawidek /* Rename needs CAP_RENAMEAT on source directory and CAP_LINKAT on destination directory. */ 520f2908898SPawel Jakub Dawidek TRY(CAP_RENAMEAT | CAP_UNLINKAT | CAP_LOOKUP); 521f2908898SPawel Jakub Dawidek #ifdef TODO 522f2908898SPawel Jakub Dawidek TRY(CAP_LOOKUP); 523f2908898SPawel Jakub Dawidek TRY(CAP_EXTATTR_DELETE); 524f2908898SPawel Jakub Dawidek TRY(CAP_EXTATTR_GET); 525f2908898SPawel Jakub Dawidek TRY(CAP_EXTATTR_LIST); 526f2908898SPawel Jakub Dawidek TRY(CAP_EXTATTR_SET); 527f2908898SPawel Jakub Dawidek TRY(CAP_ACL_CHECK); 528f2908898SPawel Jakub Dawidek TRY(CAP_ACL_DELETE); 529f2908898SPawel Jakub Dawidek TRY(CAP_ACL_GET); 530f2908898SPawel Jakub Dawidek TRY(CAP_ACL_SET); 531f2908898SPawel Jakub Dawidek TRY(CAP_ACCEPT); 532f2908898SPawel Jakub Dawidek TRY(CAP_BIND); 533f2908898SPawel Jakub Dawidek TRY(CAP_CONNECT); 534f2908898SPawel Jakub Dawidek TRY(CAP_GETPEERNAME); 535f2908898SPawel Jakub Dawidek TRY(CAP_GETSOCKNAME); 536f2908898SPawel Jakub Dawidek TRY(CAP_GETSOCKOPT); 537f2908898SPawel Jakub Dawidek TRY(CAP_LISTEN); 538f2908898SPawel Jakub Dawidek TRY(CAP_PEELOFF); 539f2908898SPawel Jakub Dawidek TRY(CAP_RECV); 540f2908898SPawel Jakub Dawidek TRY(CAP_SEND); 541f2908898SPawel Jakub Dawidek TRY(CAP_SETSOCKOPT); 542f2908898SPawel Jakub Dawidek TRY(CAP_SHUTDOWN); 543f2908898SPawel Jakub Dawidek TRY(CAP_MAC_GET); 544f2908898SPawel Jakub Dawidek TRY(CAP_MAC_SET); 545f2908898SPawel Jakub Dawidek TRY(CAP_SEM_GETVALUE); 546f2908898SPawel Jakub Dawidek TRY(CAP_SEM_POST); 547f2908898SPawel Jakub Dawidek TRY(CAP_SEM_WAIT); 548f2908898SPawel Jakub Dawidek TRY(CAP_POST_EVENT); 549f2908898SPawel Jakub Dawidek TRY(CAP_POLL_EVENT); 550f2908898SPawel Jakub Dawidek TRY(CAP_IOCTL); 551f2908898SPawel Jakub Dawidek TRY(CAP_TTYHOOK); 552f2908898SPawel Jakub Dawidek TRY(CAP_PDGETPID); 553f2908898SPawel Jakub Dawidek TRY(CAP_PDWAIT); 554f2908898SPawel Jakub Dawidek TRY(CAP_PDKILL); 555f2908898SPawel Jakub Dawidek #endif 556da749672SJonathan Anderson 557f2908898SPawel Jakub Dawidek (void)unlinkat(tmpfd, file + strlen("/tmp/"), 0); 558f2908898SPawel Jakub Dawidek (void)unlinkat(tmpfd, dir + strlen("/tmp/"), AT_REMOVEDIR); 559da749672SJonathan Anderson 560da749672SJonathan Anderson return (success); 561da749672SJonathan Anderson } 562