1 /* 2 * Copyright (c) 2014-2015 Dmitry V. Levin <ldv (at) 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, ¶ms)) 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 } 374