1 /* 2 * Support for decoding of KVM_* ioctl commands. 3 * 4 * Copyright (c) 2017 Masatake YAMATO <yamato (at) redhat.com> 5 * Copyright (c) 2017 Red Hat, Inc. 6 * Copyright (c) 2017-2018 The strace developers. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 34 #ifdef HAVE_LINUX_KVM_H 35 # include <linux/kvm.h> 36 # include "print_fields.h" 37 # include "arch_kvm.c" 38 # include "xmalloc.h" 39 # include "mmap_cache.h" 40 41 struct vcpu_info { 42 struct vcpu_info *next; 43 int fd; 44 int cpuid; 45 long mmap_addr; 46 unsigned long mmap_len; 47 bool resolved; 48 }; 49 50 static bool dump_kvm_run_structure; 51 52 static struct vcpu_info * 53 vcpu_find(struct tcb *const tcp, int fd) 54 { 55 for (struct vcpu_info *vcpu_info = tcp->vcpu_info_list; 56 vcpu_info; 57 vcpu_info = vcpu_info->next) 58 if (vcpu_info->fd == fd) 59 return vcpu_info; 60 61 return NULL; 62 } 63 64 static struct vcpu_info * 65 vcpu_alloc(struct tcb *const tcp, int fd, int cpuid) 66 { 67 struct vcpu_info *vcpu_info = xcalloc(1, sizeof(*vcpu_info)); 68 69 vcpu_info->fd = fd; 70 vcpu_info->cpuid = cpuid; 71 72 vcpu_info->next = tcp->vcpu_info_list; 73 tcp->vcpu_info_list = vcpu_info; 74 75 return vcpu_info; 76 } 77 78 void 79 kvm_vcpu_info_free(struct tcb *tcp) 80 { 81 struct vcpu_info *head, *next; 82 83 for (head = tcp->vcpu_info_list; head; head = next) { 84 next = head->next; 85 free(head); 86 } 87 88 tcp->vcpu_info_list = NULL; 89 } 90 91 static void 92 vcpu_register(struct tcb *const tcp, int fd, int cpuid) 93 { 94 if (fd < 0) 95 return; 96 97 struct vcpu_info *vcpu_info = vcpu_find(tcp, fd); 98 99 if (!vcpu_info) 100 vcpu_info = vcpu_alloc(tcp, fd, cpuid); 101 else if (vcpu_info->cpuid != cpuid) 102 { 103 vcpu_info->cpuid = cpuid; 104 vcpu_info->resolved = false; 105 } 106 } 107 108 static bool 109 is_map_for_file(struct mmap_cache_entry_t *map_info, void *data) 110 { 111 /* major version for anon inode may be given in get_anon_bdev() 112 * in linux kernel. 113 * 114 * *p = MKDEV(0, dev & MINORMASK); 115 *-----------------^ 116 */ 117 return map_info->binary_filename && 118 map_info->major == 0 && 119 strcmp(map_info->binary_filename, data) == 0; 120 } 121 122 static unsigned long 123 map_len(struct mmap_cache_entry_t *map_info) 124 { 125 return map_info->start_addr < map_info->end_addr 126 ? map_info->end_addr - map_info->start_addr 127 : 0; 128 } 129 130 #define VCPU_DENTRY_PREFIX "anon_inode:kvm-vcpu:" 131 132 static struct vcpu_info* 133 vcpu_get_info(struct tcb *const tcp, int fd) 134 { 135 struct vcpu_info *vcpu_info = vcpu_find(tcp, fd); 136 struct mmap_cache_entry_t *map_info; 137 const char *cpuid_str; 138 139 enum mmap_cache_rebuild_result mc_stat = 140 mmap_cache_rebuild_if_invalid(tcp, __func__); 141 if (mc_stat == MMAP_CACHE_REBUILD_NOCACHE) 142 return NULL; 143 144 if (vcpu_info && vcpu_info->resolved) { 145 if (mc_stat == MMAP_CACHE_REBUILD_READY) 146 return vcpu_info; 147 else { 148 map_info = mmap_cache_search(tcp, vcpu_info->mmap_addr); 149 if (map_info) { 150 cpuid_str = 151 STR_STRIP_PREFIX(map_info->binary_filename, 152 VCPU_DENTRY_PREFIX); 153 if (cpuid_str != map_info->binary_filename) { 154 int cpuid = string_to_uint(cpuid_str); 155 if (cpuid < 0) 156 return NULL; 157 if (vcpu_info->cpuid == cpuid) 158 return vcpu_info; 159 } 160 } 161 162 /* The vcpu vma may be mremap'ed. */ 163 vcpu_info->resolved = false; 164 } 165 } 166 167 /* Slow path: !vcpu_info || !vcpu_info->resolved */ 168 char path[PATH_MAX + 1]; 169 cpuid_str = path; 170 if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) 171 cpuid_str = STR_STRIP_PREFIX(path, VCPU_DENTRY_PREFIX); 172 if (cpuid_str == path) 173 map_info = NULL; 174 else 175 map_info = mmap_cache_search_custom(tcp, is_map_for_file, path); 176 177 if (map_info) { 178 int cpuid = string_to_uint(cpuid_str); 179 if (cpuid < 0) 180 return NULL; 181 if (!vcpu_info) 182 vcpu_info = vcpu_alloc(tcp, fd, cpuid); 183 else if (vcpu_info->cpuid != cpuid) 184 vcpu_info->cpuid = cpuid; 185 vcpu_info->mmap_addr = map_info->start_addr; 186 vcpu_info->mmap_len = map_len(map_info); 187 vcpu_info->resolved = true; 188 return vcpu_info; 189 } 190 191 return NULL; 192 } 193 194 static int 195 kvm_ioctl_create_vcpu(struct tcb *const tcp, const kernel_ulong_t arg) 196 { 197 uint32_t cpuid = arg; 198 199 if (entering(tcp)) { 200 tprintf(", %u", cpuid); 201 if (dump_kvm_run_structure) 202 return 0; 203 } else if (!syserror(tcp)) { 204 vcpu_register(tcp, tcp->u_rval, cpuid); 205 } 206 207 return RVAL_IOCTL_DECODED | RVAL_FD; 208 } 209 210 # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION 211 # include "xlat/kvm_mem_flags.h" 212 static int 213 kvm_ioctl_set_user_memory_region(struct tcb *const tcp, const kernel_ulong_t arg) 214 { 215 struct kvm_userspace_memory_region u_memory_region; 216 217 tprints(", "); 218 if (umove_or_printaddr(tcp, arg, &u_memory_region)) 219 return RVAL_IOCTL_DECODED; 220 221 PRINT_FIELD_U("{", u_memory_region, slot); 222 PRINT_FIELD_FLAGS(", ", u_memory_region, flags, kvm_mem_flags, 223 "KVM_MEM_???"); 224 PRINT_FIELD_X(", ", u_memory_region, guest_phys_addr); 225 PRINT_FIELD_U(", ", u_memory_region, memory_size); 226 PRINT_FIELD_X(", ", u_memory_region, userspace_addr); 227 tprints("}"); 228 229 return RVAL_IOCTL_DECODED; 230 } 231 # endif /* HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION */ 232 233 # ifdef HAVE_STRUCT_KVM_REGS 234 static int 235 kvm_ioctl_decode_regs(struct tcb *const tcp, const unsigned int code, 236 const kernel_ulong_t arg) 237 { 238 struct kvm_regs regs; 239 240 if (code == KVM_GET_REGS && entering(tcp)) 241 return 0; 242 243 tprints(", "); 244 if (!umove_or_printaddr(tcp, arg, ®s)) 245 arch_print_kvm_regs(tcp, arg, ®s); 246 247 return RVAL_IOCTL_DECODED; 248 } 249 # endif /* HAVE_STRUCT_KVM_REGS */ 250 251 # ifdef HAVE_STRUCT_KVM_CPUID2 252 # include "xlat/kvm_cpuid_flags.h" 253 static bool 254 print_kvm_cpuid_entry(struct tcb *const tcp, 255 void* elem_buf, size_t elem_size, void* data) 256 { 257 const struct kvm_cpuid_entry2 *entry = elem_buf; 258 PRINT_FIELD_X("{", *entry, function); 259 PRINT_FIELD_X(", ", *entry, index); 260 PRINT_FIELD_FLAGS(", ", *entry, flags, kvm_cpuid_flags, 261 "KVM_CPUID_FLAG_???"); 262 PRINT_FIELD_X(", ", *entry, eax); 263 PRINT_FIELD_X(", ", *entry, ebx); 264 PRINT_FIELD_X(", ", *entry, ecx); 265 PRINT_FIELD_X(", ", *entry, edx); 266 tprints("}"); 267 268 return true; 269 } 270 271 static int 272 kvm_ioctl_decode_cpuid2(struct tcb *const tcp, const unsigned int code, 273 const kernel_ulong_t arg) 274 { 275 struct kvm_cpuid2 cpuid; 276 277 if (entering(tcp) && (code == KVM_GET_SUPPORTED_CPUID 278 # ifdef KVM_GET_EMULATED_CPUID 279 || code == KVM_GET_EMULATED_CPUID 280 # endif 281 )) 282 return 0; 283 284 tprints(", "); 285 if (!umove_or_printaddr(tcp, arg, &cpuid)) { 286 PRINT_FIELD_U("{", cpuid, nent); 287 288 tprints(", entries="); 289 if (abbrev(tcp)) { 290 tprints("["); 291 if (cpuid.nent) 292 tprints("..."); 293 tprints("]"); 294 295 } else { 296 struct kvm_cpuid_entry2 entry; 297 print_array(tcp, arg + sizeof(cpuid), cpuid.nent, 298 &entry, sizeof(entry), tfetch_mem, 299 print_kvm_cpuid_entry, NULL); 300 } 301 tprints("}"); 302 } 303 304 return RVAL_IOCTL_DECODED; 305 } 306 # endif /* HAVE_STRUCT_KVM_CPUID2 */ 307 308 # ifdef HAVE_STRUCT_KVM_SREGS 309 static int 310 kvm_ioctl_decode_sregs(struct tcb *const tcp, const unsigned int code, 311 const kernel_ulong_t arg) 312 { 313 struct kvm_sregs sregs; 314 315 if (code == KVM_GET_SREGS && entering(tcp)) 316 return 0; 317 318 tprints(", "); 319 if (!umove_or_printaddr(tcp, arg, &sregs)) 320 arch_print_kvm_sregs(tcp, arg, &sregs); 321 322 return RVAL_IOCTL_DECODED; 323 } 324 # endif /* HAVE_STRUCT_KVM_SREGS */ 325 326 # include "xlat/kvm_cap.h" 327 static int 328 kvm_ioctl_decode_check_extension(struct tcb *const tcp, const unsigned int code, 329 const kernel_ulong_t arg) 330 { 331 tprints(", "); 332 printxval_index(kvm_cap, arg, "KVM_CAP_???"); 333 return RVAL_IOCTL_DECODED; 334 } 335 336 # include "xlat/kvm_exit_reason.h" 337 static void 338 kvm_ioctl_run_attach_auxstr(struct tcb *const tcp, 339 struct vcpu_info *info) 340 341 { 342 static struct kvm_run vcpu_run_struct; 343 344 if (info->mmap_len < sizeof(vcpu_run_struct)) 345 return; 346 347 if (umove(tcp, info->mmap_addr, &vcpu_run_struct) < 0) 348 return; 349 350 tcp->auxstr = xlat_idx(kvm_exit_reason, ARRAY_SIZE(kvm_exit_reason) - 1, 351 vcpu_run_struct.exit_reason); 352 if (!tcp->auxstr) 353 tcp->auxstr = "KVM_EXIT_???"; 354 } 355 356 static int 357 kvm_ioctl_decode_run(struct tcb *const tcp) 358 { 359 360 if (entering(tcp)) 361 return 0; 362 363 int r = RVAL_DECODED; 364 365 if (syserror(tcp)) 366 return r; 367 368 if (dump_kvm_run_structure) { 369 tcp->auxstr = NULL; 370 int fd = tcp->u_arg[0]; 371 struct vcpu_info *info = vcpu_get_info(tcp, fd); 372 373 if (info) { 374 kvm_ioctl_run_attach_auxstr(tcp, info); 375 if (tcp->auxstr) 376 r |= RVAL_STR; 377 } 378 } 379 380 return r; 381 } 382 383 int 384 kvm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg) 385 { 386 switch (code) { 387 case KVM_CREATE_VCPU: 388 return kvm_ioctl_create_vcpu(tcp, arg); 389 390 # ifdef HAVE_STRUCT_KVM_USERSPACE_MEMORY_REGION 391 case KVM_SET_USER_MEMORY_REGION: 392 return kvm_ioctl_set_user_memory_region(tcp, arg); 393 # endif 394 395 # ifdef HAVE_STRUCT_KVM_REGS 396 case KVM_SET_REGS: 397 case KVM_GET_REGS: 398 return kvm_ioctl_decode_regs(tcp, code, arg); 399 # endif 400 401 # ifdef HAVE_STRUCT_KVM_SREGS 402 case KVM_SET_SREGS: 403 case KVM_GET_SREGS: 404 return kvm_ioctl_decode_sregs(tcp, code, arg); 405 # endif 406 407 # ifdef HAVE_STRUCT_KVM_CPUID2 408 case KVM_SET_CPUID2: 409 case KVM_GET_SUPPORTED_CPUID: 410 # ifdef KVM_GET_EMULATED_CPUID 411 case KVM_GET_EMULATED_CPUID: 412 # endif 413 return kvm_ioctl_decode_cpuid2(tcp, code, arg); 414 # endif 415 416 case KVM_CHECK_EXTENSION: 417 return kvm_ioctl_decode_check_extension(tcp, code, arg); 418 419 case KVM_CREATE_VM: 420 return RVAL_DECODED | RVAL_FD; 421 422 case KVM_RUN: 423 return kvm_ioctl_decode_run(tcp); 424 425 case KVM_GET_VCPU_MMAP_SIZE: 426 case KVM_GET_API_VERSION: 427 default: 428 return RVAL_DECODED; 429 } 430 } 431 432 void 433 kvm_run_structure_decoder_init(void) 434 { 435 dump_kvm_run_structure = true; 436 mmap_cache_enable(); 437 } 438 439 #endif /* HAVE_LINUX_KVM_H */ 440