Skip to content

Commit

Permalink
change approach
Browse files Browse the repository at this point in the history
  • Loading branch information
topointon-jump committed Jan 3, 2025
1 parent 1a95e67 commit 4c25d98
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 53 deletions.
53 changes: 22 additions & 31 deletions src/flamenco/runtime/program/fd_bpf_loader_serialization.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t ctx,
FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
serialized_params += sizeof(ulong);
} else {
/* Calculate and store the start of the actual metadata region for this account,
excluding any duplicate account markers at the beginning.
We use this later for retrieving the serialized values later in the CPI security checks. */
ulong metadata_region_offset_with_dups = *input_mem_regions_cnt==0UL ? 0UL :
input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
input_mem_regions[ *input_mem_regions_cnt-1U ].region_sz;

acc_region_metas[i].metadata_region_offset = metadata_region_offset_with_dups +
(ulong)(serialized_params - curr_serialized_params_start);

FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
serialized_params += sizeof(uchar);

Expand Down Expand Up @@ -241,30 +252,14 @@ fd_bpf_loader_input_serialize_aligned( fd_exec_instr_ctx_t ctx,

fd_pubkey_t key = *acc;
FD_STORE( fd_pubkey_t, serialized_params, key );

/* Calculate the start of the metadata region */
ulong metadata_region_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START +
( *input_mem_regions_cnt==0UL ? 0UL : (
input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
input_mem_regions[ *input_mem_regions_cnt-1U ].region_sz ) );

/* Store the vaddrs of the serialized pubkey, owner and lamports for CPI security checks later.
We calculate them in the serialization code for several reasons:
- It makes reasoning about the code simpler
- It's slightly more efficient
- It's what Agave does */
acc_region_metas[i].serialized_acc_metadata.key_vaddr = metadata_region_vaddr + (ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(fd_pubkey_t);

fd_pubkey_t owner = *(fd_pubkey_t *)&metadata->info.owner;
FD_STORE( fd_pubkey_t, serialized_params, owner );
acc_region_metas[i].serialized_acc_metadata.owner_vaddr = metadata_region_vaddr + (ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(fd_pubkey_t);

ulong lamports = metadata->info.lamports;
FD_STORE( ulong, serialized_params, lamports );
acc_region_metas[i].serialized_acc_metadata.lamports_vaddr = metadata_region_vaddr + (ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(ulong);

ulong acc_data_len = metadata->dlen;
Expand Down Expand Up @@ -500,6 +495,17 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t ctx,
FD_STORE( uchar, serialized_params, (uchar)dup_acc_idx[acc_idx] );
serialized_params += sizeof(uchar);
} else {
/* Calculate and store the start of the actual metadata region for this account,
excluding any duplicate account markers at the beginning.
We use this later for retrieving the serialized values later in the CPI security checks. */
ulong metadata_region_offset_with_dups = *input_mem_regions_cnt==0UL ? 0UL :
input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
input_mem_regions[ *input_mem_regions_cnt-1U ].region_sz;

acc_region_metas[i].metadata_region_offset = metadata_region_offset_with_dups +
(ulong)(serialized_params - curr_serialized_params_start);

FD_STORE( uchar, serialized_params, FD_NON_DUP_MARKER );
serialized_params += sizeof(uchar);

Expand All @@ -514,20 +520,12 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t ctx,
FD_STORE( uchar, serialized_params, is_writable );
serialized_params += sizeof(uchar);

ulong metadata_region_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START +
( *input_mem_regions_cnt==0UL ? 0UL : (
input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
input_mem_regions[ *input_mem_regions_cnt-1U ].region_sz ) );

fd_pubkey_t key = *acc;
FD_STORE( fd_pubkey_t, serialized_params, key );
/* Store the vaddrs of the serialized pubkey, owner and lamports for CPI security checks later */
acc_region_metas[i].serialized_acc_metadata.key_vaddr = metadata_region_vaddr + (ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(fd_pubkey_t);

ulong lamports = metadata->info.lamports;
FD_STORE( ulong, serialized_params, lamports );
acc_region_metas[i].serialized_acc_metadata.lamports_vaddr = metadata_region_vaddr + (ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(ulong);

ulong acc_data_len = metadata->dlen;
Expand All @@ -539,13 +537,6 @@ fd_bpf_loader_input_serialize_unaligned( fd_exec_instr_ctx_t ctx,

fd_pubkey_t owner = *(fd_pubkey_t *)&metadata->info.owner;
FD_STORE( fd_pubkey_t, serialized_params, owner );

ulong second_metadata_region_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START +
( *input_mem_regions_cnt==0UL ? 0UL : (
input_mem_regions[ *input_mem_regions_cnt-1U ].vaddr_offset +
input_mem_regions[ *input_mem_regions_cnt-1U ].region_sz ) );
acc_region_metas[i].serialized_acc_metadata.owner_vaddr = second_metadata_region_vaddr +
(ulong)(serialized_params - curr_serialized_params_start);
serialized_params += sizeof(fd_pubkey_t);

uchar is_executable = (uchar)metadata->info.executable;
Expand Down
21 changes: 5 additions & 16 deletions src/flamenco/vm/fd_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,18 @@ struct __attribute__((aligned(8UL))) fd_vm_input_region {
};
typedef struct fd_vm_input_region fd_vm_input_region_t;

/* Absolute vaddr pointers to the various fields of a serialized account,
used for direct mapping CPI security checks.
https://github.com/anza-xyz/agave/blob/3aa7fdc2c726763402bf75586e2c21e24a518767/program-runtime/src/invoke_context.rs#L180 */
struct __attribute__((aligned(8UL))) fd_vm_serialized_account_metadata {
/* vaddr of the serialized pubkey of the account */
ulong key_vaddr;
/* vaddr of the serialized lamport value of the account */
ulong lamports_vaddr;
/* vaddr of the serialized pubkey value of the account's owner */
ulong owner_vaddr;
};
typedef struct fd_vm_serialized_account_metadata fd_vm_serialized_account_metadata_t;

/* fd_vm_acc_region_meta_t holds metadata about a given account. An array of these
structs will map an instruction account index to its respective input memory
region location. */

struct __attribute((aligned(8UL))) fd_vm_acc_region_meta {
uint region_idx;
uchar has_data_region;
uchar has_resizing_region;
fd_vm_serialized_account_metadata_t serialized_acc_metadata;
uchar has_resizing_region;
/* offset of the accounts metadata region, relative to the start of the input region.
excludes any duplicate account markers. */
ulong metadata_region_offset;
};
typedef struct fd_vm_acc_region_meta fd_vm_acc_region_meta_t;

Expand Down
33 changes: 33 additions & 0 deletions src/flamenco/vm/syscall/fd_vm_syscall_cpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,39 @@ fd_vm_syscall_cpi_check_authorized_program( fd_pubkey_t const * program_i
|| fd_vm_syscall_cpi_is_precompile(program_id, slot_ctx));
}

/* Helper functions to get the absolute vaddrs of the serialized accounts pubkey, lamports and owner. */
#define VM_SERIALIZED_PUBKEY_OFFSET (8UL)
#define VM_SERIALIZED_OWNER_OFFSET (40UL)
#define VM_SERIALIZED_LAMPORTS_OFFSET (72UL)

#define VM_SERIALIZED_UNALIGNED_PUBKEY_OFFSET (3UL)
#define VM_SERIALIZED_UNALIGNED_LAMPORTS_OFFSET (35UL)

static inline
ulong serialized_pubkey_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset +
(vm->is_deprecated ? VM_SERIALIZED_UNALIGNED_PUBKEY_OFFSET : VM_SERIALIZED_PUBKEY_OFFSET);
}

static inline
ulong serialized_owner_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
if ( vm->is_deprecated ) {
/* For deprecated loader programs, the owner is serialized into the start of the region
following the account data region at a fixed offset. */
return FD_VM_MEM_MAP_INPUT_REGION_START + vm->input_mem_regions[
acc_region_meta->has_data_region ? acc_region_meta->region_idx+2 : acc_region_meta->region_idx+1
].vaddr_offset;
}

return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset + VM_SERIALIZED_OWNER_OFFSET;
}

static inline
ulong serialized_lamports_vaddr( fd_vm_t * vm, fd_vm_acc_region_meta_t * acc_region_meta ) {
return FD_VM_MEM_MAP_INPUT_REGION_START + acc_region_meta->metadata_region_offset +
(vm->is_deprecated ? VM_SERIALIZED_UNALIGNED_LAMPORTS_OFFSET : VM_SERIALIZED_LAMPORTS_OFFSET);
}

/**********************************************************************
CROSS PROGRAM INVOCATION (C ABI)
**********************************************************************/
Expand Down
11 changes: 5 additions & 6 deletions src/flamenco/vm/syscall/fd_vm_syscall_cpi_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,14 +337,13 @@ VM_SYSCALL_CPI_TRANSLATE_AND_UPDATE_ACCOUNTS_FUNC(
in the serialized account metadata
https://github.com/anza-xyz/agave/blob/c79c3c9e67274594ed4f43ed8386e9ddc60a99e9/programs/bpf_loader/src/syscalls/cpi.rs#L116 */
fd_vm_acc_region_meta_t acc_region_meta = vm->acc_region_metas[index_in_caller];
fd_vm_serialized_account_metadata_t serialized_acc_meta = acc_region_meta.serialized_acc_metadata;
if ( FD_UNLIKELY(( account_infos[j].pubkey_addr != serialized_acc_meta.key_vaddr )) ) {
fd_vm_acc_region_meta_t * acc_region_meta = &vm->acc_region_metas[index_in_caller];
if ( FD_UNLIKELY(( account_infos[j].pubkey_addr != serialized_pubkey_vaddr( vm, acc_region_meta ) )) ) {
return FD_VM_SYSCALL_ERR_INVALID_POINTER;
}

/* https://github.com/anza-xyz/agave/blob/c79c3c9e67274594ed4f43ed8386e9ddc60a99e9/programs/bpf_loader/src/syscalls/cpi.rs#L122 */
if ( FD_UNLIKELY(( account_infos[j].owner_addr != serialized_acc_meta.owner_vaddr )) ) {
if ( FD_UNLIKELY(( account_infos[j].owner_addr != serialized_owner_vaddr( vm, acc_region_meta ) )) ) {
return FD_VM_SYSCALL_ERR_INVALID_POINTER;
}

Expand All @@ -361,7 +360,7 @@ VM_SYSCALL_CPI_TRANSLATE_AND_UPDATE_ACCOUNTS_FUNC(

/* https://github.com/anza-xyz/agave/blob/c79c3c9e67274594ed4f43ed8386e9ddc60a99e9/programs/bpf_loader/src/syscalls/cpi.rs#L144 */
VM_SYSCALL_CPI_ACC_INFO_LAMPORTS_VADDR( vm, (account_infos + j), lamports_vaddr )
if ( FD_UNLIKELY(( lamports_vaddr != serialized_acc_meta.lamports_vaddr )) ) {
if ( FD_UNLIKELY(( lamports_vaddr != serialized_lamports_vaddr( vm, acc_region_meta ) )) ) {
return FD_VM_SYSCALL_ERR_INVALID_POINTER;
}

Expand All @@ -378,7 +377,7 @@ VM_SYSCALL_CPI_TRANSLATE_AND_UPDATE_ACCOUNTS_FUNC(

/* https://github.com/anza-xyz/agave/blob/c79c3c9e67274594ed4f43ed8386e9ddc60a99e9/programs/bpf_loader/src/syscalls/cpi.rs#L172 */
ulong expected_data_region_vaddr = FD_VM_MEM_MAP_INPUT_REGION_START +
vm->input_mem_regions[acc_region_meta.region_idx].vaddr_offset;
vm->input_mem_regions[acc_region_meta->region_idx].vaddr_offset;
VM_SYSCALL_CPI_ACC_INFO_DATA_VADDR( vm, (account_infos + j), data_vaddr )
if ( FD_UNLIKELY(( data_vaddr != expected_data_region_vaddr )) ) {
return FD_VM_SYSCALL_ERR_INVALID_POINTER;
Expand Down

0 comments on commit 4c25d98

Please sign in to comment.