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 817104 : #define SORT_KEY_T ulong 17 1108611 : #define SORT_BEFORE(a,b) (a)<(b) 18 : #include "../../../util/tmpl/fd_sort.c" 19 : 20 : #if FD_HAS_FLATCC 21 : 22 : void 23 210 : fd_solfuzz_fb_elf_loader_build_err_effects( fd_solfuzz_runner_t * runner, int err ) { 24 210 : FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_start_as_root)( runner->fb_builder ) ); 25 210 : FD_TEST( !SOL_COMPAT_NS(ELFLoaderEffects_err_code_add)( runner->fb_builder, (uchar)(-err) ) ); 26 210 : FD_TEST( SOL_COMPAT_NS(ELFLoaderEffects_end_as_root)( runner->fb_builder ) ); 27 210 : } 28 : 29 : int 30 : fd_solfuzz_fb_elf_loader_run( fd_solfuzz_runner_t * runner, 31 950 : void const * input_ ) { 32 950 : SOL_COMPAT_NS(ELFLoaderCtx_table_t) input = fd_type_pun_const( input_ ); 33 : 34 950 : fd_spad_t * spad = runner->spad; 35 950 : flatbuffers_uint8_vec_t elf_bin_ = SOL_COMPAT_NS(ELFLoaderCtx_elf_data( input )); 36 950 : uchar const * elf_bin = (uchar const*)elf_bin_; 37 950 : ulong elf_sz = flatbuffers_uint8_vec_len( elf_bin_ ); 38 : 39 : /* Restore feature set */ 40 950 : fd_features_t feature_set = {0}; 41 950 : fd_solfuzz_fb_restore_features( &feature_set, SOL_COMPAT_NS(ELFLoaderCtx_features( input ))); 42 : 43 950 : fd_sbpf_loader_config_t config = { 44 950 : .elf_deploy_checks = SOL_COMPAT_NS(ELFLoaderCtx_deploy_checks( input )), 45 950 : }; 46 : 47 950 : fd_prog_versions_t versions = fd_prog_versions( &feature_set, UINT_MAX ); 48 950 : config.sbpf_min_version = versions.min_sbpf_version; 49 950 : config.sbpf_max_version = versions.max_sbpf_version; 50 : 51 : /* Peek */ 52 950 : fd_sbpf_elf_info_t info; 53 950 : int err = fd_sbpf_elf_peek( &info, elf_bin, elf_sz, &config ); 54 950 : if( err ) { 55 154 : fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); 56 154 : return SOL_COMPAT_V2_SUCCESS; 57 154 : } 58 : 59 : /* Set up loading context */ 60 796 : void * rodata = fd_spad_alloc_check( spad, FD_SBPF_PROG_RODATA_ALIGN, info.bin_sz ); 61 796 : 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 796 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_new( fd_spad_alloc_check( spad, fd_sbpf_syscalls_align(), fd_sbpf_syscalls_footprint() )); 63 796 : 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 796 : FD_TEST( !fd_vm_syscall_register_slot( syscalls, UINT_MAX, &feature_set, !!config.elf_deploy_checks ) ); 69 : 70 : /* Load */ 71 796 : err = fd_sbpf_program_load( prog, elf_bin, elf_sz, syscalls, &config, rodata_scratch, elf_sz ); 72 796 : if( err ) { 73 57 : fd_solfuzz_fb_elf_loader_build_err_effects( runner, err ); 74 57 : return SOL_COMPAT_V2_SUCCESS; 75 57 : } 76 : 77 : /**** Capture effects ****/ 78 : 79 : /* Error code */ 80 739 : uchar out_err_code = FD_SBPF_ELF_SUCCESS; 81 : 82 : /* Rodata */ 83 739 : ulong out_rodata_hash_u64 = fd_hash( 0UL, prog->rodata, prog->rodata_sz ); 84 739 : SOL_COMPAT_NS(XXHash_t) out_rodata_hash; 85 739 : fd_memcpy( out_rodata_hash.hash, &out_rodata_hash_u64, sizeof(ulong) ); 86 : 87 : /* Text count */ 88 739 : ulong out_text_cnt = prog->info.text_cnt; 89 : 90 : /* Text off */ 91 739 : ulong out_text_off = prog->info.text_off; 92 : 93 : /* Entry PC */ 94 739 : ulong out_entry_pc = prog->entry_pc; 95 : 96 : /* Calldests */ 97 >1844*10^16 : ulong max_out_calldests_cnt = 1UL + ( prog->calldests ? fd_sbpf_calldests_cnt( prog->calldests ) : 0UL ); 98 739 : ulong * tmp_out_calldests = fd_spad_alloc_check( spad, alignof(ulong), sizeof(ulong)*max_out_calldests_cnt ); 99 739 : ulong out_calldests_cnt = 0UL; 100 : 101 : /* Add the entrypoint to the calldests */ 102 739 : tmp_out_calldests[out_calldests_cnt++] = prog->entry_pc; 103 : 104 : /* Add the rest of the calldests */ 105 741 : if( FD_LIKELY( prog->calldests ) ) { 106 741 : for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests); 107 130095 : !fd_sbpf_calldests_const_iter_done(target_pc); 108 129354 : target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) { 109 129361 : if( FD_LIKELY( target_pc!=prog->entry_pc ) ) { 110 129361 : tmp_out_calldests[out_calldests_cnt++] = target_pc; 111 129361 : } 112 129354 : } 113 741 : } 114 : 115 : /* Sort the calldests in ascending order */ 116 739 : sort_ulong_inplace( tmp_out_calldests, out_calldests_cnt ); 117 : 118 : /* Create output calldests vector */ 119 739 : ulong out_calldests_hash_u64 = fd_hash( 0UL, tmp_out_calldests, sizeof(ulong) * out_calldests_cnt ); 120 739 : SOL_COMPAT_NS(XXHash_t) out_calldests_hash; 121 739 : fd_memcpy( out_calldests_hash.hash, &out_calldests_hash_u64, sizeof(ulong) ); 122 : 123 : /* Build effects */ 124 739 : 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 739 : return SOL_COMPAT_V2_SUCCESS; 127 796 : } 128 : 129 : #endif /* FD_HAS_FLATCC */