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 : #include "../../progcache/fd_prog_load.h"
8 :
9 : #define SORT_NAME sort_ulong
10 0 : #define SORT_KEY_T ulong
11 0 : #define SORT_BEFORE(a,b) (a)<(b)
12 : #include "../../../util/tmpl/fd_sort.c"
13 :
14 : ulong
15 : fd_solfuzz_elf_loader_run( fd_solfuzz_runner_t * runner,
16 : void const * input_,
17 : void ** output_,
18 : void * output_buf,
19 0 : ulong output_bufsz ) {
20 0 : fd_exec_test_elf_loader_ctx_t const * input = fd_type_pun_const( input_ );
21 0 : fd_exec_test_elf_loader_effects_t ** output = fd_type_pun( output_ );
22 :
23 0 : fd_sbpf_elf_info_t info;
24 0 : fd_spad_t * spad = runner->spad;
25 :
26 0 : if( FD_UNLIKELY( !input->has_elf ) ) {
27 0 : return 0UL;
28 0 : }
29 :
30 : /* Occasionally testing elf_sz = 0 and NULL elf_bin */
31 0 : ulong elf_sz = 0UL;
32 0 : void * elf_bin = NULL;
33 0 : if( FD_LIKELY( input->elf.data ) ) {
34 0 : elf_sz = input->elf.data->size;
35 0 : elf_bin = input->elf.data->bytes;
36 0 : }
37 :
38 : // Allocate space for captured effects
39 0 : ulong output_end = (ulong)output_buf + output_bufsz;
40 0 : FD_SCRATCH_ALLOC_INIT( l, output_buf );
41 :
42 0 : fd_exec_test_elf_loader_effects_t * elf_effects =
43 0 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_elf_loader_effects_t),
44 0 : sizeof (fd_exec_test_elf_loader_effects_t) );
45 0 : if( FD_UNLIKELY( _l > output_end ) ) {
46 : /* return 0 on fuzz-specific failures */
47 0 : return 0UL;
48 0 : }
49 0 : fd_memset( elf_effects, 0, sizeof(fd_exec_test_elf_loader_effects_t) );
50 :
51 : /* wrap the loader code in do-while(0) block so that we can exit
52 : immediately if execution fails at any point */
53 0 : int err = FD_SBPF_ELF_SUCCESS;
54 0 : do{
55 0 : fd_features_t feature_set = {0};
56 0 : fd_runtime_fuzz_restore_features( &feature_set, &input->features );
57 :
58 0 : fd_sbpf_loader_config_t config = {
59 0 : .elf_deploy_checks = input->deploy_checks,
60 0 : };
61 :
62 0 : fd_prog_versions_t versions = fd_prog_versions( &feature_set, UINT_MAX );
63 0 : config.sbpf_min_version = versions.min_sbpf_version;
64 0 : config.sbpf_max_version = versions.max_sbpf_version;
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 : void * scratch = fd_spad_alloc( spad, 1UL, elf_sz );
83 0 : err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config, scratch, elf_sz );
84 0 : if( FD_UNLIKELY( err ) ) {
85 0 : break;
86 0 : }
87 :
88 0 : fd_memset( elf_effects, 0, sizeof(fd_exec_test_elf_loader_effects_t) );
89 0 : elf_effects->rodata_sz = prog->rodata_sz;
90 :
91 : // Load rodata section
92 0 : elf_effects->rodata = FD_SCRATCH_ALLOC_APPEND(l, 8UL, PB_BYTES_ARRAY_T_ALLOCSIZE( prog->rodata_sz ));
93 0 : if( FD_UNLIKELY( _l > output_end ) ) {
94 0 : return 0UL;
95 0 : }
96 0 : elf_effects->rodata->size = (pb_size_t) prog->rodata_sz;
97 0 : fd_memcpy( elf_effects->rodata->bytes, prog->rodata, prog->rodata_sz );
98 :
99 0 : elf_effects->text_cnt = prog->info.text_cnt;
100 0 : elf_effects->text_off = prog->info.text_off;
101 0 : elf_effects->entry_pc = prog->entry_pc;
102 :
103 0 : pb_size_t max_calldests_sz = 1U;
104 0 : if( FD_LIKELY( prog->calldests ) ) {
105 0 : max_calldests_sz += (pb_size_t)fd_sbpf_calldests_cnt( prog->calldests);
106 0 : }
107 :
108 0 : elf_effects->calldests = FD_SCRATCH_ALLOC_APPEND(l, 8UL, max_calldests_sz * sizeof(uint64_t));
109 0 : if( FD_UNLIKELY( _l > output_end ) ) {
110 0 : return 0UL;
111 0 : }
112 :
113 : /* Add the entrypoint to the calldests */
114 0 : elf_effects->calldests[elf_effects->calldests_count++] = prog->entry_pc;
115 :
116 : /* Add the rest of the calldests */
117 0 : if( FD_LIKELY( prog->calldests ) ) {
118 0 : for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests);
119 0 : !fd_sbpf_calldests_const_iter_done(target_pc);
120 0 : target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) {
121 0 : if( FD_LIKELY( target_pc!=prog->entry_pc ) ) {
122 0 : elf_effects->calldests[elf_effects->calldests_count++] = target_pc;
123 0 : }
124 0 : }
125 0 : }
126 :
127 : /* Sort the calldests in ascending order */
128 0 : sort_ulong_inplace( elf_effects->calldests, elf_effects->calldests_count );
129 0 : } while(0);
130 :
131 0 : elf_effects->error = -err;
132 0 : ulong actual_end = FD_SCRATCH_ALLOC_FINI( l, 1UL );
133 :
134 0 : *output = elf_effects;
135 0 : return actual_end - (ulong) output_buf;
136 0 : }
|