From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web11.7471.1679290475232002420 for ; Sun, 19 Mar 2023 22:34:51 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=BQqChODQ; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: dun.tan@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1679290491; x=1710826491; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=alt0QJ2/5QFylMhtm42Lz5xgIxjFUmlA1FwVxtvfe+k=; b=BQqChODQhNvxZv+wzAZ6eH9yBs0iG5YeGxt89i298zRH/wAJQSjgSUqa poRbASairCfd8SHOLahVPJhYt+ZjAWtCA2y+fWnh4FmwmGxKt5+M2Ohkk t3trpiFBiRQ9PUHdVVkPdGhcSbN79JYg9FduR+TKXWTsK6UJT2TxaLiDM 78iuDs9hR46bRppeRxr5Ql9bPRy8bZQYB6FOnavsgzudVumGpB6F5ytF2 VdT8K510zCDEWQ4plO2zFy+RgbVbayl/yHyn/ZMufpfxRK/i7FeEsXxF+ x4zug4YiWrv1iUgp26AJ1NKB1qf4HuebDAQThcCQS8aer33Nvy18X1Ort A==; X-IronPort-AV: E=McAfee;i="6600,9927,10654"; a="401155621" X-IronPort-AV: E=Sophos;i="5.98,274,1673942400"; d="scan'208";a="401155621" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2023 22:34:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10654"; a="770059536" X-IronPort-AV: E=Sophos;i="5.98,274,1673942400"; d="scan'208";a="770059536" Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.55.92]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Mar 2023 22:34:49 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar , Gerd Hoffmann , Zhiguang Liu Subject: [Patch V3 10/18] UefiCpuPkg/CpuPageTableLib:Modify RandomTest to check Mask/Attr Date: Mon, 20 Mar 2023 13:33:21 +0800 Message-Id: <20230320053329.410-11-dun.tan@intel.com> X-Mailer: git-send-email 2.31.1.windows.1 In-Reply-To: <20230320053329.410-1-dun.tan@intel.com> References: <20230320053329.410-1-dun.tan@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Modify RandomTest to check invalid input. When creating new page table or updating exsiting page table: 1.If set [LinearAddress, LinearAddress+Length] to non-preset, all other attributes should not be provided. 2.If [LinearAddress, LinearAddress+Length] contain non-present range, the Returnstatus of PageTableMap() should be InvalidParameter when: 2.1Some of attributes are not provided when mapping non-present range to present. 2.2Set any other attribute without setting the non-present range to Present. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann Cc: Zhiguang Liu --- UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c | 6 +++++- 2 files changed, 130 insertions(+), 25 deletions(-) diff --git a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c index 52eb9daa10..eb621e6e59 100644 --- a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c +++ b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c @@ -273,6 +273,27 @@ ValidateAndRandomeModifyPageTable ( return Status; } +/** + Remove the last MAP_ENTRY in MapEntrys. + + @param MapEntrys Pointer to MapEntrys buffer +**/ +VOID +RemoveLastMapEntry ( + IN OUT MAP_ENTRYS *MapEntrys + ) +{ + UINTN MapsIndex; + + if (MapEntrys->Count == 0) { + return; + } + + MapsIndex = MapEntrys->Count - 1; + ZeroMem (&(MapEntrys->Maps[MapsIndex]), sizeof (MAP_ENTRY)); + MapEntrys->Count = MapsIndex; +} + /** Generate single random map entry. The map entry can be the input of function PageTableMap @@ -327,7 +348,16 @@ GenerateSingleRandomMapEntry ( MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64; } else { MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; - MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; + if (RandomBoolean (5)) { + // + // The probability to get random Mask should be small since all bits of a random number + // have a high probability of containing 0, which may be a invalid input. + // + MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64; + } else { + MapEntrys->Maps[MapsIndex].Mask.Uint64 = MAX_UINT64; + } + if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) { MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF; } @@ -337,15 +367,7 @@ GenerateSingleRandomMapEntry ( MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = MapEntrys->Maps[MapsIndex].LinearAddress >> 12; MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0xFFFFFFFFFF; } else { - // - // Todo: If the mask bit for base address is zero, when dump the pagetable, every entry mapping to physical address zeor. - // This means the map count will be a large number, and impossible to finish in proper time. - // Need to avoid such case when remove the Random option ONLY_ONE_ONE_MAPPING - // MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)])>> 12; - if (RandomBoolean (50)) { - MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0; - } } MapEntrys->Count += 1; @@ -608,23 +630,61 @@ SingleMapEntryTest ( IN UINTN InitMapCount ) { - UINTN MapsIndex; - RETURN_STATUS Status; - UINTN PageTableBufferSize; - VOID *Buffer; - IA32_MAP_ENTRY *Map; - UINTN MapCount; - UINTN Index; - UINTN KeyPointCount; - UINTN NewKeyPointCount; - UINT64 *KeyPointBuffer; - UINTN Level; - UINT64 Value; - UNIT_TEST_STATUS TestStatus; - - MapsIndex = MapEntrys->Count; + UINTN MapsIndex; + RETURN_STATUS Status; + UINTN PageTableBufferSize; + VOID *Buffer; + IA32_MAP_ENTRY *Map; + UINTN MapCount; + UINTN Index; + UINTN KeyPointCount; + UINTN NewKeyPointCount; + UINT64 *KeyPointBuffer; + UINTN Level; + UINT64 Value; + UNIT_TEST_STATUS TestStatus; + IA32_MAP_ATTRIBUTE *Mask; + IA32_MAP_ATTRIBUTE *Attribute; + UINT64 PreviousAddress; + UINT64 RangeLimit; + BOOLEAN IsNotPresent; + + MapsIndex = MapEntrys->Count; + MapCount = 0; + PreviousAddress = 0; + IsNotPresent = FALSE; GenerateSingleRandomMapEntry (MaxAddress, MapEntrys); + RangeLimit = MapEntrys->Maps[MapsIndex].LinearAddress + MapEntrys->Maps[MapsIndex].Length; + Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount); + + if (MapCount != 0) { + UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); + Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY))); + ASSERT (Map != NULL); + Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount); + } + + // + // Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range. + // + if (MapEntrys->Maps[MapsIndex].Length > 0) { + for (Index = 0; Index < MapCount; Index++) { + if ((PreviousAddress < Map[Index].LinearAddress) && + (MapEntrys->Maps[MapsIndex].LinearAddress < Map[Index].LinearAddress) && (RangeLimit > PreviousAddress)) + { + // + // MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table. + // + break; + } + PreviousAddress = Map[Index].LinearAddress + Map[Index].Length; + } + + if (PreviousAddress < RangeLimit) { + IsNotPresent = TRUE; + } + } PageTableBufferSize = 0; Status = PageTableMap ( @@ -637,6 +697,47 @@ SingleMapEntryTest ( &MapEntrys->Maps[MapsIndex].Attribute, &MapEntrys->Maps[MapsIndex].Mask ); + + Attribute = &MapEntrys->Maps[MapsIndex].Attribute; + Mask = &MapEntrys->Maps[MapsIndex].Mask; + // + // If set [LinearAddress, LinearAddress+Attribute] to not preset, all + // other attributes should not be provided. + // + if ((MapEntrys->Maps[MapsIndex].Length > 0) && (Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) { + RemoveLastMapEntry (MapEntrys); + UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); + return UNIT_TEST_PASSED; + } + + // + // Return Status for non-present range also should be InvalidParameter when: + // 1. Some of attributes are not provided when mapping non-present range to present. + // 2. Set any other attribute without setting the non-present range to Present. + // + if (IsNotPresent) { + if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) { + // + // Creating new page table or remapping non-present range to present. + // + if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) || + (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) || + (Mask->Bits.PageTableBaseAddress == 0) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0)) + { + RemoveLastMapEntry (MapEntrys); + UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); + return UNIT_TEST_PASSED; + } + } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) { + // + // Only change other attributes for non-present range is not permitted. + // + RemoveLastMapEntry (MapEntrys); + UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); + return UNIT_TEST_PASSED; + } + } + if (PageTableBufferSize != 0) { UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); diff --git a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c index 5bd70c0f65..10fdee2f94 100644 --- a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c +++ b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/TestHelper.c @@ -1,7 +1,7 @@ /** @file helper file for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class - Copyright (c) 2022, Intel Corporation. All rights reserved.
+ Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -171,6 +171,10 @@ IsPageTableValid ( UNIT_TEST_STATUS Status; IA32_PAGING_ENTRY *PagingEntry; + if (PageTable == 0) { + return UNIT_TEST_PASSED; + } + if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) { // // 32bit paging is never supported. -- 2.31.1.windows.1