Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions GblChainloadPkg/Library/ProtocolHookLib/InstallAll.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,101 @@

#include "HookCommon.h"

#define GBL_HOOK_REGISTRY_MAGIC SIGNATURE_32 ('G', 'B', 'H', 'K')
#define GBL_HOOK_REGISTRY_VERSION 1u

typedef struct {
UINT32 Magic;
UINT32 Version;
VOID *Owner;
UINT32 Mode;
} GBL_HOOK_REGISTRY;

STATIC EFI_GUID mGblHookRegistryGuid = {
0x67c2eab0, 0x792f, 0x46aa,
{ 0x9d, 0x2f, 0x3e, 0x1d, 0x84, 0x12, 0x5c, 0x91 }
};
STATIC GBL_HOOK_REGISTRY mGblHookRegistry = {
GBL_HOOK_REGISTRY_MAGIC,
GBL_HOOK_REGISTRY_VERSION,
NULL,
0
};

STATIC VOID *
HookOwnerToken (VOID)
{
return (VOID *)&mGblHookRegistry;
}

STATIC GBL_HOOK_REGISTRY *
FindHookRegistry (VOID)
{
UINTN Index;

if (gST == NULL) {
return NULL;
}

for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (&gST->ConfigurationTable[Index].VendorGuid,
&mGblHookRegistryGuid)) {
GBL_HOOK_REGISTRY *Registry;

Registry = (GBL_HOOK_REGISTRY *)gST->ConfigurationTable[Index].VendorTable;
if (Registry != NULL &&
Registry->Magic == GBL_HOOK_REGISTRY_MAGIC &&
Registry->Version == GBL_HOOK_REGISTRY_VERSION &&
Registry->Owner != NULL) {
return Registry;
}
return NULL;
}
}

return NULL;
}

STATIC EFI_STATUS
CheckNoExistingHooks (VOID)
{
GBL_HOOK_REGISTRY *Existing;

Existing = FindHookRegistry ();
if (Existing == NULL) {
return EFI_SUCCESS;
}

if (Existing->Mode != (UINT32)GBL_MODE) {
Print (L"ProtocolHookLib: FATAL — existing hook mode %u mismatches current mode %u\n",
Existing->Mode,
(UINT32)GBL_MODE);
} else {
Print (L"ProtocolHookLib: FATAL — hooks already active for mode %u; hard reset before re-running boot-efi\n",
Existing->Mode);
}
return EFI_ALREADY_STARTED;
}

STATIC EFI_STATUS
RegisterHookMarker (VOID)
{
EFI_STATUS Status;

mGblHookRegistry.Owner = HookOwnerToken ();
mGblHookRegistry.Mode = (UINT32)GBL_MODE;

/* Detect-only marker: this image-static record is valid for normal use
because successful StartImage() and fallback FastbootLib keep the current
GBL image resident. It is deliberately not a heap/runtime object; hard
reset is the recovery boundary for stale Qualcomm UEFI session state. */
Status = gBS->InstallConfigurationTable (&mGblHookRegistryGuid, &mGblHookRegistry);
if (EFI_ERROR (Status)) {
mGblHookRegistry.Owner = NULL;
}
return Status;
}

EFI_STATUS
EFIAPI
ProtocolHook_InstallAll (
Expand All @@ -38,6 +133,18 @@ ProtocolHook_InstallAll (
}
ZeroMem (Result, sizeof (*Result));

Status = CheckNoExistingHooks ();
if (EFI_ERROR (Status)) {
return Status;
}

Status = RegisterHookMarker ();
if (EFI_ERROR (Status)) {
Print (L"ProtocolHookLib: FATAL — hook registry install failed (%r), aborting chain-load\n",
Status);
return Status;
}

/* 1. VerifiedBoot -- required for mode-1 fakelock/persistence overlay;
optional observation-only wrapper in mode-0. */
Status = InstallVerifiedBootHook ();
Expand Down
25 changes: 25 additions & 0 deletions tests/048_hook_registry_lint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# 048_hook_registry_lint.sh — assert same-session hook detection stays small
# and does not grow into protocol-slot uninstall machinery.
set -euo pipefail
cd "$(dirname "$0")/.."

PHL="GblChainloadPkg/Library/ProtocolHookLib"

grep -q 'mGblHookRegistryGuid' "$PHL/InstallAll.c" \
|| { echo "FAIL: missing hook registry GUID"; exit 1; }
grep -q 'CheckNoExistingHooks' "$PHL/InstallAll.c" \
|| { echo "FAIL: missing existing-hook registry check"; exit 1; }
grep -q 'existing hook mode' "$PHL/InstallAll.c" \
|| { echo "FAIL: cross-mode registry reuse must fail closed"; exit 1; }
grep -q 'hard reset before re-running boot-efi' "$PHL/InstallAll.c" \
|| { echo "FAIL: same-mode rerun warning must name hard reset recovery"; exit 1; }
grep -q 'hook registry install failed' "$PHL/InstallAll.c" \
|| { echo "FAIL: registry install failure must fail closed before hooks"; exit 1; }

if grep -R -n 'ProtocolHook_UninstallAll\|Uninstall.*Hook' \
GblChainloadPkg/Include/Library/ProtocolHookLib.h "$PHL"; then
echo "FAIL: detect-only registry PR must not add hook uninstall machinery"; exit 1
fi

echo "ok 048_hook_registry_lint"
2 changes: 2 additions & 0 deletions tests/runall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ echo "== 046_mode1_protocol_hook_lint =="
bash tests/046_mode1_protocol_hook_lint.sh
echo "== 047_cleanup_lint =="
bash tests/047_cleanup_lint.sh
echo "== 048_hook_registry_lint =="
bash tests/048_hook_registry_lint.sh
echo "== 042_dynamic_patch_harness =="
bash tests/042_dynamic_patch_harness.sh
echo "== 051_gbl_root_canoe_regression =="
Expand Down
Loading