Line data Source code
1 : #include "fd_solfuzz.h" 2 : #include "fd_solfuzz_private.h" 3 : #include "../../../ballet/sbpf/fd_sbpf_loader.h" 4 : #include "../program/fd_bpf_loader_program.h" 5 : #include "../../vm/fd_vm_base.h" 6 : #include "../../progcache/fd_prog_load.h" 7 : #include "generated/elf.pb.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_pb_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_spad_t * spad = runner->spad; 24 0 : uchar const * elf_bin = input->elf_data ? input->elf_data->bytes : NULL; 25 0 : ulong elf_sz = input->elf_data ? input->elf_data->size : 0UL; 26 : 27 : /* Allocate effects struct out of the caller's output buffer */ 28 0 : ulong output_end = (ulong)output_buf + output_bufsz; 29 0 : FD_SCRATCH_ALLOC_INIT( l, output_buf ); 30 0 : fd_exec_test_elf_loader_effects_t * effects = 31 0 : FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_exec_test_elf_loader_effects_t), 32 0 : sizeof (fd_exec_test_elf_loader_effects_t) ); 33 0 : if( FD_UNLIKELY( _l > output_end ) ) return 0UL; 34 0 : fd_memset( effects, 0, sizeof(fd_exec_test_elf_loader_effects_t) ); 35 : 36 : /* Restore feature set */ 37 0 : fd_features_t feature_set = {0}; 38 0 : if( FD_UNLIKELY( input->has_features && 39 0 : !fd_solfuzz_pb_restore_features( &feature_set, &input->features ) ) ) { 40 0 : return 0UL; 41 0 : } 42 : 43 0 : fd_sbpf_loader_config_t config = { 44 0 : .elf_deploy_checks = input->deploy_checks, 45 0 : }; 46 : 47 0 : fd_prog_versions_t versions = fd_prog_versions( &feature_set, UINT_MAX ); 48 0 : config.sbpf_min_version = versions.min_sbpf_version; 49 0 : config.sbpf_max_version = versions.max_sbpf_version; 50 : 51 : /* Peek */ 52 0 : fd_sbpf_elf_info_t info; 53 0 : int err = fd_sbpf_elf_peek( &info, elf_bin, elf_sz, &config ); 54 0 : if( err ) { 55 0 : effects->err_code = (uint)(-err); 56 0 : *output = effects; 57 0 : return FD_SCRATCH_ALLOC_FINI( l, 1UL ) - (ulong)output_buf; 58 0 : } 59 : 60 : /* Set up loading context */ 61 0 : void * rodata = fd_spad_alloc_check( spad, FD_SBPF_PROG_RODATA_ALIGN, info.bin_sz ); 62 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 ); 63 0 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() )); 64 0 : void * rodata_scratch = fd_spad_alloc_check( spad, 1UL, elf_sz ); 65 : 66 : /* Register syscalls given the active feature set. We can pass in an 67 : arbitrary slot as its just used to check if features should be 68 : active or not. */ 69 0 : FD_TEST( !fd_vm_syscall_register_slot( syscalls, UINT_MAX, &feature_set, !!config.elf_deploy_checks ) ); 70 : 71 : /* Load */ 72 0 : err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config, rodata_scratch, elf_sz ); 73 0 : if( err ) { 74 0 : effects->err_code = (uint)(-err); 75 0 : *output = effects; 76 0 : return FD_SCRATCH_ALLOC_FINI( l, 1UL ) - (ulong)output_buf; 77 0 : } 78 : 79 : /**** Capture effects ****/ 80 : 81 0 : effects->err_code = FD_SBPF_ELF_SUCCESS; 82 0 : effects->rodata_hash = fd_hash( 0UL, prog->rodata, prog->rodata_sz ); 83 0 : effects->text_cnt = prog->info.text_cnt; 84 0 : effects->text_off = fd_sbpf_enable_stricter_elf_headers_enabled( prog->info.sbpf_version ) ? 0UL : prog->info.text_off; 85 0 : effects->entry_pc = prog->entry_pc; 86 : 87 : /* Calldests */ 88 0 : ulong max_out_calldests_cnt = 1UL + ( prog->calldests ? fd_sbpf_calldests_cnt( prog->calldests ) : 0UL ); 89 0 : ulong * tmp_out_calldests = fd_spad_alloc_check( spad, alignof(ulong), sizeof(ulong)*max_out_calldests_cnt ); 90 0 : ulong out_calldests_cnt = 0UL; 91 : 92 0 : if( !fd_sbpf_enable_stricter_elf_headers_enabled( prog->info.sbpf_version ) ) { 93 : /* Add the entrypoint to the calldests */ 94 0 : tmp_out_calldests[out_calldests_cnt++] = prog->entry_pc; 95 : 96 : /* Add the rest of the calldests */ 97 0 : if( FD_LIKELY( prog->calldests ) ) { 98 0 : for( ulong target_pc=fd_sbpf_calldests_const_iter_init( prog->calldests ); 99 0 : !fd_sbpf_calldests_const_iter_done( target_pc ); 100 0 : target_pc=fd_sbpf_calldests_const_iter_next( prog->calldests, target_pc ) ) { 101 0 : if( FD_LIKELY( target_pc!=prog->entry_pc ) ) { 102 0 : tmp_out_calldests[out_calldests_cnt++] = target_pc; 103 0 : } 104 0 : } 105 0 : } 106 0 : } 107 : 108 : /* Sort the calldests in ascending order */ 109 0 : sort_ulong_inplace( tmp_out_calldests, out_calldests_cnt ); 110 : 111 : /* Compute calldests hash */ 112 0 : effects->calldests_hash = fd_hash( 0UL, tmp_out_calldests, sizeof(ulong) * out_calldests_cnt ); 113 : 114 0 : *output = effects; 115 0 : return FD_SCRATCH_ALLOC_FINI( l, 1UL ) - (ulong)output_buf; 116 0 : }