From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web10.19850.1677837828807486048 for ; Fri, 03 Mar 2023 02:04:00 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=dzWvHnHP; spf=pass (domain: intel.com, ip: 134.134.136.126, 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=1677837840; x=1709373840; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cxcgWKaUzQO7/Sj9ui3VWmA6a7E+S4RjJ7puIPR9lk4=; b=dzWvHnHPG9i6cI1nuuPxo++IIn4lH9r76EZEJBrnles8m3IRy4bSWp4b tc20/vTEKMcC2Q+2qeRblvi1MKREQUQSh+pFi5OQlzGOzfRC34Wa9TqkF gC70thr8hjipI5a9niFw370ZwPbI0KfI8lH2XPh9czCxPxszoM2s3OO4P wQ9pM1NdQf/r7RaneYjP1x9z1Js1WkohIvmAxwx+lqvz+ObQoTqatO0Ni cT4bAvfPYr1h1+Lb3OMJ8l6wX2vc6j8QFmCs/3Zx0QY5RbK3DuqsnXTaa OZ+VTgVWVQY/voeHvATOef2/bkw48LgC5O4bXB1YX3Z/HkSFesG2Mos3n Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10637"; a="318831753" X-IronPort-AV: E=Sophos;i="5.98,230,1673942400"; d="scan'208";a="318831753" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Mar 2023 02:04:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10637"; a="818421061" X-IronPort-AV: E=Sophos;i="5.98,230,1673942400"; d="scan'208";a="818421061" Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.55.92]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Mar 2023 02:03:58 -0800 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar , Gerd Hoffmann , Zhiguang Liu Subject: [PATCH 5/6] UefiCpuPkg/CpuPageTableLib: Modify RandomTest to check Mask Date: Fri, 3 Mar 2023 18:03:35 +0800 Message-Id: <20230303100336.2138-6-dun.tan@intel.com> X-Mailer: git-send-email 2.31.1.windows.1 In-Reply-To: <20230303100336.2138-1-dun.tan@intel.com> References: <20230303100336.2138-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 mapping not-present range in existing page table, if any non-reserved field of input Mask are 0, the return status of PageTableMap () should be RETURN_INVALID_PARAMETER. 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 | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------- 1 file changed, 120 insertions(+), 44 deletions(-) diff --git a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c index 97a388ca1c..69d01db451 100644 --- a/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c +++ b/UefiCpuPkg/Library/CpuPageTableLib/UnitTest/RandomTest.c @@ -81,22 +81,6 @@ LocalRandomBytes ( } } -/** - Return a random boolean. - - @return boolean -**/ -BOOLEAN -RandomBoolean ( - VOID - ) -{ - BOOLEAN Value; - - LocalRandomBytes ((UINT8 *)&Value, sizeof (BOOLEAN)); - return Value%2; -} - /** Return a 32bit random number. @@ -139,6 +123,21 @@ Random64 ( return (UINT64)(Value % (Limit - Start + 1)) + Start; } +/** + Returns true with the percentage of input Probability. + + @param[in] Probability The percentage to return true. + + @return boolean +**/ +BOOLEAN +RandomBoolean ( + UINT8 Probability + ) +{ + return ((Probability > ((UINT8)Random64 (0, 100))) ? TRUE : FALSE); +} + /** Check if the Page table entry is valid @@ -178,7 +177,7 @@ ValidateAndRandomeModifyPageTablePageTableEntry ( UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64), PagingEntry->Uint64); } - if ((RandomNumber < 100) && RandomBoolean ()) { + if ((RandomNumber < 100) && RandomBoolean (50)) { RandomNumber++; if (Level == 1) { TempPhysicalBase = PagingEntry->Pte4K.Bits.PageTableBaseAddress; @@ -211,7 +210,7 @@ ValidateAndRandomeModifyPageTablePageTableEntry ( UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskNoLeaf[Level].Uint64), PagingEntry->Uint64); } - if ((RandomNumber < 100) && RandomBoolean ()) { + if ((RandomNumber < 100) && RandomBoolean (50)) { RandomNumber++; TempPhysicalBase = PagingEntry->Pnle.Bits.PageTableBaseAddress; @@ -274,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 @@ -299,7 +319,7 @@ GenerateSingleRandomMapEntry ( // // use AlignedTable to avoid that a random number can be very hard to be 1G or 2M aligned // - if ((MapsIndex != 0) && (RandomBoolean ())) { + if ((MapsIndex != 0) && (RandomBoolean (50))) { FormerLinearAddress = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].LinearAddress; if (FormerLinearAddress < 2 * (UINT64)SIZE_1GB) { FormerLinearAddressBottom = 0; @@ -323,12 +343,21 @@ GenerateSingleRandomMapEntry ( // MapEntrys->Maps[MapsIndex].Length = Random64 (0, MIN (MaxAddress - MapEntrys->Maps[MapsIndex].LinearAddress, 10 * (UINT64)SIZE_1GB)) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)]; - if ((MapsIndex != 0) && (RandomBoolean ())) { + if ((MapsIndex != 0) && (RandomBoolean (50))) { MapEntrys->Maps[MapsIndex].Attribute.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Attribute.Uint64; 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; } @@ -338,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 ()) { - MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0; - } } MapEntrys->Count += 1; @@ -609,23 +630,65 @@ 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; + UINTN PreviousAddress; + BOOLEAN IsNotPresent; + + MapsIndex = MapEntrys->Count; + MapCount = 0; + PreviousAddress = 0; + IsNotPresent = FALSE; GenerateSingleRandomMapEntry (MaxAddress, MapEntrys); + Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount); + + // + // Return Status should be InvalidParameter when: + // 1. MapEntrys->Maps[MapsIndex] contains not-present range. + // 2. MapEntrys->Maps[MapsIndex].Mask contains zero value field. + // + if (MapEntrys->Maps[MapsIndex].Length > 0) { + 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); + + if (Map[MapCount - 1].LinearAddress + Map[MapCount - 1].Length < MapEntrys->Maps[MapsIndex].LinearAddress + MapEntrys->Maps[MapsIndex].Length) { + IsNotPresent = TRUE; + } else { + for (Index = 0; Index < MapCount; Index++) { + if ((PreviousAddress < Map[Index].LinearAddress) && + (MapEntrys->Maps[MapsIndex].LinearAddress < Map[Index].LinearAddress) && + ((MapEntrys->Maps[MapsIndex].LinearAddress + MapEntrys->Maps[MapsIndex].Length) > PreviousAddress)) + { + // + // MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table. + // + IsNotPresent = TRUE; + break; + } + + PreviousAddress = (UINTN)(Map[Index].LinearAddress + Map[Index].Length); + } + } + } else { + IsNotPresent = TRUE; + } + } PageTableBufferSize = 0; Status = PageTableMap ( @@ -638,6 +701,19 @@ SingleMapEntryTest ( &MapEntrys->Maps[MapsIndex].Attribute, &MapEntrys->Maps[MapsIndex].Mask ); + + Mask = &MapEntrys->Maps[MapsIndex].Mask; + if (((Mask->Bits.Present == 0) || (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)) && + IsNotPresent) + { + RemoveLastMapEntry (MapEntrys); + UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER); + return UNIT_TEST_PASSED; + } + if (PageTableBufferSize != 0) { UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL); -- 2.31.1.windows.1