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 static void
print_keyring_serial_number(key_serial_t id)35 print_keyring_serial_number(key_serial_t id)
36 {
37 	const char *str = xlookup(key_spec, id);
38 
39 	if (str)
40 		tprints(str);
41 	else
42 		tprintf("%d", id);
43 }
44 
SYS_FUNC(add_key)45 SYS_FUNC(add_key)
46 {
47 	/* type */
48 	printstr(tcp, tcp->u_arg[0], -1);
49 	/* description */
50 	tprints(", ");
51 	printstr(tcp, tcp->u_arg[1], -1);
52 	/* payload */
53 	tprints(", ");
54 	printstr(tcp, tcp->u_arg[2], tcp->u_arg[3]);
55 	/* payload length */
56 	tprintf(", %lu, ", tcp->u_arg[3]);
57 	/* keyring serial number */
58 	print_keyring_serial_number(tcp->u_arg[4]);
59 
60 	return RVAL_DECODED;
61 }
62 
SYS_FUNC(request_key)63 SYS_FUNC(request_key)
64 {
65 	/* type */
66 	printstr(tcp, tcp->u_arg[0], -1);
67 	/* description */
68 	tprints(", ");
69 	printstr(tcp, tcp->u_arg[1], -1);
70 	/* callout_info */
71 	tprints(", ");
72 	printstr(tcp, tcp->u_arg[2], -1);
73 	/* keyring serial number */
74 	tprints(", ");
75 	print_keyring_serial_number(tcp->u_arg[3]);
76 
77 	return RVAL_DECODED;
78 }
79 
80 static void
keyctl_get_keyring_id(struct tcb * tcp,key_serial_t id,int create)81 keyctl_get_keyring_id(struct tcb *tcp, key_serial_t id, int create)
82 {
83 	print_keyring_serial_number(id);
84 	tprintf(", %d", create);
85 }
86 
87 static void
keyctl_update_key(struct tcb * tcp,key_serial_t id,long addr,long len)88 keyctl_update_key(struct tcb *tcp, key_serial_t id, long addr, long len)
89 {
90 	print_keyring_serial_number(id);
91 	tprints(", ");
92 	printstr(tcp, addr, len);
93 	tprintf(", %lu", len);
94 }
95 
96 static void
keyctl_handle_key_key(struct tcb * tcp,key_serial_t id1,key_serial_t id2)97 keyctl_handle_key_key(struct tcb *tcp, key_serial_t id1, key_serial_t id2)
98 {
99 	print_keyring_serial_number(id1);
100 	tprints(", ");
101 	print_keyring_serial_number(id2);
102 }
103 
104 static void
keyctl_read_key(struct tcb * tcp,key_serial_t id,long addr,long len)105 keyctl_read_key(struct tcb *tcp, key_serial_t id, long addr, long len)
106 {
107 	if (entering(tcp)) {
108 		print_keyring_serial_number(id);
109 		tprints(", ");
110 	} else {
111 		if (syserror(tcp))
112 			printaddr(addr);
113 		else {
114 			long rval = tcp->u_rval > len ?
115 				    len : (tcp->u_rval ? -1 : 0);
116 			printstr(tcp, addr, rval);
117 		}
118 		tprintf(", %lu", len);
119 	}
120 }
121 
122 static void
keyctl_keyring_search(struct tcb * tcp,key_serial_t id1,long addr1,long addr2,key_serial_t id2)123 keyctl_keyring_search(struct tcb *tcp, key_serial_t id1, long addr1,
124 		      long addr2, key_serial_t id2)
125 {
126 	print_keyring_serial_number(id1);
127 	tprints(", ");
128 	printstr(tcp, addr1, -1);
129 	tprints(", ");
130 	printstr(tcp, addr2, -1);
131 	tprints(", ");
132 	print_keyring_serial_number(id2);
133 }
134 
135 static void
keyctl_chown_key(struct tcb * tcp,key_serial_t id,int user,int group)136 keyctl_chown_key(struct tcb *tcp, key_serial_t id, int user, int group)
137 {
138 	print_keyring_serial_number(id);
139 	tprintf(", %d, %d", user, group);
140 }
141 
142 static void
keyctl_instantiate_key(struct tcb * tcp,key_serial_t id1,long addr,long len,key_serial_t id2)143 keyctl_instantiate_key(struct tcb *tcp, key_serial_t id1, long addr,
144 		       long len, key_serial_t id2)
145 {
146 	print_keyring_serial_number(id1);
147 	tprints(", ");
148 	printstr(tcp, addr, len);
149 	tprintf(", %lu, ", len);
150 	print_keyring_serial_number(id2);
151 }
152 
153 static void
keyctl_instantiate_key_iov(struct tcb * tcp,key_serial_t id1,long addr,long len,key_serial_t id2)154 keyctl_instantiate_key_iov(struct tcb *tcp, key_serial_t id1,
155 			   long addr, long len, key_serial_t id2)
156 {
157 	print_keyring_serial_number(id1);
158 	tprints(", ");
159 	tprint_iov(tcp, len, addr, 1);
160 	tprintf(", %lu, ", len);
161 	print_keyring_serial_number(id2);
162 }
163 
164 static void
keyctl_negate_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,key_serial_t id2)165 keyctl_negate_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
166 		  key_serial_t id2)
167 {
168 	print_keyring_serial_number(id1);
169 	tprintf(", %u, ", timeout);
170 	print_keyring_serial_number(id2);
171 }
172 
173 static void
keyctl_reject_key(struct tcb * tcp,key_serial_t id1,unsigned timeout,unsigned error,key_serial_t id2)174 keyctl_reject_key(struct tcb *tcp, key_serial_t id1, unsigned timeout,
175 		  unsigned error, key_serial_t id2)
176 {
177 	print_keyring_serial_number(id1);
178 	tprintf(", %u, %u, ", timeout, error);
179 	print_keyring_serial_number(id2);
180 }
181 
182 static void
keyctl_set_timeout(struct tcb * tcp,key_serial_t id,unsigned timeout)183 keyctl_set_timeout(struct tcb *tcp, key_serial_t id, unsigned timeout)
184 {
185 	print_keyring_serial_number(id);
186 	tprintf(", %u", timeout);
187 }
188 
189 static void
keyctl_get_persistent(struct tcb * tcp,int uid,key_serial_t id)190 keyctl_get_persistent(struct tcb *tcp, int uid, key_serial_t id)
191 {
192 	tprintf("%d, ", uid);
193 	print_keyring_serial_number(id);
194 }
195 
196 #include "xlat/key_perms.h"
197 
198 static void
keyctl_setperm_key(struct tcb * tcp,key_serial_t id,uint32_t perm)199 keyctl_setperm_key(struct tcb *tcp, key_serial_t id, uint32_t perm)
200 {
201 	print_keyring_serial_number(id);
202 	tprints(", ");
203 	printflags(key_perms, perm, "KEY_???");
204 }
205 
206 #include "xlat/key_reqkeys.h"
207 #include "xlat/keyctl_commands.h"
208 
SYS_FUNC(keyctl)209 SYS_FUNC(keyctl)
210 {
211 	int cmd = tcp->u_arg[0];
212 
213 	if (entering(tcp)) {
214 		printxval(keyctl_commands, cmd, "KEYCTL_???");
215 		tprints(", ");
216 	}
217 
218 	switch (cmd) {
219 	case KEYCTL_GET_KEYRING_ID:
220 		keyctl_get_keyring_id(tcp, tcp->u_arg[1], tcp->u_arg[2]);
221 		break;
222 
223 	case KEYCTL_JOIN_SESSION_KEYRING:
224 		printstr(tcp, tcp->u_arg[1], -1);
225 		break;
226 
227 	case KEYCTL_UPDATE:
228 		keyctl_update_key(tcp, tcp->u_arg[1],
229 				  tcp->u_arg[2], tcp->u_arg[3]);
230 		break;
231 
232 	case KEYCTL_REVOKE:
233 	case KEYCTL_CLEAR:
234 	case KEYCTL_INVALIDATE:
235 	case KEYCTL_ASSUME_AUTHORITY:
236 		print_keyring_serial_number(tcp->u_arg[1]);
237 		break;
238 
239 	case KEYCTL_LINK:
240 	case KEYCTL_UNLINK:
241 		keyctl_handle_key_key(tcp, tcp->u_arg[1], tcp->u_arg[2]);
242 		break;
243 
244 	case KEYCTL_DESCRIBE:
245 	case KEYCTL_READ:
246 	case KEYCTL_GET_SECURITY:
247 		keyctl_read_key(tcp, tcp->u_arg[1],
248 				tcp->u_arg[2], tcp->u_arg[3]);
249 		return 0;
250 
251 	case KEYCTL_SEARCH:
252 		keyctl_keyring_search(tcp, tcp->u_arg[1], tcp->u_arg[2],
253 				      tcp->u_arg[3], tcp->u_arg[4]);
254 		break;
255 
256 	case KEYCTL_CHOWN:
257 		keyctl_chown_key(tcp, tcp->u_arg[1],
258 				 tcp->u_arg[2], tcp->u_arg[3]);
259 		break;
260 
261 	case KEYCTL_SETPERM:
262 		keyctl_setperm_key(tcp, tcp->u_arg[1], tcp->u_arg[2]);
263 		break;
264 
265 	case KEYCTL_INSTANTIATE:
266 		keyctl_instantiate_key(tcp, tcp->u_arg[1], tcp->u_arg[2],
267 				       tcp->u_arg[3], tcp->u_arg[4]);
268 		break;
269 
270 	case KEYCTL_NEGATE:
271 		keyctl_negate_key(tcp, tcp->u_arg[1],
272 				  tcp->u_arg[2], tcp->u_arg[3]);
273 		break;
274 
275 	case KEYCTL_SET_REQKEY_KEYRING:
276 		printxval(key_reqkeys, tcp->u_arg[1], "KEY_REQKEY_DEFL_???");
277 		break;
278 
279 	case KEYCTL_SET_TIMEOUT:
280 		keyctl_set_timeout(tcp, tcp->u_arg[1], tcp->u_arg[2]);
281 		break;
282 
283 	case KEYCTL_SESSION_TO_PARENT:
284 		break;
285 
286 	case KEYCTL_REJECT:
287 		keyctl_reject_key(tcp, tcp->u_arg[1], tcp->u_arg[2],
288 				  tcp->u_arg[3], tcp->u_arg[4]);
289 		break;
290 
291 	case KEYCTL_INSTANTIATE_IOV:
292 		keyctl_instantiate_key_iov(tcp, tcp->u_arg[1],
293 					   tcp->u_arg[2], tcp->u_arg[3],
294 					   tcp->u_arg[4]);
295 		break;
296 
297 	case KEYCTL_GET_PERSISTENT:
298 		keyctl_get_persistent(tcp, tcp->u_arg[1], tcp->u_arg[2]);
299 		break;
300 
301 	default:
302 		tprintf("%#lx, %#lx, %#lx, %#lx",
303 			tcp->u_arg[1], tcp->u_arg[2],
304 			tcp->u_arg[3], tcp->u_arg[4]);
305 		break;
306 	}
307 
308 	return RVAL_DECODED;
309 }
310