1#include "defs.h"
2#include <linux/keyctl.h>
3
4typedef int32_t key_serial_t;
5
6#include "xlat/key_spec.h"
7
8static void
9print_keyring_serial_number(key_serial_t id)
10{
11	const char *str = xlookup(key_spec, id);
12
13	if (str)
14		tprints(str);
15	else
16		tprintf("%d", id);
17}
18
19int
20sys_add_key(struct tcb *tcp)
21{
22	if (entering(tcp)) {
23		/* type */
24		printstr(tcp, tcp->u_arg[0], -1);
25		/* description */
26		tprints(", ");
27		printstr(tcp, tcp->u_arg[1], -1);
28		/* payload */
29		tprints(", ");
30		printstr(tcp, tcp->u_arg[2], tcp->u_arg[3]);
31		/* payload length */
32		tprintf(", %lu, ", tcp->u_arg[3]);
33		/* keyring serial number */
34		print_keyring_serial_number(tcp->u_arg[4]);
35	}
36	return 0;
37}
38
39int
40sys_request_key(struct tcb *tcp)
41{
42	if (entering(tcp)) {
43		/* type */
44		printstr(tcp, tcp->u_arg[0], -1);
45		/* description */
46		tprints(", ");
47		printstr(tcp, tcp->u_arg[1], -1);
48		/* callout_info */
49		tprints(", ");
50		printstr(tcp, tcp->u_arg[2], -1);
51		/* keyring serial number */
52		tprints(", ");
53		print_keyring_serial_number(tcp->u_arg[3]);
54	}
55	return 0;
56}
57
58static int
59keyctl_get_keyring_id(struct tcb *tcp, key_serial_t id, int create)
60{
61	if (entering(tcp)) {
62		tprints(", ");
63		print_keyring_serial_number(id);
64		tprintf(", %d", create);
65	}
66	return 0;
67}
68
69static int
70keyctl_join_session_keyring(struct tcb *tcp, long addr)
71{
72	if (entering(tcp)) {
73		tprints(", ");
74		printstr(tcp, addr, -1);
75	}
76	return 0;
77}
78
79static int
80keyctl_update_key(struct tcb *tcp, key_serial_t id, long addr, long len)
81{
82	if (entering(tcp)) {
83		tprints(", ");
84		print_keyring_serial_number(id);
85		tprints(", ");
86		printstr(tcp, addr, len);
87		tprintf(", %lu", len);
88	}
89	return 0;
90}
91
92static int
93keyctl_handle_key(struct tcb *tcp, key_serial_t id)
94{
95	if (entering(tcp)) {
96		tprints(", ");
97		print_keyring_serial_number(id);
98	}
99	return 0;
100}
101
102static int
103keyctl_handle_key_key(struct tcb *tcp, key_serial_t id1, key_serial_t id2)
104{
105	if (entering(tcp)) {
106		tprints(", ");
107		print_keyring_serial_number(id1);
108		tprints(", ");
109		print_keyring_serial_number(id2);
110	}
111	return 0;
112}
113
114static int
115keyctl_read_key(struct tcb *tcp, key_serial_t id, long addr, long len)
116{
117	if (entering(tcp)) {
118		tprints(", ");
119		print_keyring_serial_number(id);
120		tprints(", ");
121	} else {
122		if (addr && syserror(tcp))
123			tprintf("%#lx", addr);
124		else {
125			long rval = tcp->u_rval > len ?
126				    len : (tcp->u_rval ? -1 : 0);
127			printstr(tcp, addr, rval);
128		}
129		tprintf(", %lu", len);
130	}
131	return 0;
132}
133
134static int
135keyctl_keyring_search(struct tcb *tcp, key_serial_t id1, long addr1,
136		      long addr2, key_serial_t id2)
137{
138	if (entering(tcp)) {
139		tprints(", ");
140		print_keyring_serial_number(id1);
141		tprints(", ");
142		printstr(tcp, addr1, -1);
143		tprints(", ");
144		printstr(tcp, addr2, -1);
145		tprints(", ");
146		print_keyring_serial_number(id2);
147	}
148	return 0;
149}
150
151static int
152keyctl_chown_key(struct tcb *tcp, key_serial_t id, int user, int group)
153{
154	if (entering(tcp)) {
155		tprints(", ");
156		print_keyring_serial_number(id);
157		tprintf(", %d, %d", user, group);
158	}
159	return 0;
160}
161
162static int
163keyctl_instantiate_key(struct tcb *tcp, key_serial_t id1, long addr,
164		       long len, key_serial_t id2)
165{
166	if (entering(tcp)) {
167		tprints(", ");
168		print_keyring_serial_number(id1);
169		tprints(", ");
170		printstr(tcp, addr, len);
171		tprintf(", %lu, ", len);
172		print_keyring_serial_number(id2);
173	}
174	return 0;
175}
176
177static int
178keyctl_instantiate_key_iov(struct tcb *tcp, key_serial_t id1,
179			   long addr, long len, key_serial_t id2)
180{
181	if (entering(tcp)) {
182		tprints(", ");
183		print_keyring_serial_number(id1);
184		tprints(", ");
185		tprint_iov(tcp, len, addr, 1);
186		tprintf(", %lu, ", len);
187		print_keyring_serial_number(id2);
188	}
189	return 0;
190}
191
192static int
193keyctl_negate_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
194		  key_serial_t id2)
195{
196	if (entering(tcp)) {
197		tprints(", ");
198		print_keyring_serial_number(id1);
199		tprintf(", %u, ", timeout);
200		print_keyring_serial_number(id2);
201	}
202	return 0;
203}
204
205static int
206keyctl_reject_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
207		  unsigned error, key_serial_t id2)
208{
209	if (entering(tcp)) {
210		tprints(", ");
211		print_keyring_serial_number(id1);
212		tprintf(", %u, %u, ", timeout, error);
213		print_keyring_serial_number(id2);
214	}
215	return 0;
216}
217
218static int
219keyctl_set_timeout(struct tcb *tcp, key_serial_t id, unsigned timeout)
220{
221	if (entering(tcp)) {
222		tprints(", ");
223		print_keyring_serial_number(id);
224		tprintf(", %u", timeout);
225	}
226	return 0;
227}
228
229static int
230keyctl_get_persistent(struct tcb *tcp, int uid, key_serial_t id)
231{
232	if (entering(tcp)) {
233		tprintf(", %d, ", uid);
234		print_keyring_serial_number(id);
235	}
236	return 0;
237}
238
239#define KEY_POS_VIEW	0x01000000
240#define KEY_POS_READ	0x02000000
241#define KEY_POS_WRITE	0x04000000
242#define KEY_POS_SEARCH	0x08000000
243#define KEY_POS_LINK	0x10000000
244#define KEY_POS_SETATTR	0x20000000
245#define KEY_POS_ALL	0x3f000000
246#define KEY_USR_VIEW	0x00010000
247#define KEY_USR_READ	0x00020000
248#define KEY_USR_WRITE	0x00040000
249#define KEY_USR_SEARCH	0x00080000
250#define KEY_USR_LINK	0x00100000
251#define KEY_USR_SETATTR	0x00200000
252#define KEY_USR_ALL	0x003f0000
253#define KEY_GRP_VIEW	0x00000100
254#define KEY_GRP_READ	0x00000200
255#define KEY_GRP_WRITE	0x00000400
256#define KEY_GRP_SEARCH	0x00000800
257#define KEY_GRP_LINK	0x00001000
258#define KEY_GRP_SETATTR	0x00002000
259#define KEY_GRP_ALL	0x00003f00
260#define KEY_OTH_VIEW	0x00000001
261#define KEY_OTH_READ	0x00000002
262#define KEY_OTH_WRITE	0x00000004
263#define KEY_OTH_SEARCH	0x00000008
264#define KEY_OTH_LINK	0x00000010
265#define KEY_OTH_SETATTR	0x00000020
266#define KEY_OTH_ALL	0x0000003f
267
268#include "xlat/key_perms.h"
269
270static int
271keyctl_setperm_key(struct tcb *tcp, key_serial_t id, uint32_t perm)
272{
273	if (entering(tcp)) {
274		tprints(", ");
275		print_keyring_serial_number(id);
276		tprints(", ");
277		printflags(key_perms, perm, "KEY_???");
278	}
279	return 0;
280}
281
282#include "xlat/key_reqkeys.h"
283
284static int
285keyctl_set_reqkey_keyring(struct tcb *tcp, int reqkey)
286{
287	if (entering(tcp)) {
288		tprints(", ");
289		printxval(key_reqkeys, reqkey, "KEY_REQKEY_DEFL_???");
290	}
291	return 0;
292}
293
294#include "xlat/keyctl_commands.h"
295
296int
297sys_keyctl(struct tcb *tcp)
298{
299	int cmd = tcp->u_arg[0];
300
301	if (entering(tcp))
302		printxval(keyctl_commands, cmd, "KEYCTL_???");
303
304	switch (cmd) {
305	case KEYCTL_GET_KEYRING_ID:
306		return keyctl_get_keyring_id(tcp, tcp->u_arg[1], tcp->u_arg[2]);
307
308	case KEYCTL_JOIN_SESSION_KEYRING:
309		return keyctl_join_session_keyring(tcp, tcp->u_arg[1]);
310
311	case KEYCTL_UPDATE:
312		return keyctl_update_key(tcp, tcp->u_arg[1],
313					 tcp->u_arg[2], tcp->u_arg[3]);
314
315	case KEYCTL_REVOKE:
316	case KEYCTL_CLEAR:
317	case KEYCTL_INVALIDATE:
318	case KEYCTL_ASSUME_AUTHORITY:
319		return keyctl_handle_key(tcp, tcp->u_arg[1]);
320
321	case KEYCTL_LINK:
322	case KEYCTL_UNLINK:
323		return keyctl_handle_key_key(tcp, tcp->u_arg[1], tcp->u_arg[2]);
324
325	case KEYCTL_DESCRIBE:
326	case KEYCTL_READ:
327	case KEYCTL_GET_SECURITY:
328		return keyctl_read_key(tcp, tcp->u_arg[1],
329				       tcp->u_arg[2], tcp->u_arg[3]);
330
331	case KEYCTL_SEARCH:
332		return keyctl_keyring_search(tcp, tcp->u_arg[1], tcp->u_arg[2],
333					     tcp->u_arg[3], tcp->u_arg[4]);
334
335	case KEYCTL_CHOWN:
336		return keyctl_chown_key(tcp, tcp->u_arg[1],
337					tcp->u_arg[2], tcp->u_arg[3]);
338
339	case KEYCTL_SETPERM:
340		return keyctl_setperm_key(tcp, tcp->u_arg[1], tcp->u_arg[2]);
341
342	case KEYCTL_INSTANTIATE:
343		return keyctl_instantiate_key(tcp, tcp->u_arg[1], tcp->u_arg[2],
344					      tcp->u_arg[3], tcp->u_arg[4]);
345
346	case KEYCTL_NEGATE:
347		return keyctl_negate_key(tcp, tcp->u_arg[1],
348					 tcp->u_arg[2], tcp->u_arg[3]);
349
350	case KEYCTL_SET_REQKEY_KEYRING:
351		return keyctl_set_reqkey_keyring(tcp, tcp->u_arg[1]);
352
353	case KEYCTL_SET_TIMEOUT:
354		return keyctl_set_timeout(tcp, tcp->u_arg[1], tcp->u_arg[2]);
355
356	case KEYCTL_SESSION_TO_PARENT:
357		return 0;
358
359	case KEYCTL_REJECT:
360		return keyctl_reject_key(tcp, tcp->u_arg[1], tcp->u_arg[2],
361					 tcp->u_arg[3], tcp->u_arg[4]);
362
363	case KEYCTL_INSTANTIATE_IOV:
364		return keyctl_instantiate_key_iov(tcp, tcp->u_arg[1],
365						  tcp->u_arg[2], tcp->u_arg[3],
366						  tcp->u_arg[4]);
367
368	case KEYCTL_GET_PERSISTENT:
369		return keyctl_get_persistent(tcp, tcp->u_arg[1], tcp->u_arg[2]);
370
371	default:
372		if (entering(tcp))
373			tprintf(", %#lx, %#lx, %#lx, %#lx",
374				tcp->u_arg[1], tcp->u_arg[2],
375				tcp->u_arg[3], tcp->u_arg[4]);
376	}
377
378	return 0;
379}
380