xref: /src/tests/sys/capsicum/ioctl.cc (revision fba81b33aabff74ad03d5f9f9663c176cf060fa6)
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 
TEST(Ioctl,SubRightNormalFD)39 TEST(Ioctl, SubRightNormalFD) {
40   int fd = open("/etc/passwd", O_RDONLY);
41   EXPECT_OK(fd);
42 
43   // Restrict the ioctl(2) subrights of a normal FD.
44   cap_ioctl_t ioctl_nread = FIONREAD;
45   EXPECT_OK(cap_ioctls_limit(fd, &ioctl_nread, 1));
46   int bytes;
47   EXPECT_OK(ioctl(fd, FIONREAD, &bytes));
48   int one = 1;
49   EXPECT_NOTCAPABLE(ioctl(fd, FIOCLEX, &one));
50 
51   // Expect to have all primary rights.
52   cap_rights_t rights;
53   EXPECT_OK(cap_rights_get(fd, &rights));
54   cap_rights_t all;
55   CAP_ALL(&all);
56   EXPECT_RIGHTS_EQ(&all, &rights);
57   cap_ioctl_t ioctls[16];
58   memset(ioctls, 0, sizeof(ioctls));
59   ssize_t nioctls = cap_ioctls_get(fd, ioctls, 16);
60   EXPECT_OK(nioctls);
61   EXPECT_EQ(1, nioctls);
62   EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]);
63 
64   // Can't widen the subrights.
65   cap_ioctl_t both_ioctls[2] = {FIONREAD, FIOCLEX};
66   EXPECT_NOTCAPABLE(cap_ioctls_limit(fd, both_ioctls, 2));
67 
68   close(fd);
69 }
70 
TEST(Ioctl,PreserveSubRights)71 TEST(Ioctl, PreserveSubRights) {
72   int fd = open("/etc/passwd", O_RDONLY);
73   EXPECT_OK(fd);
74   cap_rights_t rights;
75   cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_SEEK, CAP_IOCTL);
76   EXPECT_OK(cap_rights_limit(fd, &rights));
77   cap_ioctl_t ioctl_nread = FIONREAD;
78   EXPECT_OK(cap_ioctls_limit(fd, &ioctl_nread, 1));
79 
80   cap_rights_t cur_rights;
81   cap_ioctl_t ioctls[16];
82   ssize_t nioctls;
83   EXPECT_OK(cap_rights_get(fd, &cur_rights));
84   EXPECT_RIGHTS_EQ(&rights, &cur_rights);
85   nioctls = cap_ioctls_get(fd, ioctls, 16);
86   EXPECT_OK(nioctls);
87   EXPECT_EQ(1, nioctls);
88   EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]);
89 
90   // Limiting the top-level rights leaves the subrights unaffected...
91   cap_rights_clear(&rights, CAP_READ);
92   EXPECT_OK(cap_rights_limit(fd, &rights));
93   nioctls = cap_ioctls_get(fd, ioctls, 16);
94   EXPECT_OK(nioctls);
95   EXPECT_EQ(1, nioctls);
96   EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]);
97 
98   // ... until we remove CAP_IOCTL
99   cap_rights_clear(&rights, CAP_IOCTL);
100   EXPECT_OK(cap_rights_limit(fd, &rights));
101   nioctls = cap_ioctls_get(fd, ioctls, 16);
102   EXPECT_OK(nioctls);
103   EXPECT_EQ(0, nioctls);
104   EXPECT_EQ(-1, cap_ioctls_limit(fd, &ioctl_nread, 1));
105 
106   close(fd);
107 }
108 
TEST(Ioctl,SubRights)109 TEST(Ioctl, SubRights) {
110   int fd = open("/etc/passwd", O_RDONLY);
111   EXPECT_OK(fd);
112 
113   cap_ioctl_t ioctls[16];
114   ssize_t nioctls;
115   memset(ioctls, 0, sizeof(ioctls));
116   nioctls = cap_ioctls_get(fd, ioctls, 16);
117   EXPECT_OK(nioctls);
118   EXPECT_EQ(CAP_IOCTLS_ALL, nioctls);
119 
120   cap_rights_t rights_ioctl;
121   cap_rights_init(&rights_ioctl, CAP_IOCTL);
122   EXPECT_OK(cap_rights_limit(fd, &rights_ioctl));
123 
124   nioctls = cap_ioctls_get(fd, ioctls, 16);
125   EXPECT_OK(nioctls);
126   EXPECT_EQ(CAP_IOCTLS_ALL, nioctls);
127 
128   // Check operations that need CAP_IOCTL with subrights pristine => OK.
129   int bytes;
130   EXPECT_OK(ioctl(fd, FIONREAD, &bytes));
131   int one = 1;
132   EXPECT_OK(ioctl(fd, FIOCLEX, &one));
133 
134   // Check operations that need CAP_IOCTL with all relevant subrights => OK.
135   cap_ioctl_t both_ioctls[2] = {FIONREAD, FIOCLEX};
136   EXPECT_OK(cap_ioctls_limit(fd, both_ioctls, 2));
137   EXPECT_OK(ioctl(fd, FIONREAD, &bytes));
138   EXPECT_OK(ioctl(fd, FIOCLEX, &one));
139 
140 
141   // Check what happens if we ask for subrights but don't have the space for them.
142   cap_ioctl_t before = 0xBBBBBBBB;
143   cap_ioctl_t one_ioctl = 0;
144   cap_ioctl_t after = 0xAAAAAAAA;
145   nioctls = cap_ioctls_get(fd, &one_ioctl, 1);
146   EXPECT_EQ(2, nioctls);
147   EXPECT_EQ(0xBBBBBBBB, before);
148   EXPECT_TRUE(one_ioctl == FIONREAD || one_ioctl == FIOCLEX);
149   EXPECT_EQ(0xAAAAAAAA, after);
150 
151   // Check operations that need CAP_IOCTL with particular subrights.
152   int fd_nread = dup(fd);
153   int fd_clex = dup(fd);
154   cap_ioctl_t ioctl_nread = FIONREAD;
155   cap_ioctl_t ioctl_clex = FIOCLEX;
156   EXPECT_OK(cap_ioctls_limit(fd_nread, &ioctl_nread, 1));
157   EXPECT_OK(cap_ioctls_limit(fd_clex, &ioctl_clex, 1));
158   EXPECT_OK(ioctl(fd_nread, FIONREAD, &bytes));
159   EXPECT_NOTCAPABLE(ioctl(fd_clex, FIONREAD, &bytes));
160   EXPECT_OK(ioctl(fd_clex, FIOCLEX, &one));
161   EXPECT_NOTCAPABLE(ioctl(fd_nread, FIOCLEX, &one));
162 
163   // Also check we can retrieve the subrights.
164   memset(ioctls, 0, sizeof(ioctls));
165   nioctls = cap_ioctls_get(fd_nread, ioctls, 16);
166   EXPECT_OK(nioctls);
167   EXPECT_EQ(1, nioctls);
168   EXPECT_EQ((cap_ioctl_t)FIONREAD, ioctls[0]);
169   memset(ioctls, 0, sizeof(ioctls));
170   nioctls = cap_ioctls_get(fd_clex, ioctls, 16);
171   EXPECT_OK(nioctls);
172   EXPECT_EQ(1, nioctls);
173   EXPECT_EQ((cap_ioctl_t)FIOCLEX, ioctls[0]);
174   // And that we can't widen the subrights.
175   EXPECT_NOTCAPABLE(cap_ioctls_limit(fd_nread, both_ioctls, 2));
176   EXPECT_NOTCAPABLE(cap_ioctls_limit(fd_clex, both_ioctls, 2));
177   close(fd_nread);
178   close(fd_clex);
179 
180   // Check operations that need CAP_IOCTL with no subrights => ENOTCAPABLE.
181   EXPECT_OK(cap_ioctls_limit(fd, NULL, 0));
182   EXPECT_NOTCAPABLE(ioctl(fd, FIONREAD, &bytes));
183   EXPECT_NOTCAPABLE(ioctl(fd, FIOCLEX, &one));
184 
185   close(fd);
186 }
187 
TEST(Ioctl,TooManySubRights)188 TEST(Ioctl, TooManySubRights) {
189   int fd = open("/etc/passwd", O_RDONLY);
190   EXPECT_OK(fd);
191 
192   cap_ioctl_t ioctls[CAP_IOCTLS_LIMIT_MAX + 1];
193   for (int ii = 0; ii <= CAP_IOCTLS_LIMIT_MAX; ii++) {
194     ioctls[ii] = ii + 1;
195   }
196 
197   cap_rights_t rights_ioctl;
198   cap_rights_init(&rights_ioctl, CAP_IOCTL);
199   EXPECT_OK(cap_rights_limit(fd, &rights_ioctl));
200 
201   // Can only limit to a certain number of ioctls
202   EXPECT_EQ(-1, cap_ioctls_limit(fd, ioctls, CAP_IOCTLS_LIMIT_MAX + 1));
203   EXPECT_EQ(EINVAL, errno);
204   EXPECT_OK(cap_ioctls_limit(fd, ioctls, CAP_IOCTLS_LIMIT_MAX));
205 
206   close(fd);
207 }
208