Do not inherit socket handles #2789
This commit is contained in:
parent
1d3090f056
commit
d3f2ca9c9a
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
|
||||||
|
{
|
||||||
|
internal static class NativeMethods
|
||||||
|
{
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
private static extern bool SetHandleInformation(IntPtr hObject, HANDLE_FLAGS dwMask, HANDLE_FLAGS dwFlags);
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum HANDLE_FLAGS : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
INHERIT = 1,
|
||||||
|
PROTECT_FROM_CLOSE = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DisableHandleInheritance(Socket socket)
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
SetHandleInformation(socket.Handle, HANDLE_FLAGS.INHERIT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -80,6 +80,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
|
||||||
IPEndPoint endPoint = _endPointInformation.IPEndPoint;
|
IPEndPoint endPoint = _endPointInformation.IPEndPoint;
|
||||||
|
|
||||||
var listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
var listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
NativeMethods.DisableHandleInheritance(listenSocket);
|
||||||
|
|
||||||
// Kestrel expects IPv6Any to bind to both IPv6 and IPv4
|
// Kestrel expects IPv6Any to bind to both IPv6 and IPv4
|
||||||
if (endPoint.Address == IPAddress.IPv6Any)
|
if (endPoint.Address == IPAddress.IPv6Any)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
{
|
||||||
|
public class HandleInheritanceTests : TestApplicationErrorLoggerLoggedTest
|
||||||
|
{
|
||||||
|
[ConditionalFact]
|
||||||
|
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "No fix available for Mac https://github.com/aspnet/KestrelHttpServer/pull/2944#issuecomment-426397600")]
|
||||||
|
public async Task SpawnChildProcess_DoesNotInheritListenHandle()
|
||||||
|
{
|
||||||
|
var hostBuilder = TransportSelector.GetWebHostBuilder()
|
||||||
|
.UseKestrel()
|
||||||
|
.ConfigureServices(AddTestLogging)
|
||||||
|
.UseUrls("http://127.0.0.1:0")
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.Run(context =>
|
||||||
|
{
|
||||||
|
return context.Response.WriteAsync("Hello World");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
using (var host = hostBuilder.Build())
|
||||||
|
{
|
||||||
|
await host.StartAsync();
|
||||||
|
|
||||||
|
var processInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd.exe" : "vi",
|
||||||
|
CreateNoWindow = true,
|
||||||
|
};
|
||||||
|
using (var process = Process.Start(processInfo))
|
||||||
|
{
|
||||||
|
var port = host.GetPort();
|
||||||
|
await host.StopAsync();
|
||||||
|
|
||||||
|
// We should not be able to connect if the handle was correctly closed and not inherited by the child process.
|
||||||
|
using (var client = new TcpClient())
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAnyAsync<SocketException>(() => client.ConnectAsync("127.0.0.1", port));
|
||||||
|
}
|
||||||
|
|
||||||
|
process.Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue