parent
bb5e81c235
commit
e8d470c320
@ -1 +1 @@
|
|||||||
39620cc0d166a265d5d5022a38c5f1ec648563ae SOURCES/dotnet-v8.0.0-rc.2.23479.6.tar.gz
|
a3656c594207a2f92901d5ecc7c9a3bae6524e40 SOURCES/dotnet-v8.0.0.tar.gz
|
||||||
|
@ -1 +1 @@
|
|||||||
SOURCES/dotnet-v8.0.0-rc.2.23479.6.tar.gz
|
SOURCES/dotnet-v8.0.0.tar.gz
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Matt Thalman <mthalman@microsoft.com>
|
|
||||||
Date: Tue, 24 Oct 2023 16:20:26 -0500
|
|
||||||
Subject: [PATCH] Use correct runtime package version
|
|
||||||
|
|
||||||
---
|
|
||||||
prereqs/git-info/AllRepoVersions.props | 2 +-
|
|
||||||
prereqs/git-info/runtime.props | 4 ++--
|
|
||||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/prereqs/git-info/AllRepoVersions.props b/prereqs/git-info/AllRepoVersions.props
|
|
||||||
index 79a789e1cd..a3f3ccf094 100644
|
|
||||||
--- a/prereqs/git-info/AllRepoVersions.props
|
|
||||||
+++ b/prereqs/git-info/AllRepoVersions.props
|
|
||||||
@@ -32,7 +32,7 @@
|
|
||||||
<roslynGitCommitHash>bdd9c5ba66b00beebdc3516acc5e29b83efd89af</roslynGitCommitHash>
|
|
||||||
<roslynOutputPackageVersion>4.8.0-3.23471.11</roslynOutputPackageVersion>
|
|
||||||
<runtimeGitCommitHash>0b25e38ad32a69cd83ae246104b32449203cc71c</runtimeGitCommitHash>
|
|
||||||
- <runtimeOutputPackageVersion>8.0.0-rc.2.23475.17</runtimeOutputPackageVersion>
|
|
||||||
+ <runtimeOutputPackageVersion>8.0.0-rc.2.23479.6</runtimeOutputPackageVersion>
|
|
||||||
<sdkGitCommitHash>67e671f384bee6937630b52b02cc78e69b27e280</sdkGitCommitHash>
|
|
||||||
<sdkOutputPackageVersion>8.0.100-rc.2.23480.5</sdkOutputPackageVersion>
|
|
||||||
<sourcebuildexternalsGitCommitHash>6dbf3aaa0fc9664df86462f5c70b99800934fccd</sourcebuildexternalsGitCommitHash>
|
|
||||||
diff --git a/prereqs/git-info/runtime.props b/prereqs/git-info/runtime.props
|
|
||||||
index 546469c3a0..20c2bf8840 100644
|
|
||||||
--- a/prereqs/git-info/runtime.props
|
|
||||||
+++ b/prereqs/git-info/runtime.props
|
|
||||||
@@ -2,8 +2,8 @@
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<GitCommitHash>0b25e38ad32a69cd83ae246104b32449203cc71c</GitCommitHash>
|
|
||||||
- <OfficialBuildId>20230925.17</OfficialBuildId>
|
|
||||||
- <OutputPackageVersion>8.0.0-rc.2.23475.17</OutputPackageVersion>
|
|
||||||
+ <OfficialBuildId>20230929.6</OfficialBuildId>
|
|
||||||
+ <OutputPackageVersion>8.0.0-rc.2.23479.6</OutputPackageVersion>
|
|
||||||
<PreReleaseVersionLabel>rc.2</PreReleaseVersionLabel>
|
|
||||||
<IsStable>false</IsStable>
|
|
||||||
</PropertyGroup>
|
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"release": "8.0.0-rc.2",
|
"release": "8.0.0",
|
||||||
"channel": "8.0",
|
"channel": "8.0",
|
||||||
"tag": "v8.0.0-rc.2.23479.6",
|
"tag": "v8.0.0",
|
||||||
"sdkVersion": "8.0.100-rc.2.23502.2",
|
"sdkVersion": "8.0.100",
|
||||||
"runtimeVersion": "8.0.0-rc.2.23479.6",
|
"runtimeVersion": "8.0.0",
|
||||||
"sourceRepository": "https://github.com/dotnet/dotnet",
|
"sourceRepository": "https://github.com/dotnet/dotnet",
|
||||||
"sourceVersion": "1e872358329855089d8d14cec1f06d5b075824b5"
|
"sourceVersion": "40e7f014ff784457efffa58074549735e30772ae"
|
||||||
}
|
}
|
||||||
|
@ -1,260 +0,0 @@
|
|||||||
From 72f310a6c3dccbabf9edc29677b51ed78c87cc67 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sanjam Panda <sanjam.panda@ibm.com>
|
|
||||||
Date: Tue, 19 Sep 2023 15:16:02 +0200
|
|
||||||
Subject: [PATCH 1/3] [wasm] Endian fix for Webcil
|
|
||||||
|
|
||||||
'dotnet new blazorwasm' command failed on s390x and was throwing a not implemented exception
|
|
||||||
|
|
||||||
The issue was with with the WebCil writer and reader, specific endianness conversions relating to the webcil payload were not implemented for big endian machines.
|
|
||||||
|
|
||||||
We considered fixing the generic implementation, but there were only two structures in use: WebcilHeader and WebcilSectionHeader, so it was easier to handle them explicitly.
|
|
||||||
---
|
|
||||||
.../Microsoft.NET.WebAssembly.Webcil.csproj | 1 +
|
|
||||||
.../WebcilConverter.cs | 35 +++++++++++++-----
|
|
||||||
.../WebcilReader.cs | 37 +++++++++++++++----
|
|
||||||
3 files changed, 57 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
|
||||||
index c35eb57e80686..d09ae4a569a59 100644
|
|
||||||
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
|
||||||
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- we need to keep the version of System.Reflection.Metadata in sync with dotnet/msbuild and dotnet/sdk -->
|
|
||||||
+ <PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
|
|
||||||
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
|
|
||||||
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
index a38af7270a2da..7b882c42d579e 100644
|
|
||||||
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
@@ -2,6 +2,7 @@
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
+using System.Buffers.Binary;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Reflection.PortableExecutable;
|
|
||||||
@@ -181,9 +182,6 @@ private static void WriteHeader(Stream s, WebcilHeader header)
|
|
||||||
|
|
||||||
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
|
|
||||||
{
|
|
||||||
- // FIXME: fixup endianness
|
|
||||||
- if (!BitConverter.IsLittleEndian)
|
|
||||||
- throw new NotImplementedException();
|
|
||||||
foreach (var sectionHeader in sectionsHeaders)
|
|
||||||
{
|
|
||||||
WriteSectionHeader(s, sectionHeader);
|
|
||||||
@@ -192,16 +190,38 @@ private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHe
|
|
||||||
|
|
||||||
private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHeader)
|
|
||||||
{
|
|
||||||
+ if (!BitConverter.IsLittleEndian)
|
|
||||||
+ {
|
|
||||||
+ sectionHeader = new WebcilSectionHeader
|
|
||||||
+ (
|
|
||||||
+ virtualSize: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualSize),
|
|
||||||
+ virtualAddress: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualAddress),
|
|
||||||
+ sizeOfRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.SizeOfRawData),
|
|
||||||
+ pointerToRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.PointerToRawData)
|
|
||||||
+ );
|
|
||||||
+ }
|
|
||||||
WriteStructure(s, sectionHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ private static void WriteStructure(Stream s, WebcilHeader webcilHeader)
|
|
||||||
+ {
|
|
||||||
+ if (!BitConverter.IsLittleEndian)
|
|
||||||
+ {
|
|
||||||
+ webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
|
||||||
+ webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
|
||||||
+ webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
|
||||||
+ webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
|
||||||
+ webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
|
||||||
+ webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
|
||||||
+ webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
|
||||||
+ }
|
|
||||||
+ WriteStructure(s, webcilHeader);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
#if NETCOREAPP2_1_OR_GREATER
|
|
||||||
private static void WriteStructure<T>(Stream s, T structure)
|
|
||||||
where T : unmanaged
|
|
||||||
{
|
|
||||||
- // FIXME: fixup endianness
|
|
||||||
- if (!BitConverter.IsLittleEndian)
|
|
||||||
- throw new NotImplementedException();
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
byte* p = (byte*)&structure;
|
|
||||||
@@ -212,9 +232,6 @@ private static void WriteStructure<T>(Stream s, T structure)
|
|
||||||
private static void WriteStructure<T>(Stream s, T structure)
|
|
||||||
where T : unmanaged
|
|
||||||
{
|
|
||||||
- // FIXME: fixup endianness
|
|
||||||
- if (!BitConverter.IsLittleEndian)
|
|
||||||
- throw new NotImplementedException();
|
|
||||||
int size = Marshal.SizeOf<T>();
|
|
||||||
byte[] buffer = new byte[size];
|
|
||||||
IntPtr ptr = IntPtr.Zero;
|
|
||||||
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
|
||||||
index 4f42f82798664..ac4f9d86095a9 100644
|
|
||||||
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
|
||||||
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs
|
|
||||||
@@ -6,7 +6,7 @@
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
-
|
|
||||||
+using System.Buffers.Binary;
|
|
||||||
using System.Reflection.Metadata;
|
|
||||||
using System.Reflection.PortableExecutable;
|
|
||||||
|
|
||||||
@@ -63,14 +63,20 @@ private unsafe bool ReadHeader()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
- if (!BitConverter.IsLittleEndian)
|
|
||||||
- {
|
|
||||||
- throw new NotImplementedException("TODO: implement big endian support");
|
|
||||||
- }
|
|
||||||
fixed (byte* p = buffer)
|
|
||||||
{
|
|
||||||
header = *(WebcilHeader*)p;
|
|
||||||
}
|
|
||||||
+ if (!BitConverter.IsLittleEndian)
|
|
||||||
+ {
|
|
||||||
+ header.version_major = BinaryPrimitives.ReverseEndianness(header.version_major);
|
|
||||||
+ header.version_minor = BinaryPrimitives.ReverseEndianness(header.version_minor);
|
|
||||||
+ header.coff_sections = BinaryPrimitives.ReverseEndianness(header.coff_sections);
|
|
||||||
+ header.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_rva);
|
|
||||||
+ header.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_size);
|
|
||||||
+ header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_rva);
|
|
||||||
+ header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_size);
|
|
||||||
+ }
|
|
||||||
if (header.id[0] != 'W' || header.id[1] != 'b'
|
|
||||||
|| header.id[2] != 'I' || header.id[3] != 'L'
|
|
||||||
|| header.version_major != Internal.Constants.WC_VERSION_MAJOR
|
|
||||||
@@ -346,6 +352,7 @@ private long TranslateRVA(uint rva)
|
|
||||||
|
|
||||||
private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
|
|
||||||
{
|
|
||||||
+ WebcilSectionHeader secheader;
|
|
||||||
var sections = ImmutableArray.CreateBuilder<WebcilSectionHeader>(_header.coff_sections);
|
|
||||||
var buffer = new byte[Marshal.SizeOf<WebcilSectionHeader>()];
|
|
||||||
_stream.Seek(SectionDirectoryOffset + _webcilInWasmOffset, SeekOrigin.Begin);
|
|
||||||
@@ -357,8 +364,24 @@ private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
|
|
||||||
}
|
|
||||||
fixed (byte* p = buffer)
|
|
||||||
{
|
|
||||||
- // FIXME endianness
|
|
||||||
- sections.Add(*(WebcilSectionHeader*)p);
|
|
||||||
+ secheader = (*(WebcilSectionHeader*)p);
|
|
||||||
+ }
|
|
||||||
+ if (!BitConverter.IsLittleEndian)
|
|
||||||
+ {
|
|
||||||
+ sections.Add
|
|
||||||
+ (
|
|
||||||
+ new WebcilSectionHeader
|
|
||||||
+ (
|
|
||||||
+ virtualSize: BinaryPrimitives.ReverseEndianness(secheader.VirtualSize),
|
|
||||||
+ virtualAddress: BinaryPrimitives.ReverseEndianness(secheader.VirtualAddress),
|
|
||||||
+ sizeOfRawData: BinaryPrimitives.ReverseEndianness(secheader.SizeOfRawData),
|
|
||||||
+ pointerToRawData: BinaryPrimitives.ReverseEndianness(secheader.PointerToRawData)
|
|
||||||
+ )
|
|
||||||
+ );
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ sections.Add(secheader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sections.MoveToImmutable();
|
|
||||||
|
|
||||||
From 0c78184347335db183a38cf6bd26e2fe69160931 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= <alklig@microsoft.com>
|
|
||||||
Date: Thu, 21 Sep 2023 14:31:12 -0400
|
|
||||||
Subject: [PATCH 2/3] Fix infinite recursion
|
|
||||||
|
|
||||||
---
|
|
||||||
.../WebcilConverter.cs | 25 ++++++++-----------
|
|
||||||
1 file changed, 10 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
index 7b882c42d579e..fc95eded5bc33 100644
|
|
||||||
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
@@ -177,6 +177,16 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi
|
|
||||||
|
|
||||||
private static void WriteHeader(Stream s, WebcilHeader header)
|
|
||||||
{
|
|
||||||
+ if (!BitConverter.IsLittleEndian)
|
|
||||||
+ {
|
|
||||||
+ webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
|
||||||
+ webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
|
||||||
+ webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
|
||||||
+ webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
|
||||||
+ webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
|
||||||
+ webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
|
||||||
+ webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
|
||||||
+ }
|
|
||||||
WriteStructure(s, header);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -203,21 +213,6 @@ private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHead
|
|
||||||
WriteStructure(s, sectionHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static void WriteStructure(Stream s, WebcilHeader webcilHeader)
|
|
||||||
- {
|
|
||||||
- if (!BitConverter.IsLittleEndian)
|
|
||||||
- {
|
|
||||||
- webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
|
|
||||||
- webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
|
|
||||||
- webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
|
|
||||||
- webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
|
|
||||||
- webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
|
|
||||||
- webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
|
||||||
- webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
|
||||||
- }
|
|
||||||
- WriteStructure(s, webcilHeader);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
#if NETCOREAPP2_1_OR_GREATER
|
|
||||||
private static void WriteStructure<T>(Stream s, T structure)
|
|
||||||
where T : unmanaged
|
|
||||||
|
|
||||||
From cecf4f09f0c52340c753811098f0f2d9593049aa Mon Sep 17 00:00:00 2001
|
|
||||||
From: Aleksey Kliger <alklig@microsoft.com>
|
|
||||||
Date: Thu, 21 Sep 2023 14:36:20 -0400
|
|
||||||
Subject: [PATCH 3/3] rename var
|
|
||||||
|
|
||||||
---
|
|
||||||
src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
index fc95eded5bc33..13c34bde4b8ea 100644
|
|
||||||
--- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
+++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs
|
|
||||||
@@ -175,7 +175,7 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi
|
|
||||||
SectionStart: firstWCSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static void WriteHeader(Stream s, WebcilHeader header)
|
|
||||||
+ private static void WriteHeader(Stream s, WebcilHeader webcilHeader)
|
|
||||||
{
|
|
||||||
if (!BitConverter.IsLittleEndian)
|
|
||||||
{
|
|
||||||
@@ -187,7 +187,7 @@ private static void WriteHeader(Stream s, WebcilHeader header)
|
|
||||||
webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
|
|
||||||
webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
|
|
||||||
}
|
|
||||||
- WriteStructure(s, header);
|
|
||||||
+ WriteStructure(s, webcilHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
|
|
@ -1,416 +0,0 @@
|
|||||||
From 9aec1e3b0b9ddc02b81bd115399f8951288b261b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Tom Deseyn <tom.deseyn@gmail.com>
|
|
||||||
Date: Wed, 11 Oct 2023 18:32:20 +0200
|
|
||||||
Subject: [PATCH] Support specifying multiple directories through SSL_CERT_DIR
|
|
||||||
|
|
||||||
Co-authored-by: Jeremy Barton <jbarton@microsoft.com>
|
|
||||||
Co-authored-by: Kevin Jones <vcsjones@github.com>
|
|
||||||
---
|
|
||||||
.../OpenSslCachedSystemStoreProvider.cs | 232 +++++++++---------
|
|
||||||
.../X509Certificates/X509StoreTests.Unix.cs | 42 +++-
|
|
||||||
2 files changed, 157 insertions(+), 117 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
|
||||||
index 4c9643c01e2..e66b3d1ad11 100644
|
|
||||||
--- a/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
|
||||||
+++ b/src/runtime/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs
|
|
||||||
@@ -21,14 +21,14 @@ internal sealed class OpenSslCachedSystemStoreProvider : IStorePal
|
|
||||||
private static readonly TimeSpan s_lastWriteRecheckInterval = TimeSpan.FromSeconds(5);
|
|
||||||
private static readonly TimeSpan s_assumeInvalidInterval = TimeSpan.FromMinutes(5);
|
|
||||||
private static readonly Stopwatch s_recheckStopwatch = new Stopwatch();
|
|
||||||
- private static DirectoryInfo? s_rootStoreDirectoryInfo = SafeOpenRootDirectoryInfo();
|
|
||||||
+ private static string[]? s_rootStoreDirectories;
|
|
||||||
private static bool s_defaultRootDir;
|
|
||||||
- private static readonly FileInfo? s_rootStoreFileInfo = SafeOpenRootFileInfo();
|
|
||||||
+ private static string? s_rootStoreFile;
|
|
||||||
+ private static DateTime[]? s_directoryLastWrite;
|
|
||||||
+ private static DateTime s_fileLastWrite;
|
|
||||||
|
|
||||||
// Use non-Value-Tuple so that it's an atomic update.
|
|
||||||
private static Tuple<SafeX509StackHandle, SafeX509StackHandle>? s_nativeCollections;
|
|
||||||
- private static DateTime s_directoryCertsLastWrite;
|
|
||||||
- private static DateTime s_fileCertsLastWrite;
|
|
||||||
|
|
||||||
private readonly bool _isRoot;
|
|
||||||
|
|
||||||
@@ -93,18 +93,11 @@ public void Remove(ICertificatePal cert)
|
|
||||||
{
|
|
||||||
lock (s_recheckStopwatch)
|
|
||||||
{
|
|
||||||
- FileInfo? fileInfo = s_rootStoreFileInfo;
|
|
||||||
- DirectoryInfo? dirInfo = s_rootStoreDirectoryInfo;
|
|
||||||
-
|
|
||||||
- fileInfo?.Refresh();
|
|
||||||
- dirInfo?.Refresh();
|
|
||||||
-
|
|
||||||
if (ret == null ||
|
|
||||||
elapsed > s_assumeInvalidInterval ||
|
|
||||||
- (fileInfo != null && fileInfo.Exists && ContentWriteTime(fileInfo) != s_fileCertsLastWrite) ||
|
|
||||||
- (dirInfo != null && dirInfo.Exists && ContentWriteTime(dirInfo) != s_directoryCertsLastWrite))
|
|
||||||
+ LastWriteTimesHaveChanged())
|
|
||||||
{
|
|
||||||
- ret = LoadMachineStores(dirInfo, fileInfo);
|
|
||||||
+ ret = LoadMachineStores();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -113,9 +106,37 @@ public void Remove(ICertificatePal cert)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static Tuple<SafeX509StackHandle, SafeX509StackHandle> LoadMachineStores(
|
|
||||||
- DirectoryInfo? rootStorePath,
|
|
||||||
- FileInfo? rootStoreFile)
|
|
||||||
+ private static bool LastWriteTimesHaveChanged()
|
|
||||||
+ {
|
|
||||||
+ Debug.Assert(
|
|
||||||
+ Monitor.IsEntered(s_recheckStopwatch),
|
|
||||||
+ "LastWriteTimesHaveChanged assumes a lock(s_recheckStopwatch)");
|
|
||||||
+
|
|
||||||
+ if (s_rootStoreFile != null)
|
|
||||||
+ {
|
|
||||||
+ _ = TryStatFile(s_rootStoreFile, out DateTime lastModified);
|
|
||||||
+ if (lastModified != s_fileLastWrite)
|
|
||||||
+ {
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (s_rootStoreDirectories != null && s_directoryLastWrite != null)
|
|
||||||
+ {
|
|
||||||
+ for (int i = 0; i < s_rootStoreDirectories.Length; i++)
|
|
||||||
+ {
|
|
||||||
+ _ = TryStatDirectory(s_rootStoreDirectories[i], out DateTime lastModified);
|
|
||||||
+ if (lastModified != s_directoryLastWrite[i])
|
|
||||||
+ {
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static Tuple<SafeX509StackHandle, SafeX509StackHandle> LoadMachineStores()
|
|
||||||
{
|
|
||||||
Debug.Assert(
|
|
||||||
Monitor.IsEntered(s_recheckStopwatch),
|
|
||||||
@@ -126,61 +147,76 @@ public void Remove(ICertificatePal cert)
|
|
||||||
SafeX509StackHandle intermedStore = Interop.Crypto.NewX509Stack();
|
|
||||||
Interop.Crypto.CheckValidOpenSslHandle(intermedStore);
|
|
||||||
|
|
||||||
- DateTime newFileTime = default;
|
|
||||||
- DateTime newDirTime = default;
|
|
||||||
-
|
|
||||||
var uniqueRootCerts = new HashSet<X509Certificate2>();
|
|
||||||
var uniqueIntermediateCerts = new HashSet<X509Certificate2>();
|
|
||||||
bool firstLoad = (s_nativeCollections == null);
|
|
||||||
|
|
||||||
- if (rootStoreFile != null && rootStoreFile.Exists)
|
|
||||||
+ if (firstLoad)
|
|
||||||
{
|
|
||||||
- newFileTime = ContentWriteTime(rootStoreFile);
|
|
||||||
- ProcessFile(rootStoreFile);
|
|
||||||
+ s_rootStoreDirectories = GetRootStoreDirectories(out s_defaultRootDir);
|
|
||||||
+ s_directoryLastWrite = new DateTime[s_rootStoreDirectories.Length];
|
|
||||||
+ s_rootStoreFile = GetRootStoreFile();
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ Debug.Assert(s_rootStoreDirectories is not null);
|
|
||||||
+ Debug.Assert(s_directoryLastWrite is not null);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (s_rootStoreFile != null)
|
|
||||||
+ {
|
|
||||||
+ ProcessFile(s_rootStoreFile, out s_fileLastWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasStoreData = false;
|
|
||||||
|
|
||||||
- if (rootStorePath != null && rootStorePath.Exists)
|
|
||||||
+ for (int i = 0; i < s_rootStoreDirectories.Length; i++)
|
|
||||||
{
|
|
||||||
- newDirTime = ContentWriteTime(rootStorePath);
|
|
||||||
- hasStoreData = ProcessDir(rootStorePath);
|
|
||||||
+ hasStoreData = ProcessDir(s_rootStoreDirectories[i], out s_directoryLastWrite[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstLoad && !hasStoreData && s_defaultRootDir)
|
|
||||||
{
|
|
||||||
- DirectoryInfo etcSslCerts = new DirectoryInfo("/etc/ssl/certs");
|
|
||||||
-
|
|
||||||
- if (etcSslCerts.Exists)
|
|
||||||
+ const string DefaultCertDir = "/etc/ssl/certs";
|
|
||||||
+ hasStoreData = ProcessDir(DefaultCertDir, out DateTime lastModified);
|
|
||||||
+ if (hasStoreData)
|
|
||||||
{
|
|
||||||
- DateTime tmpTime = ContentWriteTime(etcSslCerts);
|
|
||||||
- hasStoreData = ProcessDir(etcSslCerts);
|
|
||||||
-
|
|
||||||
- if (hasStoreData)
|
|
||||||
- {
|
|
||||||
- newDirTime = tmpTime;
|
|
||||||
- s_rootStoreDirectoryInfo = etcSslCerts;
|
|
||||||
- }
|
|
||||||
+ s_rootStoreDirectories = new[] { DefaultCertDir };
|
|
||||||
+ s_directoryLastWrite = new[] { lastModified };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- bool ProcessDir(DirectoryInfo dir)
|
|
||||||
+ bool ProcessDir(string dir, out DateTime lastModified)
|
|
||||||
{
|
|
||||||
+ if (!TryStatDirectory(dir, out lastModified))
|
|
||||||
+ {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
bool hasStoreData = false;
|
|
||||||
|
|
||||||
- foreach (FileInfo file in dir.EnumerateFiles())
|
|
||||||
+ foreach (string file in Directory.EnumerateFiles(dir))
|
|
||||||
{
|
|
||||||
- hasStoreData |= ProcessFile(file);
|
|
||||||
+ hasStoreData |= ProcessFile(file, out _, skipStat: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasStoreData;
|
|
||||||
}
|
|
||||||
|
|
||||||
- bool ProcessFile(FileInfo file)
|
|
||||||
+ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false)
|
|
||||||
{
|
|
||||||
bool readData = false;
|
|
||||||
|
|
||||||
- using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb"))
|
|
||||||
+ if (skipStat)
|
|
||||||
+ {
|
|
||||||
+ lastModified = default;
|
|
||||||
+ }
|
|
||||||
+ else if (!TryStatFile(file, out lastModified))
|
|
||||||
+ {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file, "rb"))
|
|
||||||
{
|
|
||||||
// The handle may be invalid, for example when we don't have read permission for the file.
|
|
||||||
if (fileBio.IsInvalid)
|
|
||||||
@@ -274,114 +310,78 @@ bool ProcessFile(FileInfo file)
|
|
||||||
// on every call.
|
|
||||||
|
|
||||||
Volatile.Write(ref s_nativeCollections, newCollections);
|
|
||||||
- s_directoryCertsLastWrite = newDirTime;
|
|
||||||
- s_fileCertsLastWrite = newFileTime;
|
|
||||||
s_recheckStopwatch.Restart();
|
|
||||||
return newCollections;
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static FileInfo? SafeOpenRootFileInfo()
|
|
||||||
+ private static string? GetRootStoreFile()
|
|
||||||
{
|
|
||||||
string? rootFile = Interop.Crypto.GetX509RootStoreFile();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(rootFile))
|
|
||||||
{
|
|
||||||
- try
|
|
||||||
- {
|
|
||||||
- return new FileInfo(rootFile);
|
|
||||||
- }
|
|
||||||
- catch (ArgumentException)
|
|
||||||
- {
|
|
||||||
- // If SSL_CERT_FILE is set to the empty string, or anything else which gives
|
|
||||||
- // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
|
|
||||||
- }
|
|
||||||
+ return Path.GetFullPath(rootFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static DirectoryInfo? SafeOpenRootDirectoryInfo()
|
|
||||||
+ private static string[] GetRootStoreDirectories(out bool isDefault)
|
|
||||||
{
|
|
||||||
- string? rootDirectory = Interop.Crypto.GetX509RootStorePath(out s_defaultRootDir);
|
|
||||||
+ string rootDirectory = Interop.Crypto.GetX509RootStorePath(out isDefault) ?? "";
|
|
||||||
|
|
||||||
- if (!string.IsNullOrEmpty(rootDirectory))
|
|
||||||
- {
|
|
||||||
- try
|
|
||||||
- {
|
|
||||||
- return new DirectoryInfo(rootDirectory);
|
|
||||||
- }
|
|
||||||
- catch (ArgumentException)
|
|
||||||
- {
|
|
||||||
- // If SSL_CERT_DIR is set to the empty string, or anything else which gives
|
|
||||||
- // "The path is not of a legal form", then the GetX509RootStoreFile value is ignored.
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return null;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- private static DateTime ContentWriteTime(FileInfo info)
|
|
||||||
- {
|
|
||||||
- string path = info.FullName;
|
|
||||||
- string? target = Interop.Sys.ReadLink(path);
|
|
||||||
-
|
|
||||||
- if (string.IsNullOrEmpty(target))
|
|
||||||
- {
|
|
||||||
- return info.LastWriteTimeUtc;
|
|
||||||
- }
|
|
||||||
+ string[] directories = rootDirectory.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
- if (target[0] != '/')
|
|
||||||
+ for (int i = 0; i < directories.Length; i++)
|
|
||||||
{
|
|
||||||
- target = Path.Join(info.Directory?.FullName, target);
|
|
||||||
+ directories[i] = Path.GetFullPath(directories[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- try
|
|
||||||
+ // Remove duplicates.
|
|
||||||
+ if (directories.Length > 1)
|
|
||||||
{
|
|
||||||
- var targetInfo = new FileInfo(target);
|
|
||||||
-
|
|
||||||
- if (targetInfo.Exists)
|
|
||||||
+ var set = new HashSet<string>(directories, StringComparer.Ordinal);
|
|
||||||
+ if (set.Count != directories.Length)
|
|
||||||
{
|
|
||||||
- return targetInfo.LastWriteTimeUtc;
|
|
||||||
+ // Preserve the original order.
|
|
||||||
+ string[] directoriesTrimmed = new string[set.Count];
|
|
||||||
+ int j = 0;
|
|
||||||
+ for (int i = 0; i < directories.Length; i++)
|
|
||||||
+ {
|
|
||||||
+ string directory = directories[i];
|
|
||||||
+ if (set.Remove(directory))
|
|
||||||
+ {
|
|
||||||
+ directoriesTrimmed[j++] = directory;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ Debug.Assert(set.Count == 0);
|
|
||||||
+ directories = directoriesTrimmed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- catch (ArgumentException)
|
|
||||||
- {
|
|
||||||
- // If we can't load information about the link path, just treat it as not a link.
|
|
||||||
- }
|
|
||||||
|
|
||||||
- return info.LastWriteTimeUtc;
|
|
||||||
+ return directories;
|
|
||||||
}
|
|
||||||
|
|
||||||
- private static DateTime ContentWriteTime(DirectoryInfo info)
|
|
||||||
- {
|
|
||||||
- string path = info.FullName;
|
|
||||||
- string? target = Interop.Sys.ReadLink(path);
|
|
||||||
-
|
|
||||||
- if (string.IsNullOrEmpty(target))
|
|
||||||
- {
|
|
||||||
- return info.LastWriteTimeUtc;
|
|
||||||
- }
|
|
||||||
+ private static bool TryStatFile(string path, out DateTime lastModified)
|
|
||||||
+ => TryStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified);
|
|
||||||
|
|
||||||
- if (target[0] != '/')
|
|
||||||
- {
|
|
||||||
- target = Path.Join(info.Parent?.FullName, target);
|
|
||||||
- }
|
|
||||||
+ private static bool TryStatDirectory(string path, out DateTime lastModified)
|
|
||||||
+ => TryStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified);
|
|
||||||
|
|
||||||
- try
|
|
||||||
- {
|
|
||||||
- var targetInfo = new DirectoryInfo(target);
|
|
||||||
+ private static bool TryStat(string path, int fileType, out DateTime lastModified)
|
|
||||||
+ {
|
|
||||||
+ lastModified = default;
|
|
||||||
|
|
||||||
- if (targetInfo.Exists)
|
|
||||||
- {
|
|
||||||
- return targetInfo.LastWriteTimeUtc;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- catch (ArgumentException)
|
|
||||||
+ Interop.Sys.FileStatus status;
|
|
||||||
+ // Use Stat to follow links.
|
|
||||||
+ if (Interop.Sys.Stat(path, out status) < 0 ||
|
|
||||||
+ (status.Mode & Interop.Sys.FileTypes.S_IFMT) != fileType)
|
|
||||||
{
|
|
||||||
- // If we can't load information about the link path, just treat it as not a link.
|
|
||||||
+ return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return info.LastWriteTimeUtc;
|
|
||||||
+ lastModified = DateTime.UnixEpoch + TimeSpan.FromTicks(status.MTime * TimeSpan.TicksPerSecond + status.MTimeNsec / TimeSpan.NanosecondsPerTick);
|
|
||||||
+ return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs b/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
|
||||||
index 0efb6c12028..f460d6b9bd6 100644
|
|
||||||
--- a/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
|
||||||
+++ b/src/runtime/src/libraries/System.Security.Cryptography/tests/X509Certificates/X509StoreTests.Unix.cs
|
|
||||||
@@ -10,7 +10,6 @@ namespace System.Security.Cryptography.X509Certificates.Tests
|
|
||||||
{
|
|
||||||
public partial class X509StoreTests
|
|
||||||
{
|
|
||||||
-
|
|
||||||
[ConditionalFact(nameof(NotRunningAsRootAndRemoteExecutorSupported))] // root can read '2.pem'
|
|
||||||
[PlatformSpecific(TestPlatforms.Linux)] // Windows/OSX doesn't use SSL_CERT_{DIR,FILE}.
|
|
||||||
private void X509Store_MachineStoreLoadSkipsInvalidFiles()
|
|
||||||
@@ -50,6 +49,47 @@ private void X509Store_MachineStoreLoadSkipsInvalidFiles()
|
|
||||||
}, new RemoteInvokeOptions { StartInfo = psi }).Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
|
|
||||||
+ [PlatformSpecific(TestPlatforms.Linux)] // Windows/OSX doesn't use SSL_CERT_{DIR,FILE}.
|
|
||||||
+ private void X509Store_MachineStoreLoadsMutipleSslCertDirectories()
|
|
||||||
+ {
|
|
||||||
+ // Create 3 certificates and place them in two directories that will be passed
|
|
||||||
+ // using SSL_CERT_DIR.
|
|
||||||
+ string sslCertDir1 = GetTestFilePath();
|
|
||||||
+ Directory.CreateDirectory(sslCertDir1);
|
|
||||||
+ File.WriteAllBytes(Path.Combine(sslCertDir1, "1.pem"), TestData.SelfSigned1PemBytes);
|
|
||||||
+ File.WriteAllBytes(Path.Combine(sslCertDir1, "2.pem"), TestData.SelfSigned2PemBytes);
|
|
||||||
+ string sslCertDir2 = GetTestFilePath();
|
|
||||||
+ Directory.CreateDirectory(sslCertDir2);
|
|
||||||
+ File.WriteAllBytes(Path.Combine(sslCertDir2, "3.pem"), TestData.SelfSigned3PemBytes);
|
|
||||||
+
|
|
||||||
+ // Add a non-existing directory after each valid directory to verify they are ignored.
|
|
||||||
+ string sslCertDir = string.Join(Path.PathSeparator,
|
|
||||||
+ new[] {
|
|
||||||
+ sslCertDir1,
|
|
||||||
+ sslCertDir2,
|
|
||||||
+ "", // empty string
|
|
||||||
+ sslCertDir2, // duplicate directory
|
|
||||||
+ "/invalid2", // path that does not exist
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ var psi = new ProcessStartInfo();
|
|
||||||
+ psi.Environment.Add("SSL_CERT_DIR", sslCertDir);
|
|
||||||
+ // Set SSL_CERT_FILE to avoid loading the default bundle file.
|
|
||||||
+ psi.Environment.Add("SSL_CERT_FILE", "/nonexisting");
|
|
||||||
+ RemoteExecutor.Invoke(() =>
|
|
||||||
+ {
|
|
||||||
+ Assert.NotNull(Environment.GetEnvironmentVariable("SSL_CERT_DIR"));
|
|
||||||
+ using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
|
|
||||||
+ {
|
|
||||||
+ store.Open(OpenFlags.OpenExistingOnly);
|
|
||||||
+
|
|
||||||
+ // Check nr of certificates in store.
|
|
||||||
+ Assert.Equal(3, store.Certificates.Count);
|
|
||||||
+ }
|
|
||||||
+ }, new RemoteInvokeOptions { StartInfo = psi }).Dispose();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
public static bool NotRunningAsRootAndRemoteExecutorSupported => !Environment.IsPrivilegedProcess && RemoteExecutor.IsSupported;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
Loading…
Reference in new issue