1 // Test that ioctl works in capability mode. 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <sys/socket.h> 5 #include <fcntl.h> 6 #include <sys/ioctl.h> 7 8 #include "capsicum.h" 9 #include "capsicum-test.h" 10 11 // Ensure that ioctl() works consistently for both regular file descriptors and 12 // capability-wrapped ones. 13 TEST(Ioctl, Basic) { 14 cap_rights_t rights_ioctl; 15 cap_rights_init(&rights_ioctl, CAP_IOCTL); 16 cap_rights_t rights_many; 17 cap_rights_init(&rights_many, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_FSTAT, CAP_FSYNC); 18 19 int fd = open("/etc/passwd", O_RDONLY); 20 EXPECT_OK(fd); 21 int fd_no = dup(fd); 22 EXPECT_OK(fd_no); 23 EXPECT_OK(cap_rights_limit(fd, &rights_ioctl)); 24 EXPECT_OK(cap_rights_limit(fd_no, &rights_many)); 25 26 // Check that CAP_IOCTL is required. 27 int bytes; 28 EXPECT_OK(ioctl(fd, FIONREAD, &bytes)); 29 EXPECT_NOTCAPABLE(ioctl(fd_no, FIONREAD, &bytes)); 30 31 int one = 1; 32 EXPECT_OK(ioctl(fd, FIOCLEX, &one)); 33 EXPECT_NOTCAPABLE(ioctl(fd_no, FIOCLEX, &one)); 34 35 close(fd); 36 close(fd_no); 37 } 38 39 #ifdef HAVE_CAP_IOCTLS_LIMIT 40 TEST(Ioctl, SubRightNormalFD) { 41 int fd = open("/etc/passwd", O_RDONLY); 42 EXPECT_OK(fd); 43 44 // Restrict the ioctl(2) subrights of a normal FD. 45 cap_ioctl_t ioctl_nread = FIONREAD; 46 EXPECT_OK(cap_ioctls_limit(fd, &ioctl_nread, 1)); 47 int bytes; 48 EXPECT_OK(ioctl(fd, FIONREAD, &bytes)); 49 int one = 1; 50 EXPECT_NOTCAPABLE(ioctl(fd, FIOCLEX, &one)); 51 52 // Expect to have all primary rights. 53 cap_rights_t rights; 54 EXPECT_OK(cap_rights_get(fd, &rights)); 55 cap_rights_t all; 56 CAP_SET_ALL(&all); 57 EXPECT_RIGHTS_EQ(&all, &rights); 58 cap_ioctl_t ioctls[16]; 59 memset(ioctls, 0, sizeof(ioctls)); 60 ssize_t nioctls = cap_ioctls_get(fd, ioctls, 16); 61 EXPECT_OK(nioctls); 62 EXPECT_EQ(1, nioctls); 63 EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]); 64 65 // Can't widen the subrights. 66 cap_ioctl_t both_ioctls[2] = {FIONREAD, FIOCLEX}; 67 EXPECT_NOTCAPABLE(cap_ioctls_limit(fd, both_ioctls, 2)); 68 69 close(fd); 70 } 71 72 TEST(Ioctl, PreserveSubRights) { 73 int fd = open("/etc/passwd", O_RDONLY); 74 EXPECT_OK(fd); 75 cap_rights_t rights; 76 cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_IOCTL); 77 EXPECT_OK(cap_rights_limit(fd, &rights)); 78 cap_ioctl_t ioctl_nread = FIONREAD; 79 EXPECT_OK(cap_ioctls_limit(fd, &ioctl_nread, 1)); 80 81 cap_rights_t cur_rights; 82 cap_ioctl_t ioctls[16]; 83 ssize_t nioctls; 84 EXPECT_OK(cap_rights_get(fd, &cur_rights)); 85 EXPECT_RIGHTS_EQ(&rights, &cur_rights); 86 nioctls = cap_ioctls_get(fd, ioctls, 16); 87 EXPECT_OK(nioctls); 88 EXPECT_EQ(1, nioctls); 89 EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]); 90 91 // Limiting the top-level rights leaves the subrights unaffected... 92 cap_rights_clear(&rights, CAP_READ); 93 EXPECT_OK(cap_rights_limit(fd, &rights)); 94 nioctls = cap_ioctls_get(fd, ioctls, 16); 95 EXPECT_OK(nioctls); 96 EXPECT_EQ(1, nioctls); 97 EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]); 98 99 // ... until we remove CAP_IOCTL 100 cap_rights_clear(&rights, CAP_IOCTL); 101 EXPECT_OK(cap_rights_limit(fd, &rights)); 102 nioctls = cap_ioctls_get(fd, ioctls, 16); 103 EXPECT_OK(nioctls); 104 EXPECT_EQ(0, nioctls); 105 EXPECT_EQ(-1, cap_ioctls_limit(fd, &ioctl_nread, 1)); 106 107 close(fd); 108 } 109 110 TEST(Ioctl, SubRights) { 111 int fd = open("/etc/passwd", O_RDONLY); 112 EXPECT_OK(fd); 113 114 cap_ioctl_t ioctls[16]; 115 ssize_t nioctls; 116 memset(ioctls, 0, sizeof(ioctls)); 117 nioctls = cap_ioctls_get(fd, ioctls, 16); 118 EXPECT_OK(nioctls); 119 EXPECT_EQ(CAP_IOCTLS_ALL, nioctls); 120 121 cap_rights_t rights_ioctl; 122 cap_rights_init(&rights_ioctl, CAP_IOCTL); 123 EXPECT_OK(cap_rights_limit(fd, &rights_ioctl)); 124 125 nioctls = cap_ioctls_get(fd, ioctls, 16); 126 EXPECT_OK(nioctls); 127 EXPECT_EQ(CAP_IOCTLS_ALL, nioctls); 128 129 // Check operations that need CAP_IOCTL with subrights pristine => OK. 130 int bytes; 131 EXPECT_OK(ioctl(fd, FIONREAD, &bytes)); 132 int one = 1; 133 EXPECT_OK(ioctl(fd, FIOCLEX, &one)); 134 135 // Check operations that need CAP_IOCTL with all relevant subrights => OK. 136 cap_ioctl_t both_ioctls[2] = {FIONREAD, FIOCLEX}; 137 EXPECT_OK(cap_ioctls_limit(fd, both_ioctls, 2)); 138 EXPECT_OK(ioctl(fd, FIONREAD, &bytes)); 139 EXPECT_OK(ioctl(fd, FIOCLEX, &one)); 140 141 142 // Check what happens if we ask for subrights but don't have the space for them. 143 cap_ioctl_t before = 0xBBBBBBBB; 144 cap_ioctl_t one_ioctl = 0; 145 cap_ioctl_t after = 0xAAAAAAAA; 146 nioctls = cap_ioctls_get(fd, &one_ioctl, 1); 147 EXPECT_EQ(2, nioctls); 148 EXPECT_EQ(0xBBBBBBBB, before); 149 EXPECT_TRUE(one_ioctl == FIONREAD || one_ioctl == FIOCLEX); 150 EXPECT_EQ(0xAAAAAAAA, after); 151 152 // Check operations that need CAP_IOCTL with particular subrights. 153 int fd_nread = dup(fd); 154 int fd_clex = dup(fd); 155 cap_ioctl_t ioctl_nread = FIONREAD; 156 cap_ioctl_t ioctl_clex = FIOCLEX; 157 EXPECT_OK(cap_ioctls_limit(fd_nread, &ioctl_nread, 1)); 158 EXPECT_OK(cap_ioctls_limit(fd_clex, &ioctl_clex, 1)); 159 EXPECT_OK(ioctl(fd_nread, FIONREAD, &bytes)); 160 EXPECT_NOTCAPABLE(ioctl(fd_clex, FIONREAD, &bytes)); 161 EXPECT_OK(ioctl(fd_clex, FIOCLEX, &one)); 162 EXPECT_NOTCAPABLE(ioctl(fd_nread, FIOCLEX, &one)); 163 164 // Also check we can retrieve the subrights. 165 memset(ioctls, 0, sizeof(ioctls)); 166 nioctls = cap_ioctls_get(fd_nread, ioctls, 16); 167 EXPECT_OK(nioctls); 168 EXPECT_EQ(1, nioctls); 169 EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]); 170 memset(ioctls, 0, sizeof(ioctls)); 171 nioctls = cap_ioctls_get(fd_clex, ioctls, 16); 172 EXPECT_OK(nioctls); 173 EXPECT_EQ(1, nioctls); 174 EXPECT_EQ((cap_ioctl_t)FIOCLEX, ioctls[0]); 175 // And that we can't widen the subrights. 176 EXPECT_NOTCAPABLE(cap_ioctls_limit(fd_nread, both_ioctls, 2)); 177 EXPECT_NOTCAPABLE(cap_ioctls_limit(fd_clex, both_ioctls, 2)); 178 close(fd_nread); 179 close(fd_clex); 180 181 // Check operations that need CAP_IOCTL with no subrights => ENOTCAPABLE. 182 EXPECT_OK(cap_ioctls_limit(fd, NULL, 0)); 183 EXPECT_NOTCAPABLE(ioctl(fd, FIONREAD, &bytes)); 184 EXPECT_NOTCAPABLE(ioctl(fd, FIOCLEX, &one)); 185 186 close(fd); 187 } 188 189 #ifdef CAP_IOCTLS_LIMIT_MAX 190 TEST(Ioctl, TooManySubRights) { 191 int fd = open("/etc/passwd", O_RDONLY); 192 EXPECT_OK(fd); 193 194 cap_ioctl_t ioctls[CAP_IOCTLS_LIMIT_MAX + 1]; 195 for (int ii = 0; ii <= CAP_IOCTLS_LIMIT_MAX; ii++) { 196 ioctls[ii] = ii + 1; 197 } 198 199 cap_rights_t rights_ioctl; 200 cap_rights_init(&rights_ioctl, CAP_IOCTL); 201 EXPECT_OK(cap_rights_limit(fd, &rights_ioctl)); 202 203 // Can only limit to a certain number of ioctls 204 EXPECT_EQ(-1, cap_ioctls_limit(fd, ioctls, CAP_IOCTLS_LIMIT_MAX + 1)); 205 EXPECT_EQ(EINVAL, errno); 206 EXPECT_OK(cap_ioctls_limit(fd, ioctls, CAP_IOCTLS_LIMIT_MAX)); 207 208 close(fd); 209 } 210 #else 211 TEST(Ioctl, ManySubRights) { 212 int fd = open("/etc/passwd", O_RDONLY); 213 EXPECT_OK(fd); 214 215 const int nioctls = 150000; 216 cap_ioctl_t* ioctls = (cap_ioctl_t*)calloc(nioctls, sizeof(cap_ioctl_t)); 217 for (int ii = 0; ii < nioctls; ii++) { 218 ioctls[ii] = ii + 1; 219 } 220 221 cap_rights_t rights_ioctl; 222 cap_rights_init(&rights_ioctl, CAP_IOCTL); 223 EXPECT_OK(cap_rights_limit(fd, &rights_ioctl)); 224 225 EXPECT_OK(cap_ioctls_limit(fd, ioctls, nioctls)); 226 // Limit to a subset; if this takes a long time then there's an 227 // O(N^2) implementation of the ioctl list comparison. 228 EXPECT_OK(cap_ioctls_limit(fd, ioctls, nioctls - 1)); 229 230 close(fd); 231 } 232 #endif 233 234 #endif 235