mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
463 lines
11 KiB
C
Executable File
463 lines
11 KiB
C
Executable File
/** @file
|
|
Copyright (c) 2022, Mikhail Krichanov. All rights reserved.
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
**/
|
|
#include <Ext4Dxe.h>
|
|
|
|
#include <UserFile.h>
|
|
#include <UserGlobalVar.h>
|
|
#include <UserMemory.h>
|
|
#include <string.h>
|
|
|
|
#define MAP_TABLE_SIZE 0x100
|
|
#define CHAR_FAT_VALID 0x01
|
|
|
|
#define TO_UPPER(a) (CHAR16) ((a) <= 0xFF ? mEngUpperMap[a] : (a))
|
|
|
|
UINT8 _gPcd_FixedAtBuild_PcdUefiVariableDefaultLang[4] = { 101, 110, 103, 0 };
|
|
UINT8 _gPcd_FixedAtBuild_PcdUefiVariableDefaultPlatformLang[6] = { 101, 110, 45, 85, 83, 0 };
|
|
|
|
UINTN mFuzzOffset;
|
|
UINTN mFuzzSize;
|
|
CONST UINT8 *mFuzzPointer;
|
|
|
|
CHAR8 mEngUpperMap[MAP_TABLE_SIZE];
|
|
CHAR8 mEngLowerMap[MAP_TABLE_SIZE];
|
|
CHAR8 mEngInfoMap[MAP_TABLE_SIZE];
|
|
|
|
CHAR8 mOtherChars[] = {
|
|
'0',
|
|
'1',
|
|
'2',
|
|
'3',
|
|
'4',
|
|
'5',
|
|
'6',
|
|
'7',
|
|
'8',
|
|
'9',
|
|
'\\',
|
|
'.',
|
|
'_',
|
|
'^',
|
|
'$',
|
|
'~',
|
|
'!',
|
|
'#',
|
|
'%',
|
|
'&',
|
|
'-',
|
|
'{',
|
|
'}',
|
|
'(',
|
|
')',
|
|
'@',
|
|
'`',
|
|
'\'',
|
|
'\0'
|
|
};
|
|
|
|
VOID
|
|
UnicodeCollationInitializeMappingTables (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
|
|
//
|
|
// Initialize mapping tables for the supported languages
|
|
//
|
|
for (Index = 0; Index < MAP_TABLE_SIZE; Index++) {
|
|
mEngUpperMap[Index] = (CHAR8)Index;
|
|
mEngLowerMap[Index] = (CHAR8)Index;
|
|
mEngInfoMap[Index] = 0;
|
|
|
|
if (((Index >= 'a') && (Index <= 'z')) || ((Index >= 0xe0) && (Index <= 0xf6)) || ((Index >= 0xf8) && (Index <= 0xfe))) {
|
|
Index2 = Index - 0x20;
|
|
mEngUpperMap[Index] = (CHAR8)Index2;
|
|
mEngLowerMap[Index2] = (CHAR8)Index;
|
|
|
|
mEngInfoMap[Index] |= CHAR_FAT_VALID;
|
|
mEngInfoMap[Index2] |= CHAR_FAT_VALID;
|
|
}
|
|
}
|
|
|
|
for (Index = 0; mOtherChars[Index] != 0; Index++) {
|
|
Index2 = mOtherChars[Index];
|
|
mEngInfoMap[Index2] |= CHAR_FAT_VALID;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Performs a case-insensitive comparison of two Null-terminated strings.
|
|
|
|
@param This Protocol instance pointer.
|
|
@param Str1 A pointer to a Null-terminated string.
|
|
@param Str2 A pointer to a Null-terminated string.
|
|
|
|
@retval 0 Str1 is equivalent to Str2
|
|
@retval > 0 Str1 is lexically greater than Str2
|
|
@retval < 0 Str1 is lexically less than Str2
|
|
|
|
**/
|
|
INTN
|
|
StriColl (
|
|
IN CHAR16 *Str1,
|
|
IN CHAR16 *Str2
|
|
)
|
|
{
|
|
while (*Str1 != 0) {
|
|
if (TO_UPPER (*Str1) != TO_UPPER (*Str2)) {
|
|
break;
|
|
}
|
|
|
|
Str1 += 1;
|
|
Str2 += 1;
|
|
}
|
|
|
|
return TO_UPPER (*Str1) - TO_UPPER (*Str2);
|
|
}
|
|
|
|
/**
|
|
Initialises Unicode collation, which is needed for case-insensitive string comparisons
|
|
within the driver (a good example of an application of this is filename comparison).
|
|
|
|
@param[in] DriverHandle Handle to the driver image.
|
|
|
|
@retval EFI_SUCCESS Unicode collation was successfully initialised.
|
|
@retval !EFI_SUCCESS Failure.
|
|
**/
|
|
EFI_STATUS
|
|
Ext4InitialiseUnicodeCollation (
|
|
EFI_HANDLE DriverHandle
|
|
)
|
|
{
|
|
UnicodeCollationInitializeMappingTables ();
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Does a case-insensitive string comparison. Refer to EFI_UNICODE_COLLATION_PROTOCOL's StriColl
|
|
for more details.
|
|
|
|
@param[in] Str1 Pointer to a null terminated string.
|
|
@param[in] Str2 Pointer to a null terminated string.
|
|
|
|
@retval 0 Str1 is equivalent to Str2.
|
|
@retval >0 Str1 is lexically greater than Str2.
|
|
@retval <0 Str1 is lexically less than Str2.
|
|
**/
|
|
INTN
|
|
Ext4StrCmpInsensitive (
|
|
IN CHAR16 *Str1,
|
|
IN CHAR16 *Str2
|
|
)
|
|
{
|
|
return StriColl (Str1, Str2);
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiLibInstallAllDriverProtocols2 (
|
|
IN CONST EFI_HANDLE ImageHandle,
|
|
IN CONST EFI_SYSTEM_TABLE *SystemTable,
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
|
|
IN EFI_HANDLE DriverBindingHandle,
|
|
IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL
|
|
IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2, OPTIONAL
|
|
IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL
|
|
IN CONST EFI_DRIVER_CONFIGURATION2_PROTOCOL *DriverConfiguration2, OPTIONAL
|
|
IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics, OPTIONAL
|
|
IN CONST EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2 OPTIONAL
|
|
)
|
|
{
|
|
abort ();
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiLibUninstallAllDriverProtocols2 (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
|
|
IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL
|
|
IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2, OPTIONAL
|
|
IN CONST EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration, OPTIONAL
|
|
IN CONST EFI_DRIVER_CONFIGURATION2_PROTOCOL *DriverConfiguration2, OPTIONAL
|
|
IN CONST EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics, OPTIONAL
|
|
IN CONST EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2 OPTIONAL
|
|
)
|
|
{
|
|
abort ();
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
VOID
|
|
FreeAll (
|
|
IN CHAR16 *FileName,
|
|
IN EXT4_PARTITION *Part
|
|
)
|
|
{
|
|
FreePool (FileName);
|
|
|
|
if (Part != NULL) {
|
|
if (Part->DiskIo != NULL) {
|
|
FreePool (Part->DiskIo);
|
|
}
|
|
|
|
if (Part->BlockIo != NULL) {
|
|
if (Part->BlockIo->Media != NULL) {
|
|
FreePool (Part->BlockIo->Media);
|
|
}
|
|
|
|
FreePool (Part->BlockIo);
|
|
}
|
|
|
|
if (Part->Root != NULL) {
|
|
Ext4UnmountAndFreePartition (Part);
|
|
} else if (Part != NULL) {
|
|
FreePool (Part);
|
|
}
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
FuzzReadDisk (
|
|
IN EFI_DISK_IO_PROTOCOL *This,
|
|
IN UINT32 MediaId,
|
|
IN UINT64 Offset,
|
|
IN UINTN BufferSize,
|
|
OUT VOID *Buffer
|
|
)
|
|
{
|
|
if (Buffer == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((mFuzzSize - mFuzzOffset) < BufferSize) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CopyMem (Buffer, mFuzzPointer, BufferSize);
|
|
mFuzzPointer += BufferSize;
|
|
mFuzzOffset += BufferSize;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
INT32
|
|
LLVMFuzzerTestOneInput (
|
|
CONST UINT8 *FuzzData,
|
|
UINTN FuzzSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EXT4_PARTITION *Part;
|
|
EXT4_FILE *File;
|
|
EFI_FILE_PROTOCOL *This;
|
|
UINTN BufferSize;
|
|
VOID *Buffer;
|
|
EFI_FILE_PROTOCOL *NewHandle;
|
|
CHAR16 *FileName;
|
|
VOID *Info;
|
|
UINTN Len;
|
|
UINT64 Position;
|
|
UINT64 FileSize;
|
|
|
|
mFuzzOffset = 0;
|
|
mFuzzPointer = FuzzData;
|
|
mFuzzSize = FuzzSize;
|
|
|
|
Part = NULL;
|
|
BufferSize = 100;
|
|
|
|
//
|
|
// Construct file name
|
|
//
|
|
FileName = AllocateZeroPool (BufferSize);
|
|
if (FileName == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (FileName, BufferSize);
|
|
|
|
if ((mFuzzSize - mFuzzOffset) < BufferSize) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
CopyMem (FileName, mFuzzPointer, BufferSize - 2);
|
|
mFuzzPointer += BufferSize - 2;
|
|
mFuzzOffset += BufferSize - 2;
|
|
|
|
//
|
|
// Construct File System
|
|
//
|
|
Part = AllocateZeroPool (sizeof (EXT4_PARTITION));
|
|
if (Part == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Part, sizeof (EXT4_PARTITION));
|
|
|
|
InitializeListHead (&Part->OpenFiles);
|
|
|
|
Part->DiskIo = AllocateZeroPool (sizeof (EFI_DISK_IO_PROTOCOL));
|
|
if (Part->DiskIo == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Part->DiskIo, sizeof (EFI_DISK_IO_PROTOCOL));
|
|
|
|
Part->DiskIo->ReadDisk = FuzzReadDisk;
|
|
|
|
Part->BlockIo = AllocateZeroPool (sizeof (EFI_BLOCK_IO_PROTOCOL));
|
|
if (Part->BlockIo == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Part->BlockIo, sizeof (EFI_BLOCK_IO_PROTOCOL));
|
|
|
|
Part->BlockIo->Media = AllocateZeroPool (sizeof (EFI_BLOCK_IO_MEDIA));
|
|
if (Part->BlockIo->Media == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Part->BlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
|
|
|
|
Status = Ext4OpenSuperblock (Part);
|
|
if (EFI_ERROR (Status)) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
Part->Interface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
|
|
Part->Interface.OpenVolume = Ext4OpenVolume;
|
|
|
|
This = (EFI_FILE_PROTOCOL *)Part->Root;
|
|
|
|
//
|
|
// Test Ext4Dxe driver
|
|
//
|
|
Status = Ext4Open (This, &NewHandle, FileName, EFI_FILE_MODE_READ, 0);
|
|
if (Status == EFI_SUCCESS) {
|
|
Buffer = NULL;
|
|
BufferSize = 0;
|
|
Status = Ext4ReadFile (NewHandle, &BufferSize, Buffer);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Buffer = AllocateZeroPool (BufferSize);
|
|
if (Buffer == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Buffer, BufferSize);
|
|
|
|
Ext4ReadFile (NewHandle, &BufferSize, Buffer);
|
|
|
|
Ext4WriteFile (NewHandle, &BufferSize, Buffer);
|
|
|
|
FreePool (Buffer);
|
|
}
|
|
|
|
Len = 0;
|
|
Info = NULL;
|
|
Status = Ext4GetInfo (NewHandle, &gEfiFileInfoGuid, &Len, Info);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Info = AllocateZeroPool (Len);
|
|
Ext4GetInfo (NewHandle, &gEfiFileInfoGuid, &Len, Info);
|
|
FreePool (Info);
|
|
}
|
|
|
|
Len = 0;
|
|
Status = Ext4GetInfo (NewHandle, &gEfiFileSystemInfoGuid, &Len, Info);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Info = AllocateZeroPool (Len);
|
|
Ext4GetInfo (NewHandle, &gEfiFileSystemInfoGuid, &Len, Info);
|
|
FreePool (Info);
|
|
}
|
|
|
|
Len = 0;
|
|
Status = Ext4GetInfo (NewHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, &Len, Info);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Info = AllocateZeroPool (Len);
|
|
Ext4GetInfo (NewHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, &Len, Info);
|
|
FreePool (Info);
|
|
}
|
|
|
|
Ext4SetInfo (NewHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, Len, Info);
|
|
|
|
//
|
|
// Test position functions
|
|
//
|
|
Ext4GetPosition (NewHandle, &Position);
|
|
Ext4SetPosition (NewHandle, Position);
|
|
|
|
//
|
|
// Trying to reach the end of file and read/write it
|
|
//
|
|
Position = (UINT64)-1;
|
|
Status = Ext4SetPosition (NewHandle, Position);
|
|
if (!EFI_ERROR (Status)) {
|
|
Buffer = NULL;
|
|
BufferSize = 0;
|
|
Status = Ext4ReadFile (NewHandle, &BufferSize, Buffer);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Buffer = AllocateZeroPool (BufferSize);
|
|
if (Buffer == NULL) {
|
|
FreeAll (FileName, Part);
|
|
return 0;
|
|
}
|
|
|
|
ASAN_CHECK_MEMORY_REGION (Buffer, BufferSize);
|
|
|
|
Ext4ReadFile (NewHandle, &BufferSize, Buffer);
|
|
|
|
Ext4WriteFile (NewHandle, &BufferSize, Buffer);
|
|
|
|
FreePool (Buffer);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trying to reach out of bound of FileSize
|
|
//
|
|
File = EXT4_FILE_FROM_THIS (NewHandle);
|
|
FileSize = EXT4_INODE_SIZE (File->Inode);
|
|
if (FileSize < (UINT64)-1 - 1) {
|
|
Position = FileSize + 1;
|
|
Ext4SetPosition (NewHandle, Position);
|
|
}
|
|
|
|
Ext4Delete (NewHandle);
|
|
}
|
|
|
|
FreeAll (FileName, Part);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ENTRY_POINT (
|
|
int argc,
|
|
char **argv
|
|
)
|
|
{
|
|
uint32_t f;
|
|
uint8_t *b;
|
|
|
|
if ((b = UserReadFile ((argc > 1) ? argv[1] : "in.bin", &f)) == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "Read fail\n"));
|
|
return -1;
|
|
}
|
|
|
|
LLVMFuzzerTestOneInput (b, f);
|
|
FreePool (b);
|
|
return 0;
|
|
}
|