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 : 8 : #if FD_HAS_FLATCC 9 : #include "flatbuffers/generated/flatbuffers_common_builder.h" 10 : #include "flatbuffers/generated/flatbuffers_common_reader.h" 11 : #include "flatbuffers/generated/elf_reader.h" 12 : #include "flatbuffers/generated/elf_builder.h" 13 : #endif 14 : 15 : #define SORT_NAME sort_ulong 16 0 : #define SORT_KEY_T ulong 17 0 : #define SORT_BEFORE(a,b) (a)<(b) 18 : #include "../../../util/tmpl/fd_sort.c" 19 : 20 : #if FD_HAS_FLATCC 21 : 22 : void 23 0 : fd_solfuzz_fb_elf_loader_build_err_effects( fd_solfuzz_runner_t * runner, int err ) { 24 0 : FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_start_as_root)( runner->fb_builder ) ); 25 0 : FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_err_code_add)( runner->fb_builder, (uchar)(-err) ) ); 26 0 : FD_TEST( SOL_COMPAT_NS(ELFLoaderEffects_end_as_root)( runner->fb_builder ) ); 27 0 : } 28 : 29 : int 30 : fd_solfuzz_fb_elf_loader_run( fd_solfuzz_runner_t * runner, 31 0 : void const * input_ ) { 32 0 : SOL_COMPAT_NS(ELFLoaderCtx_table_t) input = fd_type_pun_const( input_ ); 33 : 34 0 : fd_spad_t * spad = runner->spad; 35 0 : flatbuffers_uint8_vec_t elf_bin_ = SOL_COMPAT_NS(ELFLoaderCtx_elf_data( input )); 36 0 : uchar const * elf_bin = (uchar const*)elf_bin_; 37 0 : ulong elf_sz = flatbuffers_uint8_vec_len( elf_bin_ ); 38 : 39 : /* Restore feature set */ 40 0 : fd_features_t feature_set = {0}; 41 0 : fd_solfuzz_fb_restore_features( &feature_set, SOL_COMPAT_NS(ELFLoaderCtx_features( input ))); 42 : 43 0 : fd_sbpf_loader_config_t config = { 44 0 : .elf_deploy_checks = SOL_COMPAT_NS(ELFLoaderCtx_deploy_checks( input )), 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 : fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); 56 0 : return SOL_COMPAT_V2_SUCCESS; 57 0 : } 58 : 59 : /* Set up loading context */ 60 0 : void * rodata = fd_spad_alloc_check( spad, FD_SBPF_PROG_RODATA_ALIGN, info.bin_sz ); 61 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 ); 62 0 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() )); 63 0 : void * rodata_scratch = fd_spad_alloc_check( spad, 1UL, elf_sz ); 64 : 65 : /* Register syscalls given the active feature set. We can pass in an 66 : arbitrary slot as its just used to check if features should be 67 : active or not. */ 68 0 : FD_TEST( !fd_vm_syscall_register_slot( syscalls, UINT_MAX, &feature_set, !!config.elf_deploy_checks ) ); 69 : 70 : /* Load */ 71 0 : err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config, rodata_scratch, elf_sz ); 72 0 : if( err ) { 73 0 : fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); 74 0 : return SOL_COMPAT_V2_SUCCESS; 75 0 : } 76 : 77 : /**** Capture effects ****/ 78 : 79 : /* Error code */ 80 0 : uchar out_err_code = FD_SBPF_ELF_SUCCESS; 81 : 82 : /* Rodata */ 83 0 : ulong out_rodata_hash_u64 = fd_hash( 0UL, prog->rodata, prog->rodata_sz ); 84 0 : SOL_COMPAT_NS(XXHash_t) out_rodata_hash; 85 0 : fd_memcpy( out_rodata_hash.hash, &out_rodata_hash_u64, sizeof(ulong) ); 86 : 87 : /* Text count */ 88 0 : ulong out_text_cnt = prog->info.text_cnt; 89 : 90 : /* Text off */ 91 0 : ulong out_text_off = prog->info.text_off; 92 : 93 : /* Entry PC */ 94 0 : ulong out_entry_pc = prog->entry_pc; 95 : 96 : /* Calldests */ 97 0 : ulong max_out_calldests_cnt = 1UL + ( prog->calldests ? fd_sbpf_calldests_cnt( prog->calldests ) : 0UL ); 98 0 : ulong * tmp_out_calldests = fd_spad_alloc_check( spad, alignof(ulong), sizeof(ulong)*max_out_calldests_cnt ); 99 0 : ulong out_calldests_cnt = 0UL; 100 : 101 : /* Add the entrypoint to the calldests */ 102 0 : tmp_out_calldests[out_calldests_cnt++] = prog->entry_pc; 103 : 104 : /* Add the rest of the calldests */ 105 0 : if( FD_LIKELY( prog->calldests ) ) { 106 0 : for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests); 107 0 : !fd_sbpf_calldests_const_iter_done(target_pc); 108 0 : target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) { 109 0 : if( FD_LIKELY( target_pc!=prog->entry_pc ) ) { 110 0 : tmp_out_calldests[out_calldests_cnt++] = target_pc; 111 0 : } 112 0 : } 113 0 : } 114 : 115 : /* Sort the calldests in ascending order */ 116 0 : sort_ulong_inplace( tmp_out_calldests, out_calldests_cnt ); 117 : 118 : /* Create output calldests vector */ 119 0 : ulong out_calldests_hash_u64 = fd_hash( 0UL, tmp_out_calldests, sizeof(ulong) * out_calldests_cnt ); 120 0 : SOL_COMPAT_NS(XXHash_t) out_calldests_hash; 121 0 : fd_memcpy( out_calldests_hash.hash, &out_calldests_hash_u64, sizeof(ulong) ); 122 : 123 : /* Build effects */ 124 0 : 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 ); 125 : 126 0 : return SOL_COMPAT_V2_SUCCESS; 127 0 : } 128 : 129 : #endif /* FD_HAS_FLATCC */