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.
TEST(Ioctl,Basic)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
TEST(Ioctl,SubRightNormalFD)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
TEST(Ioctl,PreserveSubRights)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
TEST(Ioctl,SubRights)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
TEST(Ioctl,TooManySubRights)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
TEST(Ioctl,ManySubRights)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