• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params))
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