Skip to content

Commit

Permalink
Implement write sealing
Browse files Browse the repository at this point in the history
  • Loading branch information
am11 committed Jul 22, 2024
1 parent 78da311 commit f421782
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ internal static partial class Fcntl
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetFD", SetLastError = true)]
internal static partial int SetFD(SafeHandle fd, int flags);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetSealWrite", SetLastError = true)]
internal static partial int SetSealWrite(SafeHandle fd);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetFD", SetLastError = true)]
internal static partial int GetFD(SafeHandle fd);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,19 @@ private static SafeFileHandle CreateSharedBackingObject(Interop.Sys.MemoryMapped

try
{
if (!Interop.Sys.IsMemfdSupported)
if (Interop.Sys.IsMemfdSupported)
{
// Add a writeseal for readonly case when eadonly protection requested
if ((protections & Interop.Sys.MemoryMappedProtections.PROT_READ) != 0 &&
(protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) == 0 &&
// seal write failed
Interop.Sys.Fcntl.SetSealWrite(fd) == -1)
{
fd.Dispose();
throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo());
}
}
else
{
// Unlink the shared memory object immediately so that it'll go away once all handles
// to it are closed (as with opened then unlinked files, it'll remain usable via
Expand All @@ -251,6 +263,7 @@ private static SafeFileHandle CreateSharedBackingObject(Interop.Sys.MemoryMapped
if (inheritability == HandleInheritability.Inheritable &&
Interop.Sys.Fcntl.SetFD(fd, 0) == -1)
{
fd.Dispose();
throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo());
}

Expand Down
1 change: 1 addition & 0 deletions src/native/libs/System.Native/entrypoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static const Entry s_sysNative[] =
DllImportEntry(SystemNative_OpenDir)
DllImportEntry(SystemNative_CloseDir)
DllImportEntry(SystemNative_Pipe)
DllImportEntry(SystemNative_FcntlSetSealWrite)
DllImportEntry(SystemNative_FcntlSetFD)
DllImportEntry(SystemNative_FcntlGetFD)
DllImportEntry(SystemNative_FcntlCanGetSetPipeSz)
Expand Down
11 changes: 9 additions & 2 deletions src/native/libs/System.Native/pal_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ int32_t SystemNative_MemfdSupported(void)

// Note that the name has no affect on file descriptor behavior. From linux manpage:
// Names do not affect the behavior of the file descriptor, and as such multiple files can have the same name without any side effects.
int32_t fd = memfd_create("test", MFD_CLOEXEC);
int32_t fd = memfd_create("test", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0) return 0;

close(fd);
Expand All @@ -405,7 +405,7 @@ intptr_t SystemNative_MemfdCreate(const char* name)
assert(strlen(name) <= PATH_MAX);
#endif

return memfd_create(name, MFD_CLOEXEC);
return memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
#else
(void)name;
errno = ENOTSUP;
Expand Down Expand Up @@ -665,6 +665,13 @@ int32_t SystemNative_Pipe(int32_t pipeFds[2], int32_t flags)
return result;
}

int32_t SystemNative_FcntlSetSealWrite(intptr_t fd)
{
int result;
while ((result = fcntl(ToFileDescriptor(fd), F_ADD_SEALS, F_SEAL_WRITE)) < 0 && errno == EINTR);
return result;
}

int32_t SystemNative_FcntlSetFD(intptr_t fd, int32_t flags)
{
int result;
Expand Down
7 changes: 7 additions & 0 deletions src/native/libs/System.Native/pal_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,13 @@ PALEXPORT int32_t SystemNative_Pipe(int32_t pipefd[2], // [out] pipefds[0] gets
// for each command. This allows use to have strongly typed arguments and saves
// complexity around converting command codes.

/**
* Sets the write seal on memfd_create file descriptor.
*
* Returns 0 for success; -1 for failure. Sets errno for failure.
*/
PALEXPORT int32_t SystemNative_FcntlSetSealWrite(intptr_t fd);

/**
* Sets the O_CLOEXEC flag on a file descriptor.
*
Expand Down

0 comments on commit f421782

Please sign in to comment.