• 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 typedef int32_t key_serial_t;
32 
33 #include "xlat/key_spec.h"
34 
35 struct keyctl_dh_params {
36 	int32_t private;
37 	int32_t prime;
38 	int32_t base;
39 };
40 
41 static void
print_keyring_serial_number(key_serial_t id)42 print_keyring_serial_number(key_serial_t id)
43 {
44 	const char *str = xlookup(key_spec, (unsigned int) id);
45 
46 	if (str)
47 		tprints(str);
48 	else
49 		tprintf("%d", id);
50 }
51 
SYS_FUNC(add_key)52 SYS_FUNC(add_key)
53 {
54 	/* type */
55 	printstr(tcp, tcp->u_arg[0]);
56 	/* description */
57 	tprints(", ");
58 	printstr(tcp, tcp->u_arg[1]);
59 	/* payload */
60 	tprints(", ");
61 	printstrn(tcp, tcp->u_arg[2], tcp->u_arg[3]);
62 	/* payload length */
63 	tprintf(", %" PRI_klu ", ", tcp->u_arg[3]);
64 	/* keyring serial number */
65 	print_keyring_serial_number(tcp->u_arg[4]);
66 
67 	return RVAL_DECODED;
68 }
69 
SYS_FUNC(request_key)70 SYS_FUNC(request_key)
71 {
72 	/* type */
73 	printstr(tcp, tcp->u_arg[0]);
74 	/* description */
75 	tprints(", ");
76 	printstr(tcp, tcp->u_arg[1]);
77 	/* callout_info */
78 	tprints(", ");
79 	printstr(tcp, tcp->u_arg[2]);
80 	/* keyring serial number */
81 	tprints(", ");
82 	print_keyring_serial_number(tcp->u_arg[3]);
83 
84 	return RVAL_DECODED;
85 }
86 
87 static void
keyctl_get_keyring_id(struct tcb * tcp,key_serial_t id,int create)88 keyctl_get_keyring_id(struct tcb *tcp, key_serial_t id, int create)
89 {
90 	print_keyring_serial_number(id);
91 	tprintf(", %d", create);
92 }
93 
94 static void
keyctl_update_key(struct tcb * tcp,key_serial_t id,kernel_ulong_t addr,kernel_ulong_t len)95 keyctl_update_key(struct tcb *tcp, key_serial_t id, kernel_ulong_t addr,
96 		  kernel_ulong_t len)
97 {
98 	print_keyring_serial_number(id);
99 	tprints(", ");
100 	printstrn(tcp, addr, len);
101 	tprintf(", %llu", zero_extend_signed_to_ull(len));
102 }
103 
104 static void
keyctl_handle_key_key(struct tcb * tcp,key_serial_t id1,key_serial_t id2)105 keyctl_handle_key_key(struct tcb *tcp, key_serial_t id1, key_serial_t id2)
106 {
107 	print_keyring_serial_number(id1);
108 	tprints(", ");
109 	print_keyring_serial_number(id2);
110 }
111 
112 static void
keyctl_read_key(struct tcb * tcp,key_serial_t id,kernel_ulong_t addr,kernel_ulong_t len,bool has_nul)113 keyctl_read_key(struct tcb *tcp, key_serial_t id, kernel_ulong_t addr,
114 		kernel_ulong_t len, bool has_nul)
115 {
116 	if (entering(tcp)) {
117 		print_keyring_serial_number(id);
118 		tprints(", ");
119 	} else {
120 		if (syserror(tcp))
121 			printaddr(addr);
122 		else {
123 			kernel_ulong_t rval = (tcp->u_rval >= 0) &&
124 				((kernel_ulong_t) tcp->u_rval > len) ? len :
125 				(kernel_ulong_t) tcp->u_rval;
126 			printstr_ex(tcp, addr, rval, has_nul ?
127 				    QUOTE_OMIT_TRAILING_0 : 0);
128 		}
129 		tprintf(", %llu", zero_extend_signed_to_ull(len));
130 	}
131 }
132 
133 static void
keyctl_keyring_search(struct tcb * tcp,key_serial_t id1,kernel_ulong_t addr1,kernel_ulong_t addr2,key_serial_t id2)134 keyctl_keyring_search(struct tcb *tcp, key_serial_t id1, kernel_ulong_t addr1,
135 		      kernel_ulong_t addr2, key_serial_t id2)
136 {
137 	print_keyring_serial_number(id1);
138 	tprints(", ");
139 	printstr(tcp, addr1);
140 	tprints(", ");
141 	printstr(tcp, addr2);
142 	tprints(", ");
143 	print_keyring_serial_number(id2);
144 }
145 
146 static void
keyctl_chown_key(struct tcb * tcp,key_serial_t id,unsigned user,unsigned group)147 keyctl_chown_key(struct tcb *tcp, key_serial_t id, unsigned user,
148 		 unsigned group)
149 {
150 	print_keyring_serial_number(id);
151 	printuid(", ", user);
152 	printuid(", ", group);
153 }
154 
155 static void
keyctl_instantiate_key(struct tcb * tcp,key_serial_t id1,kernel_ulong_t addr,kernel_ulong_t len,key_serial_t id2)156 keyctl_instantiate_key(struct tcb *tcp, key_serial_t id1, kernel_ulong_t addr,
157 		       kernel_ulong_t len, key_serial_t id2)
158 {
159 	print_keyring_serial_number(id1);
160 	tprints(", ");
161 	printstrn(tcp, addr, len);
162 	tprintf(", %llu, ", zero_extend_signed_to_ull(len));
163 	print_keyring_serial_number(id2);
164 }
165 
166 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)167 keyctl_instantiate_key_iov(struct tcb *tcp, key_serial_t id1,
168 			   kernel_ulong_t addr, kernel_ulong_t len,
169 			   key_serial_t id2)
170 {
171 	print_keyring_serial_number(id1);
172 	tprints(", ");
173 	tprint_iov(tcp, len, addr, IOV_DECODE_STR);
174 	tprintf(", %llu, ", zero_extend_signed_to_ull(len));
175 	print_keyring_serial_number(id2);
176 }
177 
178 static void
keyctl_negate_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,key_serial_t id2)179 keyctl_negate_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
180 		  key_serial_t id2)
181 {
182 	print_keyring_serial_number(id1);
183 	tprintf(", %u, ", timeout);
184 	print_keyring_serial_number(id2);
185 }
186 
187 static void
keyctl_reject_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,unsigned error,key_serial_t id2)188 keyctl_reject_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
189 		  unsigned error, key_serial_t id2)
190 {
191 	const char *err_str = err_name(error);
192 
193 	print_keyring_serial_number(id1);
194 	tprintf(", %u, ", timeout);
195 
196 	if (err_str)
197 		tprintf("%s, ", err_str);
198 	else
199 		tprintf("%u, ", error);
200 
201 	print_keyring_serial_number(id2);
202 }
203 
204 static void
keyctl_set_timeout(struct tcb * tcp,key_serial_t id,unsigned timeout)205 keyctl_set_timeout(struct tcb *tcp, key_serial_t id, unsigned timeout)
206 {
207 	print_keyring_serial_number(id);
208 	tprintf(", %u", timeout);
209 }
210 
211 static void
keyctl_get_persistent(struct tcb * tcp,unsigned uid,key_serial_t id)212 keyctl_get_persistent(struct tcb *tcp, unsigned uid, key_serial_t id)
213 {
214 	printuid("", uid);
215 	tprints(", ");
216 	print_keyring_serial_number(id);
217 }
218 
219 #include "xlat/key_perms.h"
220 
221 static void
keyctl_setperm_key(struct tcb * tcp,key_serial_t id,uint32_t perm)222 keyctl_setperm_key(struct tcb *tcp, key_serial_t id, uint32_t perm)
223 {
224 	print_keyring_serial_number(id);
225 	tprints(", ");
226 	printflags(key_perms, perm, "KEY_???");
227 }
228 
229 static void
print_dh_params(struct tcb * tcp,kernel_ulong_t addr)230 print_dh_params(struct tcb *tcp, kernel_ulong_t addr)
231 {
232 	struct keyctl_dh_params params;
233 
234 	if (umove_or_printaddr(tcp, addr, &params))
235 		return;
236 
237 	tprints("{private=");
238 	print_keyring_serial_number(params.private);
239 	tprints(", prime=");
240 	print_keyring_serial_number(params.prime);
241 	tprints(", base=");
242 	print_keyring_serial_number(params.base);
243 	tprints("}");
244 }
245 
246 static void
keyctl_dh_compute(struct tcb * tcp,kernel_ulong_t params,kernel_ulong_t buf,kernel_ulong_t len)247 keyctl_dh_compute(struct tcb *tcp, kernel_ulong_t params, kernel_ulong_t buf,
248 		  kernel_ulong_t len)
249 {
250 	if (entering(tcp)) {
251 		print_dh_params(tcp, params);
252 		tprints(", ");
253 	} else {
254 		if (syserror(tcp)) {
255 			printaddr(buf);
256 		} else {
257 			kernel_ulong_t rval = (tcp->u_rval >= 0) &&
258 				((kernel_ulong_t) tcp->u_rval > len) ? len :
259 				(kernel_ulong_t) tcp->u_rval;
260 			printstrn(tcp, buf, rval);
261 		}
262 		tprintf(", %llu", zero_extend_signed_to_ull(len));
263 	}
264 }
265 
266 #include "xlat/key_reqkeys.h"
267 #include "xlat/keyctl_commands.h"
268 
SYS_FUNC(keyctl)269 SYS_FUNC(keyctl)
270 {
271 	int cmd = tcp->u_arg[0];
272 	kernel_ulong_t arg2 = tcp->u_arg[1];
273 	kernel_ulong_t arg3 = tcp->u_arg[2];
274 	kernel_ulong_t arg4 = tcp->u_arg[3];
275 	kernel_ulong_t arg5 = tcp->u_arg[4];
276 
277 	if (entering(tcp)) {
278 		printxval(keyctl_commands, cmd, "KEYCTL_???");
279 
280 		/*
281 		 * For now, KEYCTL_SESSION_TO_PARENT is the only cmd without
282 		 * arguments.
283 		 */
284 		if (cmd != KEYCTL_SESSION_TO_PARENT)
285 			tprints(", ");
286 	}
287 
288 	switch (cmd) {
289 	case KEYCTL_GET_KEYRING_ID:
290 		keyctl_get_keyring_id(tcp, arg2, arg3);
291 		break;
292 
293 	case KEYCTL_JOIN_SESSION_KEYRING:
294 		printstr(tcp, arg2);
295 		break;
296 
297 	case KEYCTL_UPDATE:
298 		keyctl_update_key(tcp, arg2, arg3, arg4);
299 		break;
300 
301 	case KEYCTL_REVOKE:
302 	case KEYCTL_CLEAR:
303 	case KEYCTL_INVALIDATE:
304 	case KEYCTL_ASSUME_AUTHORITY:
305 		print_keyring_serial_number(arg2);
306 		break;
307 
308 	case KEYCTL_LINK:
309 	case KEYCTL_UNLINK:
310 		keyctl_handle_key_key(tcp, arg2, arg3);
311 		break;
312 
313 	case KEYCTL_DESCRIBE:
314 	case KEYCTL_READ:
315 	case KEYCTL_GET_SECURITY:
316 		keyctl_read_key(tcp, arg2, arg3, arg4, cmd != KEYCTL_READ);
317 		return 0;
318 
319 	case KEYCTL_SEARCH:
320 		keyctl_keyring_search(tcp, arg2, arg3, arg4, arg5);
321 		break;
322 
323 	case KEYCTL_CHOWN:
324 		keyctl_chown_key(tcp, arg2, arg3, arg4);
325 		break;
326 
327 	case KEYCTL_SETPERM:
328 		keyctl_setperm_key(tcp, arg2, arg3);
329 		break;
330 
331 	case KEYCTL_INSTANTIATE:
332 		keyctl_instantiate_key(tcp, arg2, arg3, arg4, arg5);
333 		break;
334 
335 	case KEYCTL_NEGATE:
336 		keyctl_negate_key(tcp, arg2, arg3, arg4);
337 		break;
338 
339 	case KEYCTL_SET_REQKEY_KEYRING:
340 		printxval(key_reqkeys, arg2, "KEY_REQKEY_DEFL_???");
341 		break;
342 
343 	case KEYCTL_SET_TIMEOUT:
344 		keyctl_set_timeout(tcp, arg2, arg3);
345 		break;
346 
347 	case KEYCTL_SESSION_TO_PARENT:
348 		break;
349 
350 	case KEYCTL_REJECT:
351 		keyctl_reject_key(tcp, arg2, arg3, arg4, arg5);
352 		break;
353 
354 	case KEYCTL_INSTANTIATE_IOV:
355 		keyctl_instantiate_key_iov(tcp, arg2, arg3, arg4, arg5);
356 		break;
357 
358 	case KEYCTL_GET_PERSISTENT:
359 		keyctl_get_persistent(tcp, arg2, arg3);
360 		break;
361 
362 	case KEYCTL_DH_COMPUTE:
363 		keyctl_dh_compute(tcp, arg2, arg3, arg4);
364 		return 0;
365 
366 	default:
367 		tprintf("%#" PRI_klx ", %#" PRI_klx
368 			", %#" PRI_klx ", %#" PRI_klx,
369 			arg2, arg3, arg4, arg5);
370 		break;
371 	}
372 
373 	return RVAL_DECODED;
374 }
375