Skip to content

Commit b45d086

Browse files
authored
Bump SBPF to v0.11.0 (#5839)
* Bump to SBPF v0.11.0 * Cleanup - EbpfError::InvalidVirtualAddress * Refactor - Return region index * Refactor - Simplify CoW in MemoryMapping * Inlines Serializer::push_account_data_region().
1 parent 7d51031 commit b45d086

File tree

11 files changed

+155
-119
lines changed

11 files changed

+155
-119
lines changed

Cargo.lock

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ solana-rpc-client-types = { path = "rpc-client-types", version = "=2.3.0" }
527527
solana-rpc-client-nonce-utils = { path = "rpc-client-nonce-utils", version = "=2.3.0" }
528528
solana-runtime = { path = "runtime", version = "=2.3.0" }
529529
solana-runtime-transaction = { path = "runtime-transaction", version = "=2.3.0" }
530-
solana-sbpf = "=0.10.0"
530+
solana-sbpf = "=0.11.0"
531531
solana-sdk = "2.2.2"
532532
solana-sdk-ids = "2.2.1"
533533
solana-sdk-macro = "2.2.1"

program-runtime/src/serialization.rs

+15-35
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use {
88
solana_sbpf::{
99
aligned_memory::{AlignedMemory, Pod},
1010
ebpf::{HOST_ALIGN, MM_INPUT_START},
11-
memory_region::{MemoryRegion, MemoryState},
11+
memory_region::MemoryRegion,
1212
},
1313
solana_sdk_ids::bpf_loader_deprecated,
1414
solana_system_interface::MAX_PERMITTED_DATA_LENGTH,
@@ -99,7 +99,20 @@ impl Serializer {
9999
} else {
100100
self.push_region(true);
101101
let vaddr = self.vaddr;
102-
self.push_account_data_region(account)?;
102+
if !account.get_data().is_empty() {
103+
let writable = account.can_data_be_changed().is_ok();
104+
let shared = account.is_shared();
105+
let mut new_region = if writable && !shared {
106+
MemoryRegion::new_writable(account.get_data_mut()?, self.vaddr)
107+
} else {
108+
MemoryRegion::new_readonly(account.get_data(), self.vaddr)
109+
};
110+
if writable && shared {
111+
new_region.cow_callback_payload = account.get_index_in_transaction() as u32;
112+
}
113+
self.vaddr += new_region.len;
114+
self.regions.push(new_region);
115+
}
103116
vaddr
104117
};
105118

@@ -126,27 +139,6 @@ impl Serializer {
126139
Ok(vm_data_addr)
127140
}
128141

129-
fn push_account_data_region(
130-
&mut self,
131-
account: &mut BorrowedAccount<'_>,
132-
) -> Result<(), InstructionError> {
133-
if !account.get_data().is_empty() {
134-
let region = match account_data_region_memory_state(account) {
135-
MemoryState::Readable => MemoryRegion::new_readonly(account.get_data(), self.vaddr),
136-
MemoryState::Writable => {
137-
MemoryRegion::new_writable(account.get_data_mut()?, self.vaddr)
138-
}
139-
MemoryState::Cow(index_in_transaction) => {
140-
MemoryRegion::new_cow(account.get_data(), self.vaddr, index_in_transaction)
141-
}
142-
};
143-
self.vaddr += region.len;
144-
self.regions.push(region);
145-
}
146-
147-
Ok(())
148-
}
149-
150142
fn push_region(&mut self, writable: bool) {
151143
let range = self.region_start..self.buffer.len();
152144
let region = if writable {
@@ -620,18 +612,6 @@ fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
620612
Ok(())
621613
}
622614

623-
pub fn account_data_region_memory_state(account: &BorrowedAccount<'_>) -> MemoryState {
624-
if account.can_data_be_changed().is_ok() {
625-
if account.is_shared() {
626-
MemoryState::Cow(account.get_index_in_transaction() as u64)
627-
} else {
628-
MemoryState::Writable
629-
}
630-
} else {
631-
MemoryState::Readable
632-
}
633-
}
634-
635615
#[cfg(test)]
636616
#[allow(clippy::indexing_slicing)]
637617
mod tests {

programs/bpf_loader/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,9 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
357357

358358
Ok(MemoryMapping::new_with_cow(
359359
regions,
360-
transaction_context.account_data_write_access_handler(),
361360
config,
362361
sbpf_version,
362+
transaction_context.account_data_write_access_handler(),
363363
)?)
364364
}
365365

programs/bpf_loader/src/syscalls/cpi.rs

+78-42
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,8 @@ use {
44
scopeguard::defer,
55
solana_loader_v3_interface::instruction as bpf_loader_upgradeable,
66
solana_measure::measure::Measure,
7-
solana_program_runtime::{
8-
invoke_context::SerializedAccountMetadata, serialization::account_data_region_memory_state,
9-
},
10-
solana_sbpf::{
11-
ebpf,
12-
memory_region::{MemoryRegion, MemoryState},
13-
},
7+
solana_program_runtime::invoke_context::SerializedAccountMetadata,
8+
solana_sbpf::{ebpf, memory_region::MemoryRegion},
149
solana_stable_layout::stable_instruction::StableInstruction,
1510
solana_transaction_context::BorrowedAccount,
1611
std::{mem, ptr},
@@ -365,7 +360,7 @@ impl<'a> CallerAccount<'a> {
365360
&self,
366361
memory_mapping: &'a MemoryMapping<'_>,
367362
is_loader_deprecated: bool,
368-
) -> Result<Option<&'a MemoryRegion>, Error> {
363+
) -> Result<Option<(usize, &'a MemoryRegion)>, Error> {
369364
account_realloc_region(
370365
memory_mapping,
371366
self.vm_data_addr,
@@ -1076,7 +1071,7 @@ fn cpi_common<S: SyscallInvokeSigned>(
10761071
account_infos_len: u64,
10771072
signers_seeds_addr: u64,
10781073
signers_seeds_len: u64,
1079-
memory_mapping: &MemoryMapping,
1074+
memory_mapping: &mut MemoryMapping,
10801075
) -> Result<u64, Error> {
10811076
// CPI entry.
10821077
//
@@ -1148,12 +1143,12 @@ fn cpi_common<S: SyscallInvokeSigned>(
11481143
// it's better to be safe than sorry.
11491144
for (index_in_caller, caller_account) in accounts.iter() {
11501145
if let Some(caller_account) = caller_account {
1151-
let callee_account = instruction_context
1146+
let mut callee_account = instruction_context
11521147
.try_borrow_instruction_account(transaction_context, *index_in_caller)?;
11531148
update_caller_account_perms(
11541149
memory_mapping,
11551150
caller_account,
1156-
&callee_account,
1151+
&mut callee_account,
11571152
is_loader_deprecated,
11581153
)?;
11591154
}
@@ -1266,9 +1261,9 @@ fn update_callee_account(
12661261
}
12671262

12681263
fn update_caller_account_perms(
1269-
memory_mapping: &MemoryMapping,
1264+
memory_mapping: &mut MemoryMapping,
12701265
caller_account: &CallerAccount,
1271-
callee_account: &BorrowedAccount<'_>,
1266+
callee_account: &mut BorrowedAccount<'_>,
12721267
is_loader_deprecated: bool,
12731268
) -> Result<(), Error> {
12741269
let CallerAccount {
@@ -1277,26 +1272,66 @@ fn update_caller_account_perms(
12771272
..
12781273
} = caller_account;
12791274

1280-
let data_region = account_data_region(memory_mapping, *vm_data_addr, *original_data_len)?;
1281-
if let Some(region) = data_region {
1282-
region
1283-
.state
1284-
.set(account_data_region_memory_state(callee_account));
1275+
if let Some((region_index, region)) =
1276+
account_data_region(memory_mapping, *vm_data_addr, *original_data_len)?
1277+
{
1278+
let writable = callee_account.can_data_be_changed().is_ok();
1279+
let shared = callee_account.is_shared();
1280+
let mut new_region = if writable && !shared {
1281+
MemoryRegion::new_writable(
1282+
unsafe {
1283+
std::slice::from_raw_parts_mut(
1284+
region.host_addr.get() as *mut u8,
1285+
region.len as usize,
1286+
)
1287+
},
1288+
region.vm_addr,
1289+
)
1290+
} else {
1291+
MemoryRegion::new_readonly(
1292+
unsafe {
1293+
std::slice::from_raw_parts(
1294+
region.host_addr.get() as *const u8,
1295+
region.len as usize,
1296+
)
1297+
},
1298+
region.vm_addr,
1299+
)
1300+
};
1301+
if writable && shared {
1302+
new_region.cow_callback_payload = callee_account.get_index_in_transaction() as u32;
1303+
}
1304+
memory_mapping.replace_region(region_index, new_region)?;
12851305
}
1286-
let realloc_region = account_realloc_region(
1306+
1307+
if let Some((region_index, region)) = account_realloc_region(
12871308
memory_mapping,
12881309
*vm_data_addr,
12891310
*original_data_len,
12901311
is_loader_deprecated,
1291-
)?;
1292-
if let Some(region) = realloc_region {
1293-
region
1294-
.state
1295-
.set(if callee_account.can_data_be_changed().is_ok() {
1296-
MemoryState::Writable
1297-
} else {
1298-
MemoryState::Readable
1299-
});
1312+
)? {
1313+
let new_region = if callee_account.can_data_be_changed().is_ok() {
1314+
MemoryRegion::new_writable(
1315+
unsafe {
1316+
std::slice::from_raw_parts_mut(
1317+
region.host_addr.get() as *mut u8,
1318+
region.len as usize,
1319+
)
1320+
},
1321+
region.vm_addr,
1322+
)
1323+
} else {
1324+
MemoryRegion::new_readonly(
1325+
unsafe {
1326+
std::slice::from_raw_parts(
1327+
region.host_addr.get() as *const u8,
1328+
region.len as usize,
1329+
)
1330+
},
1331+
region.vm_addr,
1332+
)
1333+
};
1334+
memory_mapping.replace_region(region_index, new_region)?;
13001335
}
13011336

13021337
Ok(())
@@ -1323,7 +1358,7 @@ fn update_caller_account(
13231358

13241359
let mut zero_all_mapped_spare_capacity = false;
13251360
if direct_mapping {
1326-
if let Some(region) = account_data_region(
1361+
if let Some((_region_index, region)) = account_data_region(
13271362
memory_mapping,
13281363
caller_account.vm_data_addr,
13291364
caller_account.original_data_len,
@@ -1412,12 +1447,12 @@ fn update_caller_account(
14121447

14131448
// Temporarily configure the realloc region as writable then set it back to
14141449
// whatever state it had.
1415-
let realloc_region = caller_account
1450+
let (_realloc_region_index, realloc_region) = caller_account
14161451
.realloc_region(memory_mapping, is_loader_deprecated)?
14171452
.unwrap(); // unwrapping here is fine, we already asserted !is_loader_deprecated
1418-
let original_state = realloc_region.state.replace(MemoryState::Writable);
1453+
let original_state = realloc_region.writable.replace(true);
14191454
defer! {
1420-
realloc_region.state.set(original_state);
1455+
realloc_region.writable.set(original_state);
14211456
};
14221457

14231458
// We need to zero the unused space in the realloc region, starting after the
@@ -1521,12 +1556,12 @@ fn update_caller_account(
15211556
//
15221557
// Therefore we temporarily configure the realloc region as writable
15231558
// then set it back to whatever state it had.
1524-
let realloc_region = caller_account
1559+
let (_realloc_region_index, realloc_region) = caller_account
15251560
.realloc_region(memory_mapping, is_loader_deprecated)?
15261561
.unwrap(); // unwrapping here is fine, we asserted !is_loader_deprecated
1527-
let original_state = realloc_region.state.replace(MemoryState::Writable);
1562+
let original_state = realloc_region.writable.replace(true);
15281563
defer! {
1529-
realloc_region.state.set(original_state);
1564+
realloc_region.writable.set(original_state);
15301565
};
15311566

15321567
translate_slice_mut::<u8>(
@@ -1566,37 +1601,38 @@ fn account_data_region<'a>(
15661601
memory_mapping: &'a MemoryMapping<'_>,
15671602
vm_data_addr: u64,
15681603
original_data_len: usize,
1569-
) -> Result<Option<&'a MemoryRegion>, Error> {
1604+
) -> Result<Option<(usize, &'a MemoryRegion)>, Error> {
15701605
if original_data_len == 0 {
15711606
return Ok(None);
15721607
}
15731608

15741609
// We can trust vm_data_addr to point to the correct region because we
15751610
// enforce that in CallerAccount::from_(sol_)account_info.
1576-
let data_region = memory_mapping.region(AccessType::Load, vm_data_addr)?;
1611+
let (data_region_index, data_region) = memory_mapping.region(AccessType::Load, vm_data_addr)?;
15771612
// vm_data_addr must always point to the beginning of the region
15781613
debug_assert_eq!(data_region.vm_addr, vm_data_addr);
1579-
Ok(Some(data_region))
1614+
Ok(Some((data_region_index, data_region)))
15801615
}
15811616

15821617
fn account_realloc_region<'a>(
15831618
memory_mapping: &'a MemoryMapping<'_>,
15841619
vm_data_addr: u64,
15851620
original_data_len: usize,
15861621
is_loader_deprecated: bool,
1587-
) -> Result<Option<&'a MemoryRegion>, Error> {
1622+
) -> Result<Option<(usize, &'a MemoryRegion)>, Error> {
15881623
if is_loader_deprecated {
15891624
return Ok(None);
15901625
}
15911626

15921627
let realloc_vm_addr = vm_data_addr.saturating_add(original_data_len as u64);
1593-
let realloc_region = memory_mapping.region(AccessType::Load, realloc_vm_addr)?;
1628+
let (realloc_region_index, realloc_region) =
1629+
memory_mapping.region(AccessType::Load, realloc_vm_addr)?;
15941630
debug_assert_eq!(realloc_region.vm_addr, realloc_vm_addr);
15951631
debug_assert!((MAX_PERMITTED_DATA_INCREASE
15961632
..MAX_PERMITTED_DATA_INCREASE.saturating_add(BPF_ALIGN_OF_U128))
15971633
.contains(&(realloc_region.len as usize)));
1598-
debug_assert!(!matches!(realloc_region.state.get(), MemoryState::Cow(_)));
1599-
Ok(Some(realloc_region))
1634+
debug_assert_eq!(realloc_region.cow_callback_payload, u32::MAX);
1635+
Ok(Some((realloc_region_index, realloc_region)))
16001636
}
16011637

16021638
#[allow(clippy::indexing_slicing)]

0 commit comments

Comments
 (0)