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, ¶ms))
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