Skip to content

Commit

Permalink
flamenco, fuzz: CPI syscall fuzzing support
Browse files Browse the repository at this point in the history
  • Loading branch information
ravyu-jump committed Aug 5, 2024
1 parent 65c003b commit 0b93a6b
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 34 deletions.
14 changes: 7 additions & 7 deletions src/flamenco/runtime/fd_executor.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ dump_sorted_features( const fd_features_t * features, fd_exec_test_feature_set_t
}

static void
dump_account_state( fd_borrowed_account_t * borrowed_account,
dump_account_state( fd_borrowed_account_t const * borrowed_account,
fd_exec_test_acct_state_t * output_account ) {
// Address
fd_memcpy(output_account->address, borrowed_account->pubkey, sizeof(fd_pubkey_t));
Expand All @@ -515,10 +515,10 @@ dump_account_state( fd_borrowed_account_t * borrowed_account,
output_account->has_seed_addr = false;
}

static void
create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * instr_context,
fd_exec_txn_ctx_t *txn_ctx,
fd_instr_info_t *instr ) {
void
fd_create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * instr_context,
fd_exec_txn_ctx_t const *txn_ctx,
fd_instr_info_t const *instr ) {
/*
NOTE: Calling this function requires the caller to have a scratch frame ready (see dump_instr_to_protobuf)
*/
Expand Down Expand Up @@ -546,7 +546,7 @@ create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t *
instr_context->accounts = fd_scratch_alloc(alignof(fd_exec_test_acct_state_t), (instr_context->accounts_count + num_sysvar_entries + txn_ctx->executable_cnt) * sizeof(fd_exec_test_acct_state_t));
for( ulong i = 0; i < txn_ctx->accounts_cnt; i++ ) {
// Copy account information over
fd_borrowed_account_t * borrowed_account = &txn_ctx->borrowed_accounts[i];
fd_borrowed_account_t const * borrowed_account = &txn_ctx->borrowed_accounts[i];
fd_exec_test_acct_state_t * output_account = &instr_context->accounts[i];
dump_account_state( borrowed_account, output_account );
}
Expand Down Expand Up @@ -670,7 +670,7 @@ dump_instr_to_protobuf( fd_exec_txn_ctx_t *txn_ctx,
}

fd_exec_test_instr_context_t instr_context = FD_EXEC_TEST_INSTR_CONTEXT_INIT_DEFAULT;
create_instr_context_protobuf_from_instructions( &instr_context, txn_ctx, instr );
fd_create_instr_context_protobuf_from_instructions( &instr_context, txn_ctx, instr );

/* Output to file */
ulong out_buf_size = 100 * 1024 * 1024;
Expand Down
10 changes: 10 additions & 0 deletions src/flamenco/runtime/fd_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@

FD_PROTOTYPES_BEGIN

/* Create an InstrContext protobuf struct from a given
transaction context and instr info.
NOTE: Calling this function requires the caller to have a scratch
frame ready and pushed (see dump_instr_to_protobuf) */
void
fd_create_instr_context_protobuf_from_instructions( fd_exec_test_instr_context_t * instr_context,
fd_exec_txn_ctx_t const * txn_ctx,
fd_instr_info_t const * instr );

/* fd_exec_instr_fn_t processes an instruction. Returns an error code
in FD_EXECUTOR_INSTR_{ERR_{...},SUCCESS}. */

Expand Down
42 changes: 30 additions & 12 deletions src/flamenco/runtime/tests/fd_exec_instr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ _instr_context_create( fd_exec_instr_test_runner_t * runner,

/* Initial variables */
txn_ctx->loaded_accounts_data_size_limit = FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT;
txn_ctx->heap_size = FD_VM_HEAP_SIZE;
txn_ctx->heap_size = fd_ulong_max( txn_ctx->heap_size, FD_VM_HEAP_SIZE ); /* FIXME: bound this to FD_VM_HEAP_MAX?*/

/* Set up epoch context */
fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( epoch_ctx );
Expand Down Expand Up @@ -509,6 +509,9 @@ _instr_context_create( fd_exec_instr_test_runner_t * runner,
}
info->acct_cnt = (uchar)test_ctx->instr_accounts_count;

// FIXME: Specifically for CPI syscalls, flag guard this?
fd_instr_info_sum_account_lamports( info, &info->starting_lamports_h, &info->starting_lamports_l );

/* This function is used to create context both for instructions and for syscalls,
however some of the remaining checks are only relevant for program instructions. */
if( !is_syscall ) {
Expand Down Expand Up @@ -1627,7 +1630,10 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner,
/* Create execution context */
const fd_exec_test_instr_context_t * input_instr_ctx = &input->instr_ctx;
fd_exec_instr_ctx_t ctx[1];
if( !_instr_context_create( runner, ctx, input_instr_ctx, alloc, true ) )
// Skip extra checks for non-CPI syscalls
bool skip_extra_checks = strncmp( (const char *)input->syscall_invocation.function_name.bytes, "sol_invoke_signed", 17 );

if( !_instr_context_create( runner, ctx, input_instr_ctx, alloc, skip_extra_checks ) )
goto error;
fd_valloc_t valloc = fd_scratch_virtual();

Expand Down Expand Up @@ -1762,7 +1768,7 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner,

/* Capture the effects */
effects->error = -syscall_err;
effects->r0 = vm->reg[0];
effects->r0 = syscall_err ? 0 : vm->reg[0]; // Save only on success
effects->cu_avail = (ulong)vm->cu;

effects->heap = FD_SCRATCH_ALLOC_APPEND(
Expand All @@ -1775,15 +1781,27 @@ fd_exec_vm_syscall_test_run( fd_exec_instr_test_runner_t * runner,
effects->stack->size = (uint)FD_VM_STACK_MAX;
fd_memcpy( effects->stack->bytes, vm->stack, FD_VM_STACK_MAX );

// if( input_data_sz ) {
// effects->inputdata = FD_SCRATCH_ALLOC_APPEND(
// l, alignof(uint), PB_BYTES_ARRAY_T_ALLOCSIZE( input_data_sz ) );
// effects->inputdata->size = (uint)input_data_sz;
// fd_memcpy( effects->inputdata->bytes, vm->input, input_data_sz );
// } else {
// effects->inputdata = NULL;
// }
effects->inputdata = NULL;
/* Flatten input data regions into a single region.
FIXME: Have SyscallEffects store repeated InputDataRegions instead
for more granularity. May need to regenerate fixtures/test-vectors. */
ulong input_regions_total_sz = 0;
for( ulong i=0; i<vm->input_mem_regions_cnt; i++ ) {
input_regions_total_sz += vm->input_mem_regions[i].region_sz;
}
if( input_regions_total_sz == 0 ) {
effects->inputdata = NULL;
} else {
effects->inputdata = FD_SCRATCH_ALLOC_APPEND(
l, alignof(uint), PB_BYTES_ARRAY_T_ALLOCSIZE( input_regions_total_sz ) );

effects->inputdata->size = (uint)input_regions_total_sz;
uchar * inputdata_ptr = effects->inputdata->bytes;
for( ulong i=0; i<vm->input_mem_regions_cnt; i++ ) {
fd_memcpy( inputdata_ptr, (void *) vm->input_mem_regions[i].haddr, vm->input_mem_regions[i].region_sz );
inputdata_ptr += vm->input_mem_regions[i].region_sz;
}
}

effects->frame_count = vm->frame_cnt;

Expand Down
38 changes: 29 additions & 9 deletions src/flamenco/runtime/tests/fd_exec_sol_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ typedef struct {
ulong supported_feature_cnt;
} sol_compat_features_t;

typedef struct {
uint16_t validator_type;
} sol_compat_metadata_t;

static sol_compat_metadata_t metadata = { .validator_type = 1 /* Firedancer */ };
static sol_compat_features_t features;
static uchar * smem;
static const ulong smax = 1UL<<30;
Expand Down Expand Up @@ -93,6 +98,16 @@ sol_compat_check_wksp_usage( void ) {
}
}

sol_compat_features_t const *
sol_compat_get_features_v1( void ) {
return &features;
}

sol_compat_metadata_t const *
sol_compat_get_metadata_v1( void ) {
return &metadata;
}

fd_exec_instr_test_runner_t *
sol_compat_setup_scratch_and_runner( void * fmem ) {
// Setup scratch
Expand Down Expand Up @@ -152,8 +167,7 @@ sol_compat_execute_wrapper( fd_exec_instr_test_runner_t * runner,
void * input,
void ** output,
exec_test_run_fn_t * exec_test_run_fn ) {
// fd_scratch_push();
do {
FD_SCRATCH_SCOPE_BEGIN {
ulong out_bufsz = 100000000; /* 100 MB */
void * out0 = fd_scratch_prepare( 1UL );
assert( out_bufsz < fd_scratch_free() );
Expand All @@ -163,8 +177,7 @@ sol_compat_execute_wrapper( fd_exec_instr_test_runner_t * runner,
*output = NULL;
break;
}
} while(0);
// fd_scratch_pop();
} FD_SCRATCH_SCOPE_END;
}

/*
Expand Down Expand Up @@ -484,10 +497,6 @@ sol_compat_elf_loader_v1( uchar * out,
return ok;
}

sol_compat_features_t const *
sol_compat_get_features_v1( void ) {
return &features;
}

int
sol_compat_vm_syscall_execute_v1( uchar * out,
Expand Down Expand Up @@ -530,7 +539,7 @@ int
sol_compat_vm_validate_v1( uchar * out,
ulong * out_sz,
uchar const * in,
ulong in_sz) {
ulong in_sz ) {
// Setup
ulong fmem[ 64 ];
fd_exec_instr_test_runner_t * runner = sol_compat_setup_scratch_and_runner( fmem );
Expand Down Expand Up @@ -562,3 +571,14 @@ sol_compat_vm_validate_v1( uchar * out,

return ok;
}

/* We still need a separate entrypoint since other harnesses (namely sfuzz-agave)
do something other than wrap their vm_syscall equivalent */
int
sol_compat_vm_cpi_syscall_v1( uchar * out,
ulong * out_sz,
uchar const * in,
ulong in_sz ) {
/* Just a wrapper to vm_syscall_execute_v1 */
return sol_compat_vm_syscall_execute_v1( out, out_sz, in, in_sz );
}
10 changes: 10 additions & 0 deletions src/flamenco/vm/fd_vm_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@
#define FD_VM_SH_OVERFLOW (-37) /* detected a shift overflow, equivalent to VeriferError::ShiftWithOverflow */
#define FD_VM_TEXT_SZ_UNALIGNED (-38) /* detected a text section that is not a multiple of 8 */

/* Error codes related to CPI syscall.
FIXME: Should this be in fd_executor_err.h instead?
Or a separate file for syscall errors? */

#define FD_VM_CPI_ERR_TOO_MANY_SIGNERS (-39) /* detected too many signers */
#define FD_VM_CPI_ERR_TOO_MANY_ACC_INFOS (-40) /* detected too many account infos */
#define FD_VM_CPI_ERR_INSTR_TOO_LARGE (-41) /* detected too many account infos meta */
#define FD_VM_CPI_ERR_INSTR_DATA_TOO_LARGE (-42) /* detected instruction data too large */
#define FD_VM_CPI_ERR_TOO_MANY_ACC_METAS (-43) /* detected too many account metas */

FD_PROTOTYPES_BEGIN

/* fd_vm_strerror converts an FD_VM_SUCCESS / FD_VM_ERR_* code into
Expand Down
Loading

0 comments on commit 0b93a6b

Please sign in to comment.