efi_loader: variable: keep temporary buffer during the authentication
This is a bug fix; Setting an authenticated variable may fail due to a memory corruption in the authentication. A temporary buffer will, if needed, be allocated to parse a variable's authentication data, and some portion of buffer, specifically signer's certificates, will be referenced by efi_signature_verify(). So the buffer should be kept valid until the authentication process is finished. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
		
							parent
							
								
									bc78d22d0f
								
							
						
					
					
						commit
						0658bb29b0
					
				|  | @ -37,16 +37,21 @@ static u8 pkcs7_hdr[] = { | |||
|  * efi_variable_parse_signature - parse a signature in variable | ||||
|  * @buf:	Pointer to variable's value | ||||
|  * @buflen:	Length of @buf | ||||
|  * @tmpbuf:	Pointer to temporary buffer | ||||
|  * | ||||
|  * Parse a signature embedded in variable's value and instantiate | ||||
|  * a pkcs7_message structure. Since pkcs7_parse_message() accepts only | ||||
|  * pkcs7's signedData, some header needed be prepended for correctly | ||||
|  * parsing authentication data, particularly for variable's. | ||||
|  * A temporary buffer will be allocated if needed, and it should be | ||||
|  * kept valid during the authentication because some data in the buffer | ||||
|  * will be referenced by efi_signature_verify(). | ||||
|  * | ||||
|  * Return:	Pointer to pkcs7_message structure on success, NULL on error | ||||
|  */ | ||||
| static struct pkcs7_message *efi_variable_parse_signature(const void *buf, | ||||
| 							  size_t buflen) | ||||
| 							  size_t buflen, | ||||
| 							  u8 **tmpbuf) | ||||
| { | ||||
| 	u8 *ebuf; | ||||
| 	size_t ebuflen, len; | ||||
|  | @ -59,7 +64,9 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf, | |||
| 	if (buflen > sizeof(pkcs7_hdr) && | ||||
| 	    !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { | ||||
| 		msg = pkcs7_parse_message(buf, buflen); | ||||
| 		goto out; | ||||
| 		if (IS_ERR(msg)) | ||||
| 			return NULL; | ||||
| 		return msg; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -94,12 +101,12 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf, | |||
| 
 | ||||
| 	msg = pkcs7_parse_message(ebuf, ebuflen); | ||||
| 
 | ||||
| 	if (IS_ERR(msg)) { | ||||
| 		free(ebuf); | ||||
| 
 | ||||
| out: | ||||
| 	if (IS_ERR(msg)) | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	*tmpbuf = ebuf; | ||||
| 	return msg; | ||||
| } | ||||
| 
 | ||||
|  | @ -136,6 +143,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable, | |||
| 	struct efi_time timestamp; | ||||
| 	struct rtc_time tm; | ||||
| 	u64 new_time; | ||||
| 	u8 *ebuf; | ||||
| 	enum efi_auth_var_type var_type; | ||||
| 	efi_status_t ret; | ||||
| 
 | ||||
|  | @ -143,6 +151,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable, | |||
| 	truststore = NULL; | ||||
| 	truststore2 = NULL; | ||||
| 	regs = NULL; | ||||
| 	ebuf = NULL; | ||||
| 	ret = EFI_SECURITY_VIOLATION; | ||||
| 
 | ||||
| 	if (*data_size < sizeof(struct efi_variable_authentication_2)) | ||||
|  | @ -204,9 +213,12 @@ static efi_status_t efi_variable_authenticate(u16 *variable, | |||
| 	/* variable's signature list */ | ||||
| 	if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info)) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	/* ebuf should be kept valid during the authentication */ | ||||
| 	var_sig = efi_variable_parse_signature(auth->auth_info.cert_data, | ||||
| 					       auth->auth_info.hdr.dwLength | ||||
| 						   - sizeof(auth->auth_info)); | ||||
| 						   - sizeof(auth->auth_info), | ||||
| 					       &ebuf); | ||||
| 	if (!var_sig) { | ||||
| 		EFI_PRINT("Parsing variable's signature failed\n"); | ||||
| 		goto err; | ||||
|  | @ -262,6 +274,7 @@ err: | |||
| 	efi_sigstore_free(truststore); | ||||
| 	efi_sigstore_free(truststore2); | ||||
| 	pkcs7_free_message(var_sig); | ||||
| 	free(ebuf); | ||||
| 	free(regs); | ||||
| 
 | ||||
| 	return ret; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue