ACK: [PATCH 3/5] efi_runtime: limit the amount of data copied to userspace

Alex Hung alex.hung at canonical.com
Mon Mar 2 02:51:45 UTC 2015


On 02/06/2015 11:50 AM, Ricardo Neri wrote:
> The memory used to copy the variable name/data from userspace and back is
> supplied by the userspace. Thus, we must not write beyond the boundaries
> of the supplied memory. Otherwise, problems may arise (e.g., segmentation
> faults). However, the UEFI runtime service functions GetNextVariableName/
> GetVariable can change the size of the memory if, for instance, the
> buffer is too small. The firmware could also be defective.
> 
> Hence, only copy to the userspace the variable name/data if the UEFI
> functions return successfully. Also, in case there is a defect in the
> firmware, only copy to the userspace the variable name/data if the needed
> memory is less or equal to what the userspace provide.
> 
> Signed-off-by: Ricardo Neri <ricardo.neri-calderon at linux.intel.com>
> ---
>  efi_runtime/efi_runtime.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
> index 1935aab..4ef1754 100644
> --- a/efi_runtime/efi_runtime.c
> +++ b/efi_runtime/efi_runtime.c
> @@ -214,7 +214,7 @@ static long efi_runtime_get_variable(unsigned long arg)
>  {
>  	struct efi_getvariable __user *pgetvariable;
>  	struct efi_getvariable pgetvariable_local;
> -	unsigned long datasize;
> +	unsigned long datasize, prev_datasize;
>  	EFI_GUID vendor_guid;
>  	efi_guid_t vendor;
>  	efi_status_t status;
> @@ -246,11 +246,13 @@ static long efi_runtime_get_variable(unsigned long arg)
>  		return -ENOMEM;
>  	}
>  
> +	prev_datasize = datasize;
>  	status = efi.get_variable(name, &vendor, &attr, &datasize, data);
>  
>  	kfree(name);
>  
> -	rv = copy_to_user(pgetvariable_local.Data, data, datasize);
> +	if (status == EFI_SUCCESS && prev_datasize >= datasize)
> +		rv = copy_to_user(pgetvariable_local.Data, data, datasize);
>  	kfree(data);
>  
>  	if (rv)
> @@ -258,7 +260,7 @@ static long efi_runtime_get_variable(unsigned long arg)
>  
>  	if (put_user(status, pgetvariable_local.status))
>  		return -EFAULT;
> -	if (status == EFI_SUCCESS) {
> +	if (status == EFI_SUCCESS && prev_datasize >= datasize) {
>  		if (put_user(attr, pgetvariable_local.Attributes) ||
>  		    put_user(datasize, pgetvariable_local.DataSize))
>  			return -EFAULT;
> @@ -429,7 +431,7 @@ static long efi_runtime_get_nextvariablename(unsigned long arg)
>  {
>  	struct efi_getnextvariablename __user *pgetnextvariablename;
>  	struct efi_getnextvariablename pgetnextvariablename_local;
> -	unsigned long name_size;
> +	unsigned long name_size, prev_name_size;
>  	efi_status_t status;
>  	efi_guid_t vendor;
>  	EFI_GUID vendor_guid;
> @@ -459,10 +461,12 @@ static long efi_runtime_get_nextvariablename(unsigned long arg)
>  	if (rv)
>  		return rv;
>  
> +	prev_name_size = name_size;
>  	status = efi.get_next_variable(&name_size, name, &vendor);
>  
> -	rv = copy_ucs2_to_user_len(pgetnextvariablename_local.VariableName,
> -				   name, name_size);
> +	if (status == EFI_SUCCESS && prev_name_size >= name_size)
> +		rv = copy_ucs2_to_user_len(pgetnextvariablename_local.VariableName,
> +					   name, name_size);
>  	kfree(name);
>  
>  	if (rv)
> @@ -478,7 +482,7 @@ static long efi_runtime_get_nextvariablename(unsigned long arg)
>  	if (copy_to_user(pgetnextvariablename_local.VendorGuid,
>  			 &vendor_guid, sizeof(EFI_GUID)))
>  		return -EFAULT;
> -	if (status != EFI_SUCCESS)
> +	if (status != EFI_SUCCESS || name_size > prev_name_size)
>  		return -EINVAL;
>  	return 0;
>  }
> 


Acked-by: Alex Hung <alex.hung at canonical.com>



More information about the fwts-devel mailing list