Restore ability for programs to upgrade themselves (#20265)

* Make helper associated fn

* Add feature definition

* Add handling to preserve program-id write lock when upgradeable loader is present; restore bpf upgrade-self test

* Use single feature
This commit is contained in:
Tyera Eulberg
2021-09-28 10:59:08 -05:00
committed by GitHub
parent 30bce9ddbc
commit 2cd9dc99b6
6 changed files with 126 additions and 16 deletions

View File

@ -354,6 +354,9 @@ impl Message {
}
pub fn is_writable(&self, i: usize, demote_program_write_locks: bool) -> bool {
let demote_program_id = demote_program_write_locks
&& self.is_key_called_as_program(i)
&& !self.is_upgradeable_loader_present();
(i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts)
as usize
|| (i >= self.header.num_required_signatures as usize
@ -363,7 +366,7 @@ impl Message {
let key = self.account_keys[i];
sysvar::is_sysvar_id(&key) || BUILTIN_PROGRAMS_KEYS.contains(&key)
}
&& !(demote_program_write_locks && self.is_key_called_as_program(i))
&& !demote_program_id
}
pub fn is_signer(&self, i: usize) -> bool {
@ -503,6 +506,13 @@ impl Message {
}
false
}
/// Returns true if any account is the bpf upgradeable loader
pub fn is_upgradeable_loader_present(&self) -> bool {
self.account_keys
.iter()
.any(|&key| key == bpf_loader_upgradeable::id())
}
}
#[cfg(test)]

View File

@ -1,5 +1,6 @@
use {
crate::{
bpf_loader_upgradeable,
message::{legacy::BUILTIN_PROGRAMS_KEYS, v0},
pubkey::Pubkey,
sysvar,
@ -99,8 +100,12 @@ impl MappedMessage {
pub fn is_writable(&self, key_index: usize, demote_program_write_locks: bool) -> bool {
if self.is_writable_index(key_index) {
if let Some(key) = self.get_account_key(key_index) {
return !(sysvar::is_sysvar_id(key) || BUILTIN_PROGRAMS_KEYS.contains(key)
|| (demote_program_write_locks && self.is_key_called_as_program(key_index)));
let demote_program_id = demote_program_write_locks
&& self.is_key_called_as_program(key_index)
&& !self.is_upgradeable_loader_present();
return !(sysvar::is_sysvar_id(key)
|| BUILTIN_PROGRAMS_KEYS.contains(key)
|| demote_program_id);
}
}
false
@ -116,6 +121,12 @@ impl MappedMessage {
false
}
}
/// Returns true if any account is the bpf upgradeable loader
pub fn is_upgradeable_loader_present(&self) -> bool {
self.account_keys_iter()
.any(|&key| key == bpf_loader_upgradeable::id())
}
}
#[cfg(test)]

View File

@ -308,6 +308,14 @@ impl SanitizedMessage {
.saturating_add(num_secp256k1_signatures),
)
}
/// Inspect all message keys for the bpf upgradeable loader
pub fn is_upgradeable_loader_present(&self) -> bool {
match self {
Self::Legacy(message) => message.is_upgradeable_loader_present(),
Self::V0(message) => message.is_upgradeable_loader_present(),
}
}
}
#[cfg(test)]