|
1 | 1 | #include "fd_solfuzz.h" |
2 | 2 | #include "fd_solfuzz_private.h" |
| 3 | +#include "flatbuffers/generated/flatbuffers_common_builder.h" |
| 4 | +#include "flatbuffers/generated/flatbuffers_common_reader.h" |
3 | 5 | #include "generated/elf.pb.h" |
4 | 6 | #include "../../../ballet/sbpf/fd_sbpf_loader.h" |
5 | 7 | #include "../program/fd_bpf_loader_program.h" |
6 | 8 | #include "../../vm/fd_vm_base.h" |
7 | 9 | #include "../../progcache/fd_prog_load.h" |
8 | 10 |
|
| 11 | +#include "flatbuffers/generated/elf_reader.h" |
| 12 | +#include "flatbuffers/generated/elf_builder.h" |
| 13 | + |
9 | 14 | #define SORT_NAME sort_ulong |
10 | 15 | #define SORT_KEY_T ulong |
11 | 16 | #define SORT_BEFORE(a,b) (a)<(b) |
@@ -134,3 +139,110 @@ fd_solfuzz_pb_elf_loader_run( fd_solfuzz_runner_t * runner, |
134 | 139 | *output = elf_effects; |
135 | 140 | return actual_end - (ulong) output_buf; |
136 | 141 | } |
| 142 | + |
| 143 | +void |
| 144 | +fd_solfuzz_fb_elf_loader_build_err_effects( fd_solfuzz_runner_t * runner, int err ) { |
| 145 | + FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_start_as_root)( runner->fb_builder ) ); |
| 146 | + FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_err_code_add)( runner->fb_builder, (uchar)(-err) ) ); |
| 147 | + FD_TEST( SOL_COMPAT_NS(ELFLoaderEffects_end_as_root)( runner->fb_builder ) ); |
| 148 | +} |
| 149 | + |
| 150 | +int |
| 151 | +fd_solfuzz_fb_elf_loader_run( fd_solfuzz_runner_t * runner, |
| 152 | + void const * input_ ) { |
| 153 | + SOL_COMPAT_NS(ELFLoaderCtx_table_t) input = fd_type_pun_const( input_ ); |
| 154 | + |
| 155 | + fd_spad_t * spad = runner->spad; |
| 156 | + flatbuffers_uint8_vec_t elf_bin_ = SOL_COMPAT_NS(ELFLoaderCtx_elf_data( input )); |
| 157 | + uchar const * elf_bin = (uchar const*)elf_bin_; |
| 158 | + ulong elf_sz = flatbuffers_uint8_vec_len( elf_bin_ ); |
| 159 | + |
| 160 | + /* Restore feature set */ |
| 161 | + fd_features_t feature_set = {0}; |
| 162 | + fd_solfuzz_fb_restore_features( &feature_set, SOL_COMPAT_NS(ELFLoaderCtx_features( input ))); |
| 163 | + |
| 164 | + fd_sbpf_loader_config_t config = { |
| 165 | + .elf_deploy_checks = SOL_COMPAT_NS(ELFLoaderCtx_deploy_checks( input )), |
| 166 | + }; |
| 167 | + |
| 168 | + fd_prog_versions_t versions = fd_prog_versions( &feature_set, UINT_MAX ); |
| 169 | + config.sbpf_min_version = versions.min_sbpf_version; |
| 170 | + config.sbpf_max_version = versions.max_sbpf_version; |
| 171 | + |
| 172 | + /* Peek */ |
| 173 | + fd_sbpf_elf_info_t info; |
| 174 | + int err = fd_sbpf_elf_peek( &info, elf_bin, elf_sz, &config ); |
| 175 | + if( err ) { |
| 176 | + fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); |
| 177 | + return SOL_COMPAT_V2_SUCCESS; |
| 178 | + } |
| 179 | + |
| 180 | + /* Set up loading context */ |
| 181 | + void * rodata = fd_spad_alloc_check( spad, FD_SBPF_PROG_RODATA_ALIGN, info.bin_sz ); |
| 182 | + 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 ); |
| 183 | + fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() )); |
| 184 | + void * rodata_scratch = fd_spad_alloc_check( spad, 1UL, elf_sz ); |
| 185 | + |
| 186 | + /* Register syscalls given the active feature set. We can pass in an |
| 187 | + arbitrary slot as its just used to check if features should be |
| 188 | + active or not. */ |
| 189 | + FD_TEST( !fd_vm_syscall_register_slot( syscalls, UINT_MAX, &feature_set, !!config.elf_deploy_checks ) ); |
| 190 | + |
| 191 | + /* Load */ |
| 192 | + err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config, rodata_scratch, elf_sz ); |
| 193 | + if( err ) { |
| 194 | + fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); |
| 195 | + return SOL_COMPAT_V2_SUCCESS; |
| 196 | + } |
| 197 | + |
| 198 | + /**** Capture effects ****/ |
| 199 | + |
| 200 | + /* Error code */ |
| 201 | + uchar out_err_code = FD_SBPF_ELF_SUCCESS; |
| 202 | + |
| 203 | + /* Rodata */ |
| 204 | + ulong out_rodata_hash_u64 = fd_hash( 0UL, prog->rodata, prog->rodata_sz ); |
| 205 | + SOL_COMPAT_NS(XXHash_t) out_rodata_hash; |
| 206 | + fd_memcpy( out_rodata_hash.hash, &out_rodata_hash_u64, sizeof(ulong) ); |
| 207 | + |
| 208 | + /* Text count */ |
| 209 | + ulong out_text_cnt = prog->info.text_cnt; |
| 210 | + |
| 211 | + /* Text off */ |
| 212 | + ulong out_text_off = prog->info.text_off; |
| 213 | + |
| 214 | + /* Entry PC */ |
| 215 | + ulong out_entry_pc = prog->entry_pc; |
| 216 | + |
| 217 | + /* Calldests */ |
| 218 | + ulong max_out_calldests_cnt = 1UL + ( prog->calldests ? fd_sbpf_calldests_cnt( prog->calldests ) : 0UL ); |
| 219 | + ulong * tmp_out_calldests = fd_spad_alloc_check( spad, alignof(ulong), sizeof(ulong)*max_out_calldests_cnt ); |
| 220 | + ulong out_calldests_cnt = 0UL; |
| 221 | + |
| 222 | + /* Add the entrypoint to the calldests */ |
| 223 | + tmp_out_calldests[out_calldests_cnt++] = prog->entry_pc; |
| 224 | + |
| 225 | + /* Add the rest of the calldests */ |
| 226 | + if( FD_LIKELY( prog->calldests ) ) { |
| 227 | + for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests); |
| 228 | + !fd_sbpf_calldests_const_iter_done(target_pc); |
| 229 | + target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) { |
| 230 | + if( FD_LIKELY( target_pc!=prog->entry_pc ) ) { |
| 231 | + tmp_out_calldests[out_calldests_cnt++] = target_pc; |
| 232 | + } |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + /* Sort the calldests in ascending order */ |
| 237 | + sort_ulong_inplace( tmp_out_calldests, out_calldests_cnt ); |
| 238 | + |
| 239 | + /* Create output calldests vector */ |
| 240 | + ulong out_calldests_hash_u64 = fd_hash( 0UL, tmp_out_calldests, sizeof(ulong) * out_calldests_cnt ); |
| 241 | + SOL_COMPAT_NS(XXHash_t) out_calldests_hash; |
| 242 | + fd_memcpy( out_calldests_hash.hash, &out_calldests_hash_u64, sizeof(ulong) ); |
| 243 | + |
| 244 | + /* Build effects */ |
| 245 | + SOL_COMPAT_NS(ELFLoaderEffects_create_as_root)( runner->fb_builder, out_err_code, &out_rodata_hash, out_text_cnt, out_text_off, out_entry_pc, &out_calldests_hash ); |
| 246 | + |
| 247 | + return SOL_COMPAT_V2_SUCCESS; |
| 248 | +} |
0 commit comments