Skip to content

Commit 99a3c84

Browse files
committed
fix
1 parent 4fe8ded commit 99a3c84

File tree

9 files changed

+93
-134
lines changed

9 files changed

+93
-134
lines changed

executor/common_kvm_amd64.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ static void install_syzos_code(void* host_mem, size_t mem_size)
11261126
{
11271127
size_t size = (char*)&__stop_guest - (char*)&__start_guest;
11281128
if (size > mem_size)
1129-
fail("SyzOS size exceeds guest memory");
1129+
fail("SYZOS size exceeds guest memory");
11301130
memcpy(host_mem, &__start_guest, size);
11311131
}
11321132

executor/common_kvm_amd64_syzos.h

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66

77
// This file provides guest code running inside the AMD64 KVM.
88

9-
#include "common_kvm_syzos.h"
10-
#include "kvm.h"
119
#include <linux/kvm.h>
1210
#include <stdbool.h>
1311

12+
#include "common_kvm_syzos.h"
13+
#include "kvm.h"
14+
1415
// There are no particular rules to assign numbers here, but changing them will
1516
// result in losing some existing reproducers. Therefore, we try to leave spaces
1617
// between unrelated IDs.
@@ -43,16 +44,6 @@ typedef enum {
4344
SYZOS_API_STOP, // Must be the last one
4445
} syzos_api_id;
4546

46-
struct api_call_header {
47-
uint64 call;
48-
uint64 size;
49-
};
50-
51-
struct api_call_uexit {
52-
struct api_call_header header;
53-
uint64 exit_code;
54-
};
55-
5647
struct api_call_code {
5748
struct api_call_header header;
5849
uint8 insns[];
@@ -70,26 +61,6 @@ struct api_call_cpuid {
7061
uint32 ecx;
7162
};
7263

73-
struct api_call_1 {
74-
struct api_call_header header;
75-
uint64 arg;
76-
};
77-
78-
struct api_call_2 {
79-
struct api_call_header header;
80-
uint64 args[2];
81-
};
82-
83-
struct api_call_3 {
84-
struct api_call_header header;
85-
uint64 args[3];
86-
};
87-
88-
struct api_call_5 {
89-
struct api_call_header header;
90-
uint64 args[5];
91-
};
92-
9364
// This struct must match the push/pop order in nested_vm_exit_handler_intel_asm().
9465
struct l2_guest_regs {
9566
uint64 rax, rbx, rcx, rdx, rsi, rdi, rbp;
@@ -165,8 +136,8 @@ __attribute__((naked)) GUEST_CODE static void uexit_irq_handler()
165136
// TODO(glider): executor/style_test.go insists that single-line compound statements should not
166137
// be used e.g. in the following case:
167138
// if (call == SYZOS_API_UEXIT) {
168-
// struct api_call_uexit* ucmd = (struct api_call_uexit*)cmd;
169-
// guest_uexit(ucmd->exit_code);
139+
// struct api_call_1* ccmd = (struct api_call_1*)cmd;
140+
// guest_uexit(ucmd->arg);
170141
// } else if (call == SYZOS_API_WR_CRN) {
171142
// guest_handle_wr_crn((struct api_call_2*)cmd); // Style check fails here
172143
// }
@@ -188,8 +159,8 @@ guest_main(uint64 size, uint64 cpu)
188159
volatile uint64 call = cmd->call;
189160
if (call == SYZOS_API_UEXIT) {
190161
// Issue a user exit.
191-
struct api_call_uexit* ucmd = (struct api_call_uexit*)cmd;
192-
guest_uexit(ucmd->exit_code);
162+
struct api_call_1* ccmd = (struct api_call_1*)cmd;
163+
guest_uexit(ccmd->arg);
193164
} else if (call == SYZOS_API_CODE) {
194165
// Execute an instruction blob.
195166
struct api_call_code* ccmd = (struct api_call_code*)cmd;

executor/common_kvm_arm64.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ static void vm_set_user_memory_region(int vmfd, uint32 slot, uint32 flags, uint6
7070
#define ADRP_OPCODE 0x90000000
7171
#define ADRP_OPCODE_MASK 0x9f000000
7272

73-
// Code loading SyzOS into guest memory does not handle data relocations (see
74-
// https://github.com/google/syzkaller/issues/5565), so SyzOS will crash soon after encountering an
73+
// Code loading SYZOS into guest memory does not handle data relocations (see
74+
// https://github.com/google/syzkaller/issues/5565), so SYZOS will crash soon after encountering an
7575
// ADRP instruction. Detect these instructions to catch regressions early.
7676
// The most common reason for using data relocaions is accessing global variables and constants.
7777
// Sometimes the compiler may choose to emit a read-only constant to zero-initialize a structure
@@ -81,15 +81,15 @@ static void validate_guest_code(void* mem, size_t size)
8181
uint32* insns = (uint32*)mem;
8282
for (size_t i = 0; i < size / 4; i++) {
8383
if ((insns[i] & ADRP_OPCODE_MASK) == ADRP_OPCODE)
84-
fail("ADRP instruction detected in SyzOS, exiting");
84+
fail("ADRP instruction detected in SYZOS, exiting");
8585
}
8686
}
8787

8888
static void install_syzos_code(void* host_mem, size_t mem_size)
8989
{
9090
size_t size = (char*)&__stop_guest - (char*)&__start_guest;
9191
if (size > mem_size)
92-
fail("SyzOS size exceeds guest memory");
92+
fail("SYZOS size exceeds guest memory");
9393
memcpy(host_mem, &__start_guest, size);
9494
validate_guest_code(host_mem, size);
9595
}

executor/common_kvm_arm64_syzos.h

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66

77
// This file provides guest code running inside the ARM64 KVM.
88

9-
#include "common_kvm_syzos.h"
10-
#include "kvm.h"
119
#include <linux/kvm.h>
1210
#include <stdbool.h>
1311

12+
#include "common_kvm_syzos.h"
13+
#include "kvm.h"
14+
1415
// Compilers will eagerly try to transform the switch statement in guest_main()
1516
// into a jump table, unless the cases are sparse enough.
1617
// We use prime numbers multiplied by 10 to prevent this behavior.
@@ -31,31 +32,6 @@ typedef enum {
3132
SYZOS_API_STOP, // Must be the last one
3233
} syzos_api_id;
3334

34-
struct api_call_header {
35-
uint64 call;
36-
uint64 size;
37-
};
38-
39-
struct api_call_uexit {
40-
struct api_call_header header;
41-
uint64 exit_code;
42-
};
43-
44-
struct api_call_1 {
45-
struct api_call_header header;
46-
uint64 arg;
47-
};
48-
49-
struct api_call_2 {
50-
struct api_call_header header;
51-
uint64 args[2];
52-
};
53-
54-
struct api_call_3 {
55-
struct api_call_header header;
56-
uint64 args[3];
57-
};
58-
5935
struct api_call_code {
6036
struct api_call_header header;
6137
uint32 insns[];
@@ -127,8 +103,8 @@ guest_main(uint64 size, uint64 cpu)
127103
return;
128104
switch (cmd->call) {
129105
case SYZOS_API_UEXIT: {
130-
struct api_call_uexit* ucmd = (struct api_call_uexit*)cmd;
131-
guest_uexit(ucmd->exit_code);
106+
struct api_call_1* ccmd = (struct api_call_1*)cmd;
107+
guest_uexit(ccmd->arg);
132108
break;
133109
}
134110
case SYZOS_API_CODE: {
@@ -1219,7 +1195,7 @@ GUEST_CODE static void its_send_sync_cmd(uint64 cmdq_base, uint32 vcpu_id)
12191195
}
12201196

12211197
// This function is carefully written in a way that prevents jump table emission.
1222-
// SyzOS cannot reference global constants, and compilers are very eager to generate a jump table
1198+
// SYZOS cannot reference global constants, and compilers are very eager to generate a jump table
12231199
// for a switch over GITS commands.
12241200
// To work around that, we replace the switch statement with a series of if statements.
12251201
// In addition, cmd->type is stored in a volatile variable, so that it is read on each if statement,

executor/common_kvm_riscv64.h

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88

99
// Implementation of syz_kvm_setup_cpu pseudo-syscall.
1010

11-
#include "common_kvm.h"
12-
#include "kvm.h"
1311
#include <stdint.h>
1412
#include <string.h>
1513
#include <sys/ioctl.h>
1614

15+
#include "common_kvm.h"
16+
#include "kvm.h"
17+
1718
#if SYZ_EXECUTOR || __NR_syz_kvm_setup_syzos_vm || __NR_syz_kvm_add_vcpu
1819
#include "common_kvm_riscv64_syzos.h"
1920
#endif
@@ -101,6 +102,10 @@ struct kvm_text {
101102
#endif
102103

103104
#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu || __NR_syz_kvm_setup_syzos_vm || __NR_syz_kvm_add_vcpu
105+
// The exception vector table setup and SBI invocation here follow the
106+
// implementation in Linux kselftest KVM RISC-V tests.
107+
// See https://elixir.bootlin.com/linux/v6.19-rc5/source/tools/testing/selftests/kvm/lib/riscv/processor.c#L337 .
108+
104109
#define KVM_RISCV_SELFTESTS_SBI_EXT 0x08FFFFFF
105110
#define KVM_RISCV_SELFTESTS_SBI_UNEXP 1
106111

@@ -116,14 +121,14 @@ struct sbiret sbi_ecall(unsigned long arg0, unsigned long arg1,
116121
{
117122
struct sbiret ret;
118123

119-
register uintptr_t a0 asm("a0") = (uintptr_t)(arg0);
120-
register uintptr_t a1 asm("a1") = (uintptr_t)(arg1);
121-
register uintptr_t a2 asm("a2") = (uintptr_t)(arg2);
122-
register uintptr_t a3 asm("a3") = (uintptr_t)(arg3);
123-
register uintptr_t a4 asm("a4") = (uintptr_t)(arg4);
124-
register uintptr_t a5 asm("a5") = (uintptr_t)(arg5);
125-
register uintptr_t a6 asm("a6") = (uintptr_t)(fid);
126-
register uintptr_t a7 asm("a7") = (uintptr_t)(ext);
124+
register unsigned long a0 asm("a0") = arg0;
125+
register unsigned long a1 asm("a1") = arg1;
126+
register unsigned long a2 asm("a2") = arg2;
127+
register unsigned long a3 asm("a3") = arg3;
128+
register unsigned long a4 asm("a4") = arg4;
129+
register unsigned long a5 asm("a5") = arg5;
130+
register unsigned long a6 asm("a6") = fid;
131+
register unsigned long a7 asm("a7") = ext;
127132
asm volatile("ecall"
128133
: "+r"(a0), "+r"(a1)
129134
: "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7)
@@ -143,8 +148,6 @@ __attribute__((used)) __attribute((__aligned__(16))) static void guest_unexp_tra
143148
#endif
144149

145150
#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu
146-
// Define the starting physical address for the guest code.
147-
#define CODE_START 0x80000000ULL
148151

149152
// syz_kvm_setup_cpu$riscv64(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text_riscv64, 1]], ntext len[text], flags const[0], opts ptr[in, array[kvm_setup_opt_riscv64, 1]], nopt len[opts])
150153
static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7)
@@ -163,7 +166,7 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
163166
struct kvm_userspace_memory_region mem = {
164167
.slot = (unsigned int)i,
165168
.flags = 0,
166-
.guest_phys_addr = CODE_START + i * page_size,
169+
.guest_phys_addr = RISCV64_ADDR_USER_CODE + i * page_size,
167170
.memory_size = page_size,
168171
.userspace_addr =
169172
(uintptr_t)(host_mem + i * page_size),
@@ -185,10 +188,10 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
185188

186189
// Initialize VCPU registers.
187190
// Set PC (program counter) to start of code.
188-
if (kvm_set_reg(cpufd, RISCV_CORE_REG(CORE_PC), CODE_START))
191+
if (kvm_set_reg(cpufd, RISCV_CORE_REG(CORE_PC), RISCV64_ADDR_USER_CODE))
189192
return -1;
190193
// Set SP (stack pointer) at end of memory, reserving space for stack.
191-
unsigned long stack_top = CODE_START + guest_mem_size - page_size;
194+
unsigned long stack_top = RISCV64_ADDR_USER_CODE + guest_mem_size - page_size;
192195
if (kvm_set_reg(cpufd, RISCV_CORE_REG(CORE_SP), stack_top))
193196
return -1;
194197
// Set privilege mode to S-mode.
@@ -199,7 +202,7 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
199202
if (kvm_set_reg(cpufd, RISCV_CSR_REG(CSR_SSTATUS), sstatus))
200203
return -1;
201204
// Set STVEC.
202-
unsigned long stvec = CODE_START + page_size;
205+
unsigned long stvec = RISCV64_ADDR_USER_CODE + page_size;
203206
if (kvm_set_reg(cpufd, RISCV_CSR_REG(CSR_STVEC), stvec))
204207
return -1;
205208
// Set GP.
@@ -276,8 +279,8 @@ static void vm_set_user_memory_region(int vmfd, uint32 slot, uint32 flags, uint6
276279
#define AUIPC_OPCODE 0x17
277280
#define AUIPC_OPCODE_MASK 0x7f
278281

279-
// Code loading SyzOS into guest memory does not handle data relocations (see
280-
// https://github.com/google/syzkaller/issues/5565), so SyzOS will crash soon after encountering an
282+
// Code loading SYZOS into guest memory does not handle data relocations (see
283+
// https://github.com/google/syzkaller/issues/5565), so SYZOS will crash soon after encountering an
281284
// AUIPC instruction. Detect these instructions to catch regressions early.
282285
// The most common reason for using data relocaions is accessing global variables and constants.
283286
// Sometimes the compiler may choose to emit a read-only constant to zero-initialize a structure
@@ -287,15 +290,15 @@ static void validate_guest_code(void* mem, size_t size)
287290
uint32* insns = (uint32*)mem;
288291
for (size_t i = 0; i < size / 4; i++) {
289292
if ((insns[i] & AUIPC_OPCODE_MASK) == AUIPC_OPCODE)
290-
fail("AUIPC instruction detected in SyzOS, exiting");
293+
fail("AUIPC instruction detected in SYZOS, exiting");
291294
}
292295
}
293296

294297
static void install_syzos_code(void* host_mem, size_t mem_size)
295298
{
296299
size_t size = (char*)&__stop_guest - (char*)&__start_guest;
297300
if (size > mem_size)
298-
fail("SyzOS size exceeds guest memory");
301+
fail("SYZOS size exceeds guest memory");
299302
memcpy(host_mem, &__start_guest, size);
300303
validate_guest_code(host_mem, size);
301304
}

0 commit comments

Comments
 (0)