diff --git a/docs/src/developing/programming-model/runtime.md b/docs/src/developing/programming-model/runtime.md index cee5d5a6c2..c4eff5f6c8 100644 --- a/docs/src/developing/programming-model/runtime.md +++ b/docs/src/developing/programming-model/runtime.md @@ -30,6 +30,7 @@ adhere to the runtime policy. The policy is as follows: - Only the owner of the account may change owner. - And only if the account is writable. + - And only if the account is not executable - And only if the data is zero-initialized or empty. - An account not assigned to the program cannot have its balance decrease. - The balance of read-only and executable accounts may not change. diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 23b43b73fd..54871afd43 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -80,9 +80,11 @@ impl PreAccount { ) -> Result<(), InstructionError> { // Only the owner of the account may change owner and // only if the account is writable and + // only if the account is not executable and // only if the data is zero-initialized or empty if self.owner != post.owner && (!self.is_writable // line coverage used to get branch coverage + || self.is_executable || *program_id != self.owner || !Self::is_zeroed(&post.data)) { @@ -994,6 +996,15 @@ mod tests { Ok(()), "mallory should be able to change the account owner, if she leaves clear data" ); + assert_eq!( + Change::new(&mallory_program_id, &mallory_program_id) + .owner(&alice_program_id) + .executable(true, true) + .data(vec![42], vec![0]) + .verify(), + Err(InstructionError::ModifiedProgramId), + "mallory should not be able to change the account owner, if the account executable" + ); assert_eq!( Change::new(&mallory_program_id, &mallory_program_id) .owner(&alice_program_id)