diff options
| author | Alexander Potapenko <glider@google.com> | 2024-11-21 16:30:50 +0100 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2024-11-26 11:12:47 +0000 |
| commit | 2ebbc7259f2bda405779335b46a2f519f14ec473 (patch) | |
| tree | b81960041de957bb95a917df9c42924d8ac6de9b | |
| parent | ae34cc2c773d3522e98ab8f038e2e5875fb9dac4 (diff) | |
executor: arm64: sys/linux: allocate 1024 pages for guest address space
Pass 1024 pages of memory to both syz_kvm_setup_syzos_vm() and
syz_kvm_setup_cpu$arm64() to make sure that:
- there is enough memory for guest allocations (e.g. ITS pages)
- host can tamper with that memory, provoking more bugs
| -rw-r--r-- | executor/common_kvm_arm64.h | 31 | ||||
| -rw-r--r-- | executor/common_linux.h | 2 | ||||
| -rw-r--r-- | sys/linux/dev_kvm.txt | 4 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-memwrite | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-msr | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-smc | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3 | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-cpu1 | 2 | ||||
| -rw-r--r-- | sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-its | 2 |
10 files changed, 21 insertions, 30 deletions
diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h index bc809a152..dcd83aa6b 100644 --- a/executor/common_kvm_arm64.h +++ b/executor/common_kvm_arm64.h @@ -13,7 +13,7 @@ #define KVM_MAX_VCPU 4 #define KVM_PAGE_SIZE (4 << 10) -#define KVM_GUEST_MEM_SIZE (24 * KVM_PAGE_SIZE) +#define KVM_GUEST_MEM_SIZE (1024 * KVM_PAGE_SIZE) #endif @@ -101,15 +101,15 @@ static void setup_vm(int vmfd, void* host_mem, void** text_slot) next = alloc_guest_mem(&allocator, KVM_PAGE_SIZE); vm_set_user_memory_region(vmfd, slot++, 0, ARM64_ADDR_SCRATCH_CODE, next.size, (uintptr_t)next.addr); + // Allocate memory for the ITS tables: 64K for the device table, collection table, command queue, property table, + // plus 64K * 4 CPUs for the pending tables, and 64K * 16 devices for the ITT tables. + int its_size = SZ_64K * (4 + 4 + 16); + next = alloc_guest_mem(&allocator, its_size); + vm_set_user_memory_region(vmfd, slot++, 0, ARM64_ADDR_ITS_TABLES, next.size, (uintptr_t)next.addr); + // Map the remaining pages at address 0. next = alloc_guest_mem(&allocator, allocator.size); vm_set_user_memory_region(vmfd, slot++, 0, 0, next.size, (uintptr_t)next.addr); - - // Allocate memory for the ITS tables. - // TODO(glider): leak this memory for now, this shouldn't be a problem for the short-living executor process. - int its_size = SZ_64K * (4 + /*num_cpus*/ 4 + /*num_devices*/ 16); - void* its = mmap(NULL, its_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); - vm_set_user_memory_region(vmfd, slot++, 0, ARM64_ADDR_ITS_TABLES, its_size, (uintptr_t)its); } #endif @@ -214,23 +214,14 @@ struct kvm_syz_vm { #if SYZ_EXECUTOR || __NR_syz_kvm_setup_syzos_vm -// Allocate a page using a syscall, as we may not have malloc(). -// This page will be leaked, its address will be used as an opaque resource ID. -static void* leaky_alloc_page() -{ - return mmap(NULL, KVM_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); -} - -static long syz_kvm_setup_syzos_vm(volatile long a0) +static long syz_kvm_setup_syzos_vm(volatile long a0, volatile long a1) { const int vmfd = a0; - - struct kvm_syz_vm* ret = (struct kvm_syz_vm*)leaky_alloc_page(); - if ((long)ret == -1) - return -1; + void* host_mem = (void*)a1; void* user_text_slot = NULL; - void* host_mem = mmap(NULL, KVM_GUEST_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + struct kvm_syz_vm* ret = (struct kvm_syz_vm*)host_mem; + host_mem = (void*)((uint64)host_mem + KVM_PAGE_SIZE); setup_vm(vmfd, host_mem, &user_text_slot); ret->vmfd = vmfd; ret->next_cpu_id = 0; diff --git a/executor/common_linux.h b/executor/common_linux.h index 562fe703b..b6214563e 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -3222,7 +3222,7 @@ static long syz_kvm_add_vcpu(volatile long a0, volatile long a1, volatile long a } #endif #if !GOARCH_arm64 && (SYZ_EXECUTOR || __NR_syz_kvm_setup_syzos_vm) -static long syz_kvm_setup_syzos_vm(volatile long a0) +static long syz_kvm_setup_syzos_vm(volatile long a0, volatile long a1) { return 0; } diff --git a/sys/linux/dev_kvm.txt b/sys/linux/dev_kvm.txt index def833602..784b625fb 100644 --- a/sys/linux/dev_kvm.txt +++ b/sys/linux/dev_kvm.txt @@ -260,14 +260,14 @@ kvm_x86_rflags = 1, 2, 4, 16, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, # Pseudo call that setups VCPU into a reasonable interesting state for execution. # The interface is designed for extensibility so that addition of new options does not invalidate all existing programs. syz_kvm_setup_cpu$x86(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text_x86, 1]], ntext len[text], flags flags[kvm_setup_flags], opts ptr[in, array[kvm_setup_opt_x86, 0:2]], nopt len[opts]) -syz_kvm_setup_cpu$arm64(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text_arm64, 1]], ntext len[text], flags const[0], opts ptr[in, array[kvm_setup_opt_arm64, 1]], nopt len[opts]) +syz_kvm_setup_cpu$arm64(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[1024], text ptr[in, array[kvm_text_arm64, 1]], ntext len[text], flags const[0], opts ptr[in, array[kvm_setup_opt_arm64, 1]], nopt len[opts]) syz_kvm_setup_cpu$ppc64(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text_ppc64, 1]], ntext len[text], flags flags[kvm_setup_flags_ppc64], opts ptr[in, array[kvm_setup_opt_ppc64, 1]], nopt len[opts]) kvm_num_irqs = 32, 64, 128, 256, 512 # This pseudo-syscall is ARM64-specific. syz_kvm_vgic_v3_setup(fd fd_kvmvm, ncpus intptr[0:4], nirqs flags[kvm_num_irqs]) fd_kvmdev resource kvm_syz_vm[int64] -syz_kvm_setup_syzos_vm(fd fd_kvmvm) kvm_syz_vm +syz_kvm_setup_syzos_vm(fd fd_kvmvm, usermem vma[1024]) kvm_syz_vm syz_kvm_add_vcpu(vm kvm_syz_vm, text ptr[in, kvm_text_arm64], opts ptr[in, array[kvm_setup_opt_arm64, 1]], nopt len[opts]) fd_kvmcpu resource kvm_run_ptr[int64] diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm index 4648c4595..29fcbb864 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) # Perform two uexits. The first one is done via a code blob: # d2802000 mov x0, #0x100 // #256 # f2bbbba0 movk x0, #0xdddd, lsl #16 diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-memwrite b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-memwrite index 69f0b176f..e10a26853 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-memwrite +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-memwrite @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) # Emulate a uexit with the memwrite API command: write 0 at address ARM64_ADDR_UEXIT. # r3 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@memwrite={AUTO, AUTO, @generic={0xdddd0000, 0x100, 0x0, 0x8}}], AUTO}, 0x0, 0x0) diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-msr b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-msr index f242b47d5..b0298d87d 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-msr +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-msr @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) # # 0x603000000013c600 is VBAR_EL1, it aligns the written value on 0x20. # diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-smc b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-smc index d165b2b92..0b9fa62c2 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-smc +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-smc @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) # # KVM_SET_DEVICE_ATTR: group=KVM_ARM_VM_SMCCC_CTRL, attr=KVM_ARM_VM_SMCCC_FILTER # Filter: base=0xef000000, nr_functions=0x1000, action=KVM_SMCCC_FILTER_FWD_TO_USER diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3 b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3 index 07bfa5f10..0c6b0dfc4 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3 +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3 @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) r3 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@irq_setup={AUTO, AUTO, {0x1, 0x20}}], AUTO}, 0x0, 0x0) syz_kvm_vgic_v3_setup(r1, 0x1, 0x100) ioctl$KVM_RUN(r3, AUTO, 0x0) diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-cpu1 b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-cpu1 index 02551142b..a77ae90d0 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-cpu1 +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-cpu1 @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) r3 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@irq_setup={AUTO, AUTO, {0x1, 0x20}}], AUTO}, 0x0, 0x0) r4 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@irq_setup={AUTO, AUTO, {0x1, 0x20}}], AUTO}, 0x0, 0x0) syz_kvm_vgic_v3_setup(r1, 0x2, 0x100) diff --git a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-its b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-its index c1f151c8a..7752a8f6e 100644 --- a/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-its +++ b/sys/linux/test/arm64-syz_kvm_setup_syzos_vm-vgicv3-its @@ -3,7 +3,7 @@ # r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0) r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0) -r2 = syz_kvm_setup_syzos_vm(r1) +r2 = syz_kvm_setup_syzos_vm(r1, &(0x7f0000c00000/0x400000)=nil) r3 = syz_kvm_add_vcpu(r2, &AUTO={0x0, &AUTO=[@irq_setup={AUTO, AUTO, {0x1, 0x20}}], AUTO}, 0x0, 0x0) syz_kvm_vgic_v3_setup(r1, 0x1, 0x100) |
