]> granicus.if.org Git - strace/blob - keyctl.c
tests: check decoding of prctl PR_GET_TID_ADDRESS operation
[strace] / keyctl.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &params))
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
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
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 }