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