Skip to content

CipherSuitesPolicy constructor throws PlatformNotSupportedException on Linux with OpenSSL 1.1.1 #61891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gunnarhelgason opened this issue Nov 21, 2021 · 10 comments · Fixed by #62973
Assignees
Labels
area-System.Net.Security bug os-linux Linux OS (any supported distro)
Milestone

Comments

@gunnarhelgason
Copy link

gunnarhelgason commented Nov 21, 2021

Description

According to the documentation, it should be possible to use the CipherSuitesPolicy class on Linux systems with OpenSSL 1.1.1 or higher or macOS. However, when using .NET 6 on Linux with OpenSSL 1.1.1, PlatformNotSupportedException is thrown. The same code works fine when using .NET 5

Reproduction Steps

Run the following program:

using System.Net.Security;

namespace csptest
{
    public static class Program
    {
        public static void Main()
        {
            var cipherSuitesPolicy = new CipherSuitesPolicy(new TlsCipherSuite[] { });
        }
    }
}

Expected behavior

Program completes successfully

Actual behavior

Exception is thrown:

Unhandled exception. System.PlatformNotSupportedException: CipherSuitesPolicy is not supported on this platform.
   at System.Net.Security.CipherSuitesPolicyPal..ctor(IEnumerable`1 allowedCipherSuites)
   at System.Net.Security.CipherSuitesPolicy..ctor(IEnumerable`1 allowedCipherSuites)
   at csptest.Program.Main() in /home/gth/csptest/Program.cs:line 9

Regression?

Seems like it, as it works fine on .NET 5

Known Workarounds

No response

Configuration

.NET
.NET 6

dotnet --list-sdks
6.0.100 [/usr/share/dotnet/sdk]
dotnet --list-runtimes
Microsoft.AspNetCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

OpenSSL
OpenSSL 1.1.1f

openssl version
OpenSSL 1.1.1f  31 Mar 2020

OS
Ubuntu 20.04.3 LTS x86_64 (completely clean install)

lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.3 LTS
Release:	20.04
Codename:	focal

Same issue also occurs on Ubuntu 21.10

Other information

No response

@ghost ghost added area-System.Net.Security untriaged New issue has not been triaged by the area owner labels Nov 21, 2021
@ghost
Copy link

ghost commented Nov 21, 2021

Tagging subscribers to this area: @dotnet/ncl, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

According to the documentation, it should be possible to use the CipherSuitesPolicy class on Linux systems with OpenSSL 1.1.1 or higher or macOS. However, when using .NET 6 on Linux with OpenSSL 1.1.1, PlatformNotSupportedException is thrown. The same code completes successfully when using .NET 5

Reproduction Steps

Run the following program:

using System.Net.Security;

namespace csptest
{
    public static class Program
    {
        public static void Main()
        {
            var cipherSuitesPolicy = new CipherSuitesPolicy(new TlsCipherSuite[] { });
        }
    }
}

Expected behavior

Program completes successfully

Actual behavior

Exception is thrown:

Unhandled exception. System.PlatformNotSupportedException: CipherSuitesPolicy is not supported on this platform.
   at System.Net.Security.CipherSuitesPolicyPal..ctor(IEnumerable`1 allowedCipherSuites)
   at System.Net.Security.CipherSuitesPolicy..ctor(IEnumerable`1 allowedCipherSuites)
   at csptest.Program.Main() in /home/gth/csptest/Program.cs:line 9

Regression?

Works fine on .NET 5

Known Workarounds

No response

Configuration

.NET
.NET 6

dotnet --list-sdks
6.0.100 [/usr/share/dotnet/sdk]
dotnet --list-runtimes
Microsoft.AspNetCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

OpenSSL

openssl version
OpenSSL 1.1.1f  31 Mar 2020

OS
Ubuntu 20.04.3 LTS x86_64 (completely clean install)

lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.3 LTS
Release:	20.04
Codename:	focal

Same issue also occurs on Ubuntu 21.10

Other information

No response

Author: gunnarhelgason
Assignees: -
Labels:

area-System.Net.Security, untriaged

Milestone: -

@wfurt wfurt removed the untriaged New issue has not been triaged by the area owner label Nov 21, 2021
@wfurt wfurt added this to the 7.0.0 milestone Nov 21, 2021
@vcsjones
Copy link
Member

Hm, well, I can reproduce it on 21.10 using 6.0-RTM installed by binaries.

@wfurt
Copy link
Member

wfurt commented Nov 21, 2021

There is something wrong with the loading. It works when I modify it as

using System.Net.Security;
using System.Net.Http;
using System;

namespace csptest
{
    public class Program
    {
        public static void Main()
        {
            try {
                var client = new HttpClient();
                _ = client.GetAsync("https://microsoft.com").GetAwaiter().GetResult();
            } catch { };

            var cipherSuitesPolicy = new CipherSuitesPolicy(new TlsCipherSuite[] { });
            Console.WriteLine("Policy OK");
        }
    }
}

API_EXISTS(SSL_CTX_set_ciphersuites) returns 0 and SSL_CTX_set_ciphersuites_ptr is null with the original code.
cc: @bartonjs

@bartonjs
Copy link
Member

I wonder if the CipherSuitesPolicy ctor functionally depends on CryptoInitializer but doesn't actually cause it to run.

@wfurt
Copy link
Member

wfurt commented Nov 22, 2021

It seems like the problem is ordering. I have two breakpoints and the following lldb/sos fragment is in order.

(lldb) bt
* thread #1, name = 'aa', stop reason = breakpoint 1.1
  * frame #0: 0x00007fffed4c849f libSystem.Security.Cryptography.Native.OpenSsl.so`CryptoNative_Tls13Supported at pal_ssl.c:581:87

(lldb) clrstack
OS Thread Id: 0x6a0c (1)
        Child SP               IP Call Site
00007FFFFFFFCB38 00007fffed4c849f [InlinedCallFrame: 00007fffffffcb38] Interop+Ssl.Tls13SupportedImpl()
00007FFFFFFFCB38 00007fff7d3e77cd [InlinedCallFrame: 00007fffffffcb38] Interop+Ssl.Tls13SupportedImpl()
00007FFFFFFFCB30 00007FFF7D3E77CD ILStubClass.IL_STUB_PInvoke()
00007FFFFFFFCBE0 00007FFF7D3E76F3 Interop+Ssl..cctor() [/home/furt/github/wfurt-runtime2/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @ 146]
00007FFFFFFFD328 00007ffff68dc457 [HelperMethodFrame: 00007fffffffd328]
00007FFFFFFFD470 00007FFF7D3E70AA System.Net.Security.CipherSuitesPolicyPal..ctor(System.Collections.Generic.IEnumerable`1<System.Net.Security.TlsCipherSuite>) [/home/furt/github/wfurt-runtime2/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs @ 31]
00007FFFFFFFD5B0 00007FFF7D3E5F79 System.Net.Security.CipherSuitesPolicy..ctor(System.Collections.Generic.IEnumerable`1<System.Net.Security.TlsCipherSuite>) [/home/furt/github/wfurt-runtime2/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs @ 23]
00007FFFFFFFD5F0 00007FFF7D3E5A4D csptest.Program.Main() [/tmp/aa/Program.cs @ 18]


(lldb) bt
* thread #1, name = 'aa', stop reason = breakpoint 2.1
  * frame #0: 0x00007fffed4c78bf libSystem.Security.Cryptography.Native.OpenSsl.so`CryptoNative_EnsureLibSslInitialized at pal_ssl.c:127:61
    frame #1: 0x00007fff7d3f3e17

(lldb) clrstack
OS Thread Id: 0x6a0c (1)
        Child SP               IP Call Site
00007FFFFFFFC298 00007fffed4c78bf [InlinedCallFrame: 00007fffffffc298] Interop+Ssl.EnsureLibSslInitialized()
00007FFFFFFFC298 00007fff7d3f3e17 [InlinedCallFrame: 00007fffffffc298] Interop+Ssl.EnsureLibSslInitialized()
00007FFFFFFFC290 00007FFF7D3F3E17 ILStubClass.IL_STUB_PInvoke()
00007FFFFFFFC330 00007FFF7D3F3B50 Interop+SslInitializer..cctor() [/home/furt/github/wfurt-runtime2/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs @ 28]
00007FFFFFFFCA88 00007ffff68dc457 [HelperMethodFrame: 00007fffffffca88]
00007FFFFFFFCBD0 00007FFF7D3F36E8 Interop+SslInitializer.Initialize() [/home/furt/github/wfurt-runtime2/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs @ 38]
00007FFFFFFFCBE0 00007FFF7D3E771E Interop+Ssl..cctor() [/home/furt/github/wfurt-runtime2/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.Initialization.cs @ 16]
00007FFFFFFFD328 00007ffff68dc457 [HelperMethodFrame: 00007fffffffd328]
00007FFFFFFFD470 00007FFF7D3E70AA System.Net.Security.CipherSuitesPolicyPal..ctor(System.Collections.Generic.IEnumerable`1<System.Net.Security.TlsCipherSuite>) [/home/furt/github/wfurt-runtime2/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs @ 31]
00007FFFFFFFD5B0 00007FFF7D3E5F79 System.Net.Security.CipherSuitesPolicy..ctor(System.Collections.Generic.IEnumerable`1<System.Net.Security.TlsCipherSuite>) [/home/furt/github/wfurt-runtime2/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicy.cs @ 23]
00007FFFFFFFD5F0 00007FFF7D3E5A4D csptest.Program.Main() [/tmp/aa/Program.cs @ 18]

So the method on Ssl class is called sooner than static constructor for given class. None of the logic seems to change in 6.0.
Adding @stephentoub and @janvorli in case they have some more insight to the mystery.

@bartonjs
Copy link
Member

bartonjs commented Nov 22, 2021

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Tls13Supported")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool Tls13SupportedImpl();
internal static readonly bool Tls13Supported = Tls13SupportedImpl();

That uses a static field initializer to populate the value. I that runs before the explicit cctor. So this has probably always had an ordering dependency on waking up something from the main crypto codepaths first; just for one reason or another it never came up.

@wfurt
Copy link
Member

wfurt commented Nov 22, 2021

I think you are right. The reason why it worked in 5.0 is

__attribute__((constructor))
static void InitializeOpenSSLShim()
{

so the function pointers were always loaded regardless of CryptoNative_EnsureLibSslInitialized being called.
That was removed in #46640.
cc: @VSadov

@bartonjs
Copy link
Member

So the fix is probably just to delay call the routine

private static int s_tls13Supported;

internal static bool Tls13Supported
{
    get
    {
        if (s_tls13Supported == 0)
        {
          s_tls13Supported = Tls13SupportedImpl() ? 1 : -1;
        }

        return s_tls13Supported == 1;
    }
}

@wfurt
Copy link
Member

wfurt commented Nov 22, 2021

That does work. I'm not sure how much we care about loosing readonly.

We could possibly fix up this particular in different ways (including the C PAL) But I'm wondering if we may have issues with other functions as well where somebody may (indirectly) call some functionality before fist SSL kicks in.

@karelz karelz added bug os-linux Linux OS (any supported distro) labels Nov 23, 2021
@wfurt wfurt self-assigned this Nov 24, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Nov 25, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Dec 17, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Dec 17, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jan 4, 2022
@wfurt wfurt reopened this Jan 4, 2022
@wfurt wfurt modified the milestones: 7.0.0, 6.0.x Jan 4, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jan 25, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 7, 2022
@wfurt
Copy link
Member

wfurt commented Feb 8, 2022

Fixed in 7.0 (main) in PR #62973 and in 6.0.3 in PR #64252.

@wfurt wfurt closed this as completed Feb 8, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Mar 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.