Line data Source code
1 : #include "fd_solfuzz.h"
2 : #include "fd_solfuzz_private.h"
3 : #include "generated/elf.pb.h"
4 : #include "../../../ballet/sbpf/fd_sbpf_loader.h"
5 : #include "../program/fd_bpf_loader_program.h"
6 : #include "../../vm/fd_vm_base.h"
7 :
8 : #define SORT_NAME sort_ulong
9 0 : #define SORT_KEY_T ulong
10 0 : #define SORT_BEFORE(a,b) (a)<(b)
11 : #include "../../../util/tmpl/fd_sort.c"
12 :
13 : ulong
14 : fd_solfuzz_elf_loader_run( fd_solfuzz_runner_t * runner,
15 : void const * input_,
16 : void ** output_,
17 : void * output_buf,
18 0 : ulong output_bufsz ) {
19 0 : fd_exec_test_elf_loader_ctx_t const * input = fd_type_pun_const( input_ );
20 0 : fd_exec_test_elf_loader_effects_t ** output = fd_type_pun( output_ );
21 :
22 0 : fd_sbpf_elf_info_t info;
23 0 : fd_spad_t * spad = runner->spad;
24 :
25 0 : if( FD_UNLIKELY( !input->has_elf ) ) {
26 0 : return 0UL;
27 0 : }
28 :
29 : /* Occasionally testing elf_sz = 0 and NULL elf_bin */
30 0 : ulong elf_sz = 0UL;
31 0 : void * elf_bin = NULL;
32 0 : if( FD_LIKELY( input->elf.data ) ) {
33 0 : elf_sz = input->elf.data->size;
34 0 : elf_bin = input->elf.data->bytes;
35 0 : }
36 :
37 : // Allocate space for captured effects
38 0 : ulong output_end = (ulong)output_buf + output_bufsz;
39 0 : FD_SCRATCH_ALLOC_INIT( l, output_buf );
40 :
41 0 : fd_exec_test_elf_loader_effects_t * elf_effects =
42 0 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_elf_loader_effects_t),
43 0 : sizeof (fd_exec_test_elf_loader_effects_t) );
44 0 : if( FD_UNLIKELY( _l > output_end ) ) {
45 : /* return 0 on fuzz-specific failures */
46 0 : return 0UL;
47 0 : }
48 0 : fd_memset( elf_effects, 0, sizeof(fd_exec_test_elf_loader_effects_t) );
49 :
50 : /* wrap the loader code in do-while(0) block so that we can exit
51 : immediately if execution fails at any point */
52 0 : int err = FD_SBPF_ELF_SUCCESS;
53 0 : do{
54 0 : fd_features_t feature_set = {0};
55 0 : fd_runtime_fuzz_restore_features( &feature_set, &input->features );
56 :
57 0 : fd_sbpf_loader_config_t config = {
58 0 : .elf_deploy_checks = input->deploy_checks,
59 0 : };
60 0 : fd_bpf_get_sbpf_versions(
61 0 : &config.sbpf_min_version,
62 0 : &config.sbpf_max_version,
63 0 : UINT_MAX,
64 0 : &feature_set );
65 :
66 0 : err = fd_sbpf_elf_peek( &info, elf_bin, elf_sz, &config );
67 0 : if( FD_UNLIKELY( err ) ) {
68 0 : break;
69 0 : }
70 :
71 0 : void * rodata = fd_spad_alloc_check( spad, FD_SBPF_PROG_RODATA_ALIGN, info.bin_sz );
72 0 : fd_sbpf_program_t * prog = fd_sbpf_program_new( fd_spad_alloc_check( spad, fd_sbpf_program_align(), fd_sbpf_program_footprint( &info ) ), &info, rodata );
73 0 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() ));
74 :
75 : /* Register any syscalls given the active feature set */
76 0 : fd_vm_syscall_register_slot(
77 0 : syscalls,
78 0 : UINT_MAX /* Arbitrary slot, doesn't matter */,
79 0 : &feature_set,
80 0 : !!config.elf_deploy_checks );
81 :
82 0 : err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config );
83 0 : if( FD_UNLIKELY( err ) ) {
84 0 : break;
85 0 : }
86 :
87 0 : fd_memset( elf_effects, 0, sizeof(fd_exec_test_elf_loader_effects_t) );
88 0 : elf_effects->rodata_sz = prog->rodata_sz;
89 :
90 : // Load rodata section
91 0 : elf_effects->rodata = FD_SCRATCH_ALLOC_APPEND(l, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( prog->rodata_sz ));
92 0 : if( FD_UNLIKELY( _l > output_end ) ) {
93 0 : return 0UL;
94 0 : }
95 0 : elf_effects->rodata->size = (pb_size_t) prog->rodata_sz;
96 0 : fd_memcpy( elf_effects->rodata->bytes, prog->rodata, prog->rodata_sz );
97 :
98 0 : elf_effects->text_cnt = prog->info.text_cnt;
99 0 : elf_effects->text_off = prog->info.text_off;
100 0 : elf_effects->entry_pc = prog->entry_pc;
101 :
102 0 : pb_size_t max_calldests_sz = 1U;
103 0 : if( FD_LIKELY( prog->calldests ) ) {
104 0 : max_calldests_sz += (pb_size_t)fd_sbpf_calldests_cnt( prog->calldests);
105 0 : }
106 :
107 0 : elf_effects->calldests = FD_SCRATCH_ALLOC_APPEND(l, 8UL, max_calldests_sz * sizeof(uint64_t));
108 0 : if( FD_UNLIKELY( _l > output_end ) ) {
109 0 : return 0UL;
110 0 : }
111 :
112 : /* Add the entrypoint to the calldests */
113 0 : elf_effects->calldests[elf_effects->calldests_count++] = prog->entry_pc;
114 :
115 : /* Add the rest of the calldests */
116 0 : if( FD_LIKELY( prog->calldests ) ) {
117 0 : for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests);
118 0 : !fd_sbpf_calldests_const_iter_done(target_pc);
119 0 : target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) {
120 0 : if( FD_LIKELY( target_pc!=prog->entry_pc ) ) {
121 0 : elf_effects->calldests[elf_effects->calldests_count++] = target_pc;
122 0 : }
123 0 : }
124 0 : }
125 :
126 : /* Sort the calldests in ascending order */
127 0 : sort_ulong_inplace( elf_effects->calldests, elf_effects->calldests_count );
128 0 : } while(0);
129 :
130 0 : elf_effects->error = -err;
131 0 : ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
132 :
133 0 : *output = elf_effects;
134 0 : return actual_end - (ulong) output_buf;
135 0 : }
|