Skip to content

Commit 42cebab

Browse files
committed
executor, sys/linux, pkg: enable syzos for riscv64
This patch enables syzos for riscv64 and implements the corresponding pseudo syscalls. Pseudo syscalls: - syz_kvm_setup_syzos_vm - syz_kvm_add_vcpu - syz_kvm_assert_syzos_uexit Syzos guest support: - guest_uexit - guest_execute_code - guest_handle_csrr and guest_handle_csrw Test seeds: - riscv64-syz_kvm_setup_syzos_vm - riscv64-syz_kvm_setup_syzos_vm-csrr - riscv64-syz_kvm_setup_syzos_vm-csrw
1 parent a16aed1 commit 42cebab

16 files changed

+671
-89
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(ccmd->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,

0 commit comments

Comments
 (0)