[efi] Nullify interfaces and leak memory on uninstallation failure

The UEFI specification allows uninstallation of a protocol interface
to fail.  There is no sensible way for code to react to this, since
uninstallation is likely to be taking place on a code path that cannot
itself fail (e.g. a code path that is itself a failure path).

Where the protocol structure exists within a dynamically allocated
block of memory, this leads to possible use-after-free bugs.  Work
around this unfortunate design choice by nullifying the protocol
(i.e. overwriting the method pointers with no-ops) and leaking the
memory containing the protocol structure.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2020-10-26 15:10:18 +00:00
parent 86c6c79fcd
commit 5b41b9a80f
7 changed files with 737 additions and 50 deletions

View File

@@ -0,0 +1,31 @@
#ifndef _IPXE_EFI_NULL_H
#define _IPXE_EFI_NULL_H
/** @file
*
* EFI null interfaces
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/AppleNetBoot.h>
#include <ipxe/efi/Protocol/BlockIo.h>
#include <ipxe/efi/Protocol/ComponentName2.h>
#include <ipxe/efi/Protocol/HiiConfigAccess.h>
#include <ipxe/efi/Protocol/LoadFile.h>
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <ipxe/efi/Protocol/PxeBaseCode.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
extern void efi_nullify_snp ( EFI_SIMPLE_NETWORK_PROTOCOL *snp );
extern void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii );
extern void efi_nullify_name2 ( EFI_COMPONENT_NAME2_PROTOCOL *name2 );
extern void efi_nullify_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file );
extern void efi_nullify_hii ( EFI_HII_CONFIG_ACCESS_PROTOCOL *hii );
extern void efi_nullify_block ( EFI_BLOCK_IO_PROTOCOL *block );
extern void efi_nullify_pxe ( EFI_PXE_BASE_CODE_PROTOCOL *pxe );
extern void efi_nullify_apple ( EFI_APPLE_NET_BOOT_PROTOCOL *apple );
#endif /* _IPXE_EFI_NULL_H */

View File

@@ -76,7 +76,7 @@ struct efi_snp_device {
};
extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
extern int efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle );
extern struct efi_snp_device * last_opened_snpdev ( void );
extern void efi_snp_add_claim ( int delta );