Verify BPF ELF during finalize (#7266)
This commit is contained in:
		| @@ -34,6 +34,13 @@ pub fn create_vm(prog: &[u8]) -> Result<(EbpfVm, MemoryRegion), Error> { | |||||||
|     Ok((vm, heap_region)) |     Ok((vm, heap_region)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | pub fn check_elf(prog: &[u8]) -> Result<(), Error> { | ||||||
|  |     let mut vm = EbpfVm::new(None)?; | ||||||
|  |     vm.set_verifier(bpf_verifier::check)?; | ||||||
|  |     vm.set_elf(&prog)?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  |  | ||||||
| fn serialize_parameters( | fn serialize_parameters( | ||||||
|     program_id: &Pubkey, |     program_id: &Pubkey, | ||||||
|     keyed_accounts: &mut [KeyedAccount], |     keyed_accounts: &mut [KeyedAccount], | ||||||
| @@ -118,6 +125,11 @@ pub fn process_instruction( | |||||||
|                     return Err(InstructionError::MissingRequiredSignature); |                     return Err(InstructionError::MissingRequiredSignature); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |                 if let Err(e) = check_elf(&program.account.data) { | ||||||
|  |                     warn!("Invalid ELF: {}", e); | ||||||
|  |                     return Err(InstructionError::InvalidAccountData); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 rent::verify_rent_exemption(&program, &rent)?; |                 rent::verify_rent_exemption(&program, &rent)?; | ||||||
|  |  | ||||||
|                 program.account.executable = true; |                 program.account.executable = true; | ||||||
| @@ -244,7 +256,11 @@ mod tests { | |||||||
|         let program_id = Pubkey::new_rand(); |         let program_id = Pubkey::new_rand(); | ||||||
|         let program_key = Pubkey::new_rand(); |         let program_key = Pubkey::new_rand(); | ||||||
|         let rent_key = rent::id(); |         let rent_key = rent::id(); | ||||||
|  |         let mut file = File::open("test_elfs/noop.so").expect("file open failed"); | ||||||
|  |         let mut elf = Vec::new(); | ||||||
|  |         file.read_to_end(&mut elf).unwrap(); | ||||||
|         let mut program_account = Account::new(1, 0, &program_id); |         let mut program_account = Account::new(1, 0, &program_id); | ||||||
|  |         program_account.data = elf; | ||||||
|         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, false, &mut program_account)]; |         let mut keyed_accounts = vec![KeyedAccount::new(&program_key, false, &mut program_account)]; | ||||||
|         let ix_data = bincode::serialize(&LoaderInstruction::Finalize).unwrap(); |         let ix_data = bincode::serialize(&LoaderInstruction::Finalize).unwrap(); | ||||||
|  |  | ||||||
| @@ -273,6 +289,17 @@ mod tests { | |||||||
|             process_instruction(&program_id, &mut keyed_accounts, &ix_data) |             process_instruction(&program_id, &mut keyed_accounts, &ix_data) | ||||||
|         ); |         ); | ||||||
|         assert!(keyed_accounts[0].account.executable); |         assert!(keyed_accounts[0].account.executable); | ||||||
|  |  | ||||||
|  |         // Case: Finalize | ||||||
|  |         program_account.data[0] = 0; // bad elf | ||||||
|  |         let mut keyed_accounts = vec![ | ||||||
|  |             KeyedAccount::new(&program_key, true, &mut program_account), | ||||||
|  |             KeyedAccount::new(&rent_key, false, &mut rent_account), | ||||||
|  |         ]; | ||||||
|  |         assert_eq!( | ||||||
|  |             Err(InstructionError::InvalidAccountData), | ||||||
|  |             process_instruction(&program_id, &mut keyed_accounts, &ix_data) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user