1 /*
2 * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@altlinux.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "defs.h"
29
30 typedef int32_t key_serial_t;
31
32 #include "xlat/key_spec.h"
33
34 struct keyctl_dh_params {
35 int32_t private;
36 int32_t prime;
37 int32_t base;
38 };
39
40 static void
print_keyring_serial_number(key_serial_t id)41 print_keyring_serial_number(key_serial_t id)
42 {
43 const char *str = xlookup(key_spec, (unsigned int) id);
44
45 if (str)
46 tprints(str);
47 else
48 tprintf("%d", id);
49 }
50
SYS_FUNC(add_key)51 SYS_FUNC(add_key)
52 {
53 /* type */
54 printstr(tcp, tcp->u_arg[0]);
55 /* description */
56 tprints(", ");
57 printstr(tcp, tcp->u_arg[1]);
58 /* payload */
59 tprints(", ");
60 printstrn(tcp, tcp->u_arg[2], tcp->u_arg[3]);
61 /* payload length */
62 tprintf(", %" PRI_klu ", ", tcp->u_arg[3]);
63 /* keyring serial number */
64 print_keyring_serial_number(tcp->u_arg[4]);
65
66 return RVAL_DECODED;
67 }
68
SYS_FUNC(request_key)69 SYS_FUNC(request_key)
70 {
71 /* type */
72 printstr(tcp, tcp->u_arg[0]);
73 /* description */
74 tprints(", ");
75 printstr(tcp, tcp->u_arg[1]);
76 /* callout_info */
77 tprints(", ");
78 printstr(tcp, tcp->u_arg[2]);
79 /* keyring serial number */
80 tprints(", ");
81 print_keyring_serial_number(tcp->u_arg[3]);
82
83 return RVAL_DECODED;
84 }
85
86 static void
keyctl_get_keyring_id(struct tcb * tcp,key_serial_t id,int create)87 keyctl_get_keyring_id(struct tcb *tcp, key_serial_t id, int create)
88 {
89 print_keyring_serial_number(id);
90 tprintf(", %d", create);
91 }
92
93 static void
keyctl_update_key(struct tcb * tcp,key_serial_t id,kernel_ulong_t addr,kernel_ulong_t len)94 keyctl_update_key(struct tcb *tcp, key_serial_t id, kernel_ulong_t addr,
95 kernel_ulong_t len)
96 {
97 print_keyring_serial_number(id);
98 tprints(", ");
99 printstrn(tcp, addr, len);
100 tprintf(", %llu", zero_extend_signed_to_ull(len));
101 }
102
103 static void
keyctl_handle_key_key(struct tcb * tcp,key_serial_t id1,key_serial_t id2)104 keyctl_handle_key_key(struct tcb *tcp, key_serial_t id1, key_serial_t id2)
105 {
106 print_keyring_serial_number(id1);
107 tprints(", ");
108 print_keyring_serial_number(id2);
109 }
110
111 static void
keyctl_read_key(struct tcb * tcp,key_serial_t id,kernel_ulong_t addr,kernel_ulong_t len,bool has_nul)112 keyctl_read_key(struct tcb *tcp, key_serial_t id, kernel_ulong_t addr,
113 kernel_ulong_t len, bool has_nul)
114 {
115 if (entering(tcp)) {
116 print_keyring_serial_number(id);
117 tprints(", ");
118 } else {
119 if (syserror(tcp))
120 printaddr(addr);
121 else {
122 kernel_ulong_t rval = (tcp->u_rval >= 0) &&
123 ((kernel_ulong_t) tcp->u_rval > len) ? len :
124 (kernel_ulong_t) tcp->u_rval;
125 printstr_ex(tcp, addr, rval, has_nul ?
126 QUOTE_OMIT_TRAILING_0 : 0);
127 }
128 tprintf(", %llu", zero_extend_signed_to_ull(len));
129 }
130 }
131
132 static void
keyctl_keyring_search(struct tcb * tcp,key_serial_t id1,kernel_ulong_t addr1,kernel_ulong_t addr2,key_serial_t id2)133 keyctl_keyring_search(struct tcb *tcp, key_serial_t id1, kernel_ulong_t addr1,
134 kernel_ulong_t addr2, key_serial_t id2)
135 {
136 print_keyring_serial_number(id1);
137 tprints(", ");
138 printstr(tcp, addr1);
139 tprints(", ");
140 printstr(tcp, addr2);
141 tprints(", ");
142 print_keyring_serial_number(id2);
143 }
144
145 static void
keyctl_chown_key(struct tcb * tcp,key_serial_t id,unsigned user,unsigned group)146 keyctl_chown_key(struct tcb *tcp, key_serial_t id, unsigned user,
147 unsigned group)
148 {
149 print_keyring_serial_number(id);
150 printuid(", ", user);
151 printuid(", ", group);
152 }
153
154 static void
keyctl_instantiate_key(struct tcb * tcp,key_serial_t id1,kernel_ulong_t addr,kernel_ulong_t len,key_serial_t id2)155 keyctl_instantiate_key(struct tcb *tcp, key_serial_t id1, kernel_ulong_t addr,
156 kernel_ulong_t len, key_serial_t id2)
157 {
158 print_keyring_serial_number(id1);
159 tprints(", ");
160 printstrn(tcp, addr, len);
161 tprintf(", %llu, ", zero_extend_signed_to_ull(len));
162 print_keyring_serial_number(id2);
163 }
164
165 static void
keyctl_instantiate_key_iov(struct tcb * tcp,key_serial_t id1,kernel_ulong_t addr,kernel_ulong_t len,key_serial_t id2)166 keyctl_instantiate_key_iov(struct tcb *tcp, key_serial_t id1,
167 kernel_ulong_t addr, kernel_ulong_t len,
168 key_serial_t id2)
169 {
170 print_keyring_serial_number(id1);
171 tprints(", ");
172 tprint_iov(tcp, len, addr, IOV_DECODE_STR);
173 tprintf(", %llu, ", zero_extend_signed_to_ull(len));
174 print_keyring_serial_number(id2);
175 }
176
177 static void
keyctl_negate_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,key_serial_t id2)178 keyctl_negate_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
179 key_serial_t id2)
180 {
181 print_keyring_serial_number(id1);
182 tprintf(", %u, ", timeout);
183 print_keyring_serial_number(id2);
184 }
185
186 static void
keyctl_reject_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,unsigned error,key_serial_t id2)187 keyctl_reject_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
188 unsigned error, key_serial_t id2)
189 {
190 const char *err_str = err_name(error);
191
192 print_keyring_serial_number(id1);
193 tprintf(", %u, ", timeout);
194
195 if (err_str)
196 tprintf("%s, ", err_str);
197 else
198 tprintf("%u, ", error);
199
200 print_keyring_serial_number(id2);
201 }
202
203 static void
keyctl_set_timeout(struct tcb * tcp,key_serial_t id,unsigned timeout)204 keyctl_set_timeout(struct tcb *tcp, key_serial_t id, unsigned timeout)
205 {
206 print_keyring_serial_number(id);
207 tprintf(", %u", timeout);
208 }
209
210 static void
keyctl_get_persistent(struct tcb * tcp,unsigned uid,key_serial_t id)211 keyctl_get_persistent(struct tcb *tcp, unsigned uid, key_serial_t id)
212 {
213 printuid("", uid);
214 tprints(", ");
215 print_keyring_serial_number(id);
216 }
217
218 #include "xlat/key_perms.h"
219
220 static void
keyctl_setperm_key(struct tcb * tcp,key_serial_t id,uint32_t perm)221 keyctl_setperm_key(struct tcb *tcp, key_serial_t id, uint32_t perm)
222 {
223 print_keyring_serial_number(id);
224 tprints(", ");
225 printflags(key_perms, perm, "KEY_???");
226 }
227
228 static void
print_dh_params(struct tcb * tcp,kernel_ulong_t addr)229 print_dh_params(struct tcb *tcp, kernel_ulong_t addr)
230 {
231 struct keyctl_dh_params params;
232
233 if (umove_or_printaddr(tcp, addr, ¶ms))
234 return;
235
236 tprints("{private=");
237 print_keyring_serial_number(params.private);
238 tprints(", prime=");
239 print_keyring_serial_number(params.prime);
240 tprints(", base=");
241 print_keyring_serial_number(params.base);
242 tprints("}");
243 }
244
245 static void
keyctl_dh_compute(struct tcb * tcp,kernel_ulong_t params,kernel_ulong_t buf,kernel_ulong_t len)246 keyctl_dh_compute(struct tcb *tcp, kernel_ulong_t params, kernel_ulong_t buf,
247 kernel_ulong_t len)
248 {
249 if (entering(tcp)) {
250 print_dh_params(tcp, params);
251 tprints(", ");
252 } else {
253 if (syserror(tcp)) {
254 printaddr(buf);
255 } else {
256 kernel_ulong_t rval = (tcp->u_rval >= 0) &&
257 ((kernel_ulong_t) tcp->u_rval > len) ? len :
258 (kernel_ulong_t) tcp->u_rval;
259 printstrn(tcp, buf, rval);
260 }
261 tprintf(", %llu", zero_extend_signed_to_ull(len));
262 }
263 }
264
265 #include "xlat/key_reqkeys.h"
266 #include "xlat/keyctl_commands.h"
267
SYS_FUNC(keyctl)268 SYS_FUNC(keyctl)
269 {
270 int cmd = tcp->u_arg[0];
271 kernel_ulong_t arg2 = tcp->u_arg[1];
272 kernel_ulong_t arg3 = tcp->u_arg[2];
273 kernel_ulong_t arg4 = tcp->u_arg[3];
274 kernel_ulong_t arg5 = tcp->u_arg[4];
275
276 if (entering(tcp)) {
277 printxval(keyctl_commands, cmd, "KEYCTL_???");
278
279 /*
280 * For now, KEYCTL_SESSION_TO_PARENT is the only cmd without
281 * arguments.
282 */
283 if (cmd != KEYCTL_SESSION_TO_PARENT)
284 tprints(", ");
285 }
286
287 switch (cmd) {
288 case KEYCTL_GET_KEYRING_ID:
289 keyctl_get_keyring_id(tcp, arg2, arg3);
290 break;
291
292 case KEYCTL_JOIN_SESSION_KEYRING:
293 printstr(tcp, arg2);
294 break;
295
296 case KEYCTL_UPDATE:
297 keyctl_update_key(tcp, arg2, arg3, arg4);
298 break;
299
300 case KEYCTL_REVOKE:
301 case KEYCTL_CLEAR:
302 case KEYCTL_INVALIDATE:
303 case KEYCTL_ASSUME_AUTHORITY:
304 print_keyring_serial_number(arg2);
305 break;
306
307 case KEYCTL_LINK:
308 case KEYCTL_UNLINK:
309 keyctl_handle_key_key(tcp, arg2, arg3);
310 break;
311
312 case KEYCTL_DESCRIBE:
313 case KEYCTL_READ:
314 case KEYCTL_GET_SECURITY:
315 keyctl_read_key(tcp, arg2, arg3, arg4, cmd != KEYCTL_READ);
316 return 0;
317
318 case KEYCTL_SEARCH:
319 keyctl_keyring_search(tcp, arg2, arg3, arg4, arg5);
320 break;
321
322 case KEYCTL_CHOWN:
323 keyctl_chown_key(tcp, arg2, arg3, arg4);
324 break;
325
326 case KEYCTL_SETPERM:
327 keyctl_setperm_key(tcp, arg2, arg3);
328 break;
329
330 case KEYCTL_INSTANTIATE:
331 keyctl_instantiate_key(tcp, arg2, arg3, arg4, arg5);
332 break;
333
334 case KEYCTL_NEGATE:
335 keyctl_negate_key(tcp, arg2, arg3, arg4);
336 break;
337
338 case KEYCTL_SET_REQKEY_KEYRING:
339 printxval(key_reqkeys, arg2, "KEY_REQKEY_DEFL_???");
340 break;
341
342 case KEYCTL_SET_TIMEOUT:
343 keyctl_set_timeout(tcp, arg2, arg3);
344 break;
345
346 case KEYCTL_SESSION_TO_PARENT:
347 break;
348
349 case KEYCTL_REJECT:
350 keyctl_reject_key(tcp, arg2, arg3, arg4, arg5);
351 break;
352
353 case KEYCTL_INSTANTIATE_IOV:
354 keyctl_instantiate_key_iov(tcp, arg2, arg3, arg4, arg5);
355 break;
356
357 case KEYCTL_GET_PERSISTENT:
358 keyctl_get_persistent(tcp, arg2, arg3);
359 break;
360
361 case KEYCTL_DH_COMPUTE:
362 keyctl_dh_compute(tcp, arg2, arg3, arg4);
363 return 0;
364
365 default:
366 tprintf("%#" PRI_klx ", %#" PRI_klx
367 ", %#" PRI_klx ", %#" PRI_klx,
368 arg2, arg3, arg4, arg5);
369 break;
370 }
371
372 return RVAL_DECODED;
373 }
374