Skip to content

Commit

Permalink
Adjusts the access violation checks at BPF ABIv0 and ABIv1 syscall fo…
Browse files Browse the repository at this point in the history
…r CPI.
  • Loading branch information
Lichtso committed Jun 10, 2022
1 parent 2072aaf commit a263e52
Showing 1 changed file with 45 additions and 11 deletions.
56 changes: 45 additions & 11 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2939,6 +2939,10 @@ fn get_translated_accounts<'a, T, F>(
where
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
{
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context
.get_current_instruction_context()
.map_err(SyscallError::InstructionError)?;
let mut accounts = Vec::with_capacity(instruction_accounts.len().saturating_add(1));

let program_account_index = program_indices
Expand All @@ -2952,22 +2956,24 @@ where
if index_in_instruction != instruction_account.index_in_callee {
continue; // Skip duplicate account
}
let account = invoke_context
.transaction_context
.get_account_at_index(instruction_account.index_in_transaction)
let mut borrowed_account = instruction_context
.try_borrow_instruction_account(
transaction_context,
instruction_account.index_in_caller,
)
.map_err(SyscallError::InstructionError)?;
let account_key = invoke_context
.transaction_context
.get_key_of_account_at_index(instruction_account.index_in_transaction)
.map_err(SyscallError::InstructionError)?;
if account.borrow().executable() {
if borrowed_account.is_executable() {
// Use the known account
if invoke_context
.feature_set
.is_active(&executables_incur_cpi_data_cost::id())
{
invoke_context.get_compute_meter().consume(
(account.borrow().data().len() as u64)
(borrowed_account.get_data().len() as u64)
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
)?;
}
Expand All @@ -2982,12 +2988,40 @@ where
invoke_context,
)?;
{
let mut account = account.borrow_mut();
account.copy_into_owner_from_slice(caller_account.owner.as_ref());
account.set_data_from_slice(caller_account.data);
account.set_lamports(*caller_account.lamports);
account.set_executable(caller_account.executable);
account.set_rent_epoch(caller_account.rent_epoch);
if borrowed_account.get_lamports() != *caller_account.lamports {
borrowed_account
.set_lamports(*caller_account.lamports)
.map_err(SyscallError::InstructionError)?;
}
// The redundant `is_data_mutable` helps to avoid the expensive data comparison if we can
if borrowed_account
.is_data_mutable(caller_account.data.len())
.is_ok()
|| borrowed_account.get_data() != caller_account.data
{
borrowed_account
.set_data(caller_account.data)
.map_err(SyscallError::InstructionError)?;
}
if borrowed_account.is_executable() != caller_account.executable {
borrowed_account
.set_executable(caller_account.executable)
.map_err(SyscallError::InstructionError)?;
}
if borrowed_account.get_owner() != caller_account.owner {
borrowed_account
.set_owner(caller_account.owner.as_ref())
.map_err(SyscallError::InstructionError)?;
}
drop(borrowed_account);
// TODO: What to do about the `rent_epoch` field?
let account = invoke_context
.transaction_context
.get_account_at_index(instruction_account.index_in_transaction)
.map_err(SyscallError::InstructionError)?;
account
.borrow_mut()
.set_rent_epoch(caller_account.rent_epoch);
}
let caller_account = if instruction_account.is_writable {
let orig_data_lens = invoke_context
Expand Down

0 comments on commit a263e52

Please sign in to comment.