Skip to content

Commit 2168e52

Browse files
Make sure that shared memory object name meets the length requirements (#64099) (#64266)
Co-authored-by: Stephen Toub <[email protected]> # Conflicts: # src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs # src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs # src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs # src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs
1 parent 2caf6fb commit 2168e52

File tree

6 files changed

+42
-20
lines changed

6 files changed

+42
-20
lines changed

src/libraries/Native/Unix/System.Native/pal_io.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ int32_t SystemNative_Unlink(const char* path)
324324

325325
intptr_t SystemNative_ShmOpen(const char* name, int32_t flags, int32_t mode)
326326
{
327+
#if defined(SHM_NAME_MAX) // macOS
328+
assert(strlen(name) <= SHM_NAME_MAX);
329+
#elif defined(PATH_MAX) // other Unixes
330+
assert(strlen(name) <= PATH_MAX);
331+
#endif
332+
327333
#if HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP
328334
flags = ConvertOpenFlags(flags);
329335
if (flags == -1)

src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics;
45
using Microsoft.Win32.SafeHandles;
56

67
namespace System.IO.MemoryMappedFiles
@@ -173,9 +174,6 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
173174
private static FileStream? CreateSharedBackingObjectUsingMemory(
174175
Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability)
175176
{
176-
// The POSIX shared memory object name must begin with '/'. After that we just want something short and unique.
177-
string mapName = string.Create(null, stackalloc char[128], $"/corefx_map_{Guid.NewGuid():N}");
178-
179177
// Determine the flags to use when creating the shared memory object
180178
Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ?
181179
Interop.Sys.OpenFlags.O_RDWR :
@@ -191,22 +189,32 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
191189
if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0)
192190
perms |= Interop.Sys.Permissions.S_IXUSR;
193191

194-
// Create the shared memory object.
195-
SafeFileHandle fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms);
196-
if (fd.IsInvalid)
192+
string mapName;
193+
SafeFileHandle fd;
194+
195+
do
197196
{
198-
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
199-
if (errorInfo.Error == Interop.Error.ENOTSUP)
197+
mapName = GenerateMapName();
198+
fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); // Create the shared memory object.
199+
200+
if (fd.IsInvalid)
200201
{
201-
// If ShmOpen is not supported, fall back to file backing object.
202-
// Note that the System.Native shim will force this failure on platforms where
203-
// the result of native shm_open does not work well with our subsequent call
204-
// to mmap.
205-
return null;
206-
}
202+
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
203+
fd.Dispose();
207204

208-
throw Interop.GetExceptionForIoErrno(errorInfo);
209-
}
205+
if (errorInfo.Error == Interop.Error.ENOTSUP)
206+
{
207+
// If ShmOpen is not supported, fall back to file backing object.
208+
// Note that the System.Native shim will force this failure on platforms where
209+
// the result of native shm_open does not work well with our subsequent call to mmap.
210+
return null;
211+
}
212+
else if (errorInfo.Error != Interop.Error.EEXIST) // map with same name already existed
213+
{
214+
throw Interop.GetExceptionForIoErrno(errorInfo);
215+
}
216+
}
217+
} while (fd.IsInvalid);
210218

211219
try
212220
{
@@ -236,6 +244,18 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt
236244
fd.Dispose();
237245
throw;
238246
}
247+
248+
static string GenerateMapName()
249+
{
250+
const int MaxSharedMemoryObjectNameLength = 32; // SHM_NAME_MAX on OSX ARM64, on other systems it's equal PATH_MAX (250)
251+
// The POSIX shared memory object name must begin with '/'. After that we just want something short (32) and unique.
252+
return string.Create(MaxSharedMemoryObjectNameLength, 0, (span, state) =>
253+
{
254+
Guid.NewGuid().TryFormat(span, out int charsWritten, "N");
255+
Debug.Assert(charsWritten == MaxSharedMemoryObjectNameLength);
256+
"/dotnet_".CopyTo(span);
257+
});
258+
}
239259
}
240260

241261
private static FileStream CreateSharedBackingObjectUsingFile(Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability)

src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
1111
/// <summary>
1212
/// Tests for MemoryMappedFile.CreateNew.
1313
/// </summary>
14-
[ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))]
1514
public class MemoryMappedFileTests_CreateNew : MemoryMappedFilesTestBase
1615
{
1716
/// <summary>

src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
1111
/// <summary>
1212
/// Tests for MemoryMappedViewAccessor.
1313
/// </summary>
14-
[ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))]
1514
public class MemoryMappedViewAccessorTests : MemoryMappedFilesTestBase
1615
{
1716
/// <summary>

src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests
1111
/// <summary>
1212
/// Tests for MemoryMappedViewStream.
1313
/// </summary>
14-
[ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))]
1514
public class MemoryMappedViewStreamTests : MemoryMappedFilesTestBase
1615
{
1716
/// <summary>

src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ private Task<Stream> CreateStream(byte[] initialData, FileAccess access)
4545
}
4646
}
4747

48-
[ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))]
4948
public class AnonymousMemoryMappedViewStreamConformanceTests : MemoryMappedViewStreamConformanceTests
5049
{
5150
protected override MemoryMappedFile CreateFile(int length) =>

0 commit comments

Comments
 (0)