Skip to content
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

Make sure that shared memory object name meets the length requirements #64099

Merged
merged 11 commits into from
Jan 25, 2022
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using Microsoft.Win32.SafeHandles;

namespace System.IO.MemoryMappedFiles
Expand Down Expand Up @@ -173,9 +174,6 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
private static FileStream? CreateSharedBackingObjectUsingMemory(
Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability)
{
// The POSIX shared memory object name must begin with '/'. After that we just want something short and unique.
string mapName = string.Create(null, stackalloc char[128], $"/corefx_map_{Guid.NewGuid():N}");

// Determine the flags to use when creating the shared memory object
Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ?
Interop.Sys.OpenFlags.O_RDWR :
Expand All @@ -191,22 +189,31 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0)
perms |= Interop.Sys.Permissions.S_IXUSR;

// Create the shared memory object.
SafeFileHandle fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms);
if (fd.IsInvalid)
string mapName;
SafeFileHandle fd;

do
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (errorInfo.Error == Interop.Error.ENOTSUP)
mapName = GenerateMapName();
fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); // Create the shared memory object.

if (fd.IsInvalid)
{
// If ShmOpen is not supported, fall back to file backing object.
// Note that the System.Native shim will force this failure on platforms where
// the result of native shm_open does not work well with our subsequent call
// to mmap.
return null;
}
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved

throw Interop.GetExceptionForIoErrno(errorInfo);
}
if (errorInfo.Error == Interop.Error.ENOTSUP)
{
// If ShmOpen is not supported, fall back to file backing object.
// Note that the System.Native shim will force this failure on platforms where
// the result of native shm_open does not work well with our subsequent call to mmap.
return null;
}
else if (errorInfo.Error != Interop.Error.EEXIST) // map with same name already existed
{
throw Interop.GetExceptionForIoErrno(errorInfo);
}
}
} while (fd.IsInvalid);
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved

try
{
Expand Down Expand Up @@ -236,6 +243,18 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
fd.Dispose();
throw;
}

static string GenerateMapName()
{
const int MaxSharedMemoryObjectNameLength = 32; // SHM_NAME_MAX on OSX ARM64, on other systems it's equal PATH_MAX (250)
// The POSIX shared memory object name must begin with '/'. After that we just want something short (32) and unique.
return string.Create(MaxSharedMemoryObjectNameLength, 0, (span, state) =>
{
Guid.NewGuid().TryFormat(span, out int charsWritten, "N");
Debug.Assert(charsWritten == MaxSharedMemoryObjectNameLength);
"/corefx_map_".CopyTo(span);
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
});
}
}

private static FileStream CreateSharedBackingObjectUsingFile(Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
/// <summary>
/// Tests for MemoryMappedFile.CreateNew.
/// </summary>
[ActiveIssue("https://github.com/dotnet/runtime/issues/63240", typeof(PlatformDetection), nameof(PlatformDetection.IsOSX), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsNotMonoRuntime))]
public class MemoryMappedFileTests_CreateNew : MemoryMappedFilesTestBase
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
/// <summary>
/// Tests for MemoryMappedViewAccessor.
/// </summary>
[ActiveIssue("https://github.com/dotnet/runtime/issues/63240", typeof(PlatformDetection), nameof(PlatformDetection.IsOSX), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsNotMonoRuntime))]
public class MemoryMappedViewAccessorTests : MemoryMappedFilesTestBase
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
/// <summary>
/// Tests for MemoryMappedViewStream.
/// </summary>
[ActiveIssue("https://github.com/dotnet/runtime/issues/63240", typeof(PlatformDetection), nameof(PlatformDetection.IsOSX), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsNotMonoRuntime))]
public class MemoryMappedViewStreamTests : MemoryMappedFilesTestBase
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ private Task<Stream> CreateStream(byte[] initialData, FileAccess access)
}
}

[ActiveIssue("https://github.com/dotnet/runtime/issues/63240", typeof(PlatformDetection), nameof(PlatformDetection.IsOSX), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsNotMonoRuntime))]
public class AnonymousMemoryMappedViewStreamConformanceTests : MemoryMappedViewStreamConformanceTests
{
protected override MemoryMappedFile CreateFile(int length) =>
Expand Down
6 changes: 6 additions & 0 deletions src/native/libs/System.Native/pal_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ int32_t SystemNative_Unlink(const char* path)

intptr_t SystemNative_ShmOpen(const char* name, int32_t flags, int32_t mode)
{
#if defined(SHM_NAME_MAX) // macOS
assert(strlen(name) <= SHM_NAME_MAX);
#elif defined(PATH_MAX) // other Unixes
assert(strlen(name) <= PATH_MAX);
#endif

#if HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP
flags = ConvertOpenFlags(flags);
if (flags == -1)
Expand Down