Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Kieß <kiess@ki4.de>2019-10-09 21:49:14 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2019-10-09 21:49:14 +0300
commit30886f997fa4fbcd7e7cc585dfd2109941f139c4 (patch)
treee63b714249cf4e0c917c1d485a1ed777b56e9042 /mcs/class/Mono.Posix
parent1cf081529e5e37dd9472f7c7b0d0ead659e9b54f (diff)
[Mono.Posix] Add support for memfd_create() and file sealing (#17225)
* [Mono.Posix] Add support for memfd_create() and file sealing Add the linux syscall memfd_create() and add support for file sealing with fcntl(). * Bump API snapshot submodule
Diffstat (limited to 'mcs/class/Mono.Posix')
-rw-r--r--mcs/class/Mono.Posix/Mono.Posix_test.dll.sources1
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs64
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs51
-rw-r--r--mcs/class/Mono.Posix/Test/Mono.Unix.Native/MemfdTest.cs98
4 files changed, 214 insertions, 0 deletions
diff --git a/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources b/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
index 5aee212abe7..c41a3a8f2bf 100644
--- a/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
+++ b/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
@@ -9,6 +9,7 @@ Mono.Unix/UnixPathTest.cs
Mono.Unix/UnixSignalTest.cs
Mono.Unix/UnixUserTest.cs
Mono.Unix.Android/TestHelper.cs
+Mono.Unix.Native/MemfdTest.cs
Mono.Unix.Native/OFDLockTest.cs
Mono.Unix.Native/RealTimeSignumTests.cs
Mono.Unix.Native/SocketTest.cs
diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs
index cf538806236..816b1f76729 100644
--- a/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.generated.cs
@@ -438,6 +438,38 @@ namespace Mono.Unix.Native {
return rval;
}
+ [DllImport (LIB, EntryPoint="Mono_Posix_FromMemfdFlags")]
+ private static extern int FromMemfdFlags (MemfdFlags value, out UInt32 rval);
+
+ public static bool TryFromMemfdFlags (MemfdFlags value, out UInt32 rval)
+ {
+ return FromMemfdFlags (value, out rval) == 0;
+ }
+
+ public static UInt32 FromMemfdFlags (MemfdFlags value)
+ {
+ UInt32 rval;
+ if (FromMemfdFlags (value, out rval) == -1)
+ ThrowArgumentException (value);
+ return rval;
+ }
+
+ [DllImport (LIB, EntryPoint="Mono_Posix_ToMemfdFlags")]
+ private static extern int ToMemfdFlags (UInt32 value, out MemfdFlags rval);
+
+ public static bool TryToMemfdFlags (UInt32 value, out MemfdFlags rval)
+ {
+ return ToMemfdFlags (value, out rval) == 0;
+ }
+
+ public static MemfdFlags ToMemfdFlags (UInt32 value)
+ {
+ MemfdFlags rval;
+ if (ToMemfdFlags (value, out rval) == -1)
+ ThrowArgumentException (value);
+ return rval;
+ }
+
[DllImport (LIB, EntryPoint="Mono_Posix_FromMessageFlags")]
private static extern int FromMessageFlags (MessageFlags value, out Int32 rval);
@@ -806,6 +838,38 @@ namespace Mono.Unix.Native {
return rval;
}
+ [DllImport (LIB, EntryPoint="Mono_Posix_FromSealType")]
+ private static extern int FromSealType (SealType value, out Int32 rval);
+
+ public static bool TryFromSealType (SealType value, out Int32 rval)
+ {
+ return FromSealType (value, out rval) == 0;
+ }
+
+ public static Int32 FromSealType (SealType value)
+ {
+ Int32 rval;
+ if (FromSealType (value, out rval) == -1)
+ ThrowArgumentException (value);
+ return rval;
+ }
+
+ [DllImport (LIB, EntryPoint="Mono_Posix_ToSealType")]
+ private static extern int ToSealType (Int32 value, out SealType rval);
+
+ public static bool TryToSealType (Int32 value, out SealType rval)
+ {
+ return ToSealType (value, out rval) == 0;
+ }
+
+ public static SealType ToSealType (Int32 value)
+ {
+ SealType rval;
+ if (ToSealType (value, out rval) == -1)
+ ThrowArgumentException (value);
+ return rval;
+ }
+
[DllImport (LIB, EntryPoint="Mono_Posix_FromSeekFlags")]
private static extern int FromSeekFlags (SeekFlags value, out Int16 rval);
diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
index e4f2b58e19a..c5189618063 100644
--- a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
@@ -231,6 +231,8 @@ namespace Mono.Unix.Native {
F_SETLEASE = 1024, // Set a lease.
F_GETLEASE = 1025, // Enquire what lease is active.
F_NOTIFY = 1026, // Required notifications on a directory
+ F_ADD_SEALS = 1033, // Add seals.
+ F_GET_SEALS = 1034, // Get seals.
}
[Map]
@@ -241,6 +243,16 @@ namespace Mono.Unix.Native {
F_UNLCK = 2, // Remove lock.
}
+ [Flags][Map]
+ [CLSCompliant (false)]
+ public enum SealType : int {
+ F_SEAL_SEAL = 0x0001, // prevent further seals from being set
+ F_SEAL_SHRINK = 0x0002, // prevent file from shrinking
+ F_SEAL_GROW = 0x0004, // prevent file from growing
+ F_SEAL_WRITE = 0x0008, // prevent writes
+ F_SEAL_FUTURE_WRITE = 0x0010, // prevent future writes while mapped
+ }
+
[Map]
[CLSCompliant (false)]
public enum SeekFlags : short {
@@ -733,6 +745,26 @@ namespace Mono.Unix.Native {
MREMAP_MAYMOVE = 0x1,
}
+ [Map][Flags]
+ [CLSCompliant (false)]
+ public enum MemfdFlags : uint {
+ MFD_CLOEXEC = 0x00000001,
+ MFD_ALLOW_SEALING = 0x00000002,
+ MFD_HUGETLB = 0x00000004,
+ MFD_HUGE_64KB = 0x40000000,
+ MFD_HUGE_512KB = 0x4c000000,
+ MFD_HUGE_1MB = 0x50000000,
+ MFD_HUGE_2MB = 0x54000000,
+ MFD_HUGE_8MB = 0x5c000000,
+ MFD_HUGE_16MB = 0x60000000,
+ MFD_HUGE_32MB = 0x64000000,
+ MFD_HUGE_256MB = 0x70000000,
+ MFD_HUGE_512MB = 0x74000000,
+ MFD_HUGE_1GB = 0x78000000,
+ MFD_HUGE_2GB = 0x7c000000,
+ MFD_HUGE_16GB = 0x88000000,
+ }
+
[Map]
[CLSCompliant (false)]
public enum UnixSocketType : int {
@@ -3021,6 +3053,12 @@ namespace Mono.Unix.Native {
return fcntl (fd, FcntlCommand.F_NOTIFY, _arg);
}
+ public static int fcntl (int fd, FcntlCommand cmd, SealType arg)
+ {
+ int _arg = NativeConvert.FromSealType (arg);
+ return fcntl (fd, cmd, _arg);
+ }
+
[DllImport (MPH, SetLastError=true,
EntryPoint="Mono_Posix_Syscall_fcntl_lock")]
public static extern int fcntl (int fd, FcntlCommand cmd, ref Flock @lock);
@@ -3857,6 +3895,19 @@ namespace Mono.Unix.Native {
public static extern int remap_file_pages (IntPtr start, ulong size,
MmapProts prot, long pgoff, MmapFlags flags);
+ // memfd_create(2)
+ // int memfd_create(const char *name, unsigned int flags);
+ [DllImport (LIBC, SetLastError=true, EntryPoint="memfd_create")]
+ private static extern int sys_memfd_create (
+ [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
+ string name, uint flags);
+
+ public static int memfd_create (string name, MemfdFlags flags)
+ {
+ uint _flags = NativeConvert.FromMemfdFlags (flags);
+ return sys_memfd_create (name, _flags);
+ }
+
#endregion
#region <sys/poll.h> Declarations
diff --git a/mcs/class/Mono.Posix/Test/Mono.Unix.Native/MemfdTest.cs b/mcs/class/Mono.Posix/Test/Mono.Unix.Native/MemfdTest.cs
new file mode 100644
index 00000000000..91fdd019e2d
--- /dev/null
+++ b/mcs/class/Mono.Posix/Test/Mono.Unix.Native/MemfdTest.cs
@@ -0,0 +1,98 @@
+//
+// Tests for memfd_create and file sealing
+//
+// Authors:
+// Steffen Kiess (kiess@ki4.de)
+//
+// Copyright (C) 2019 Steffen Kiess
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+
+using Mono.Unix;
+using Mono.Unix.Native;
+
+using NUnit.Framework;
+
+namespace MonoTests.Mono.Unix.Native
+{
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows"), Category ("NotOnMac")]
+ public class MemfdTest {
+ [Test]
+ public unsafe void TestMemfd ()
+ {
+ int fd;
+ try {
+ fd = Syscall.memfd_create ("mono-test", 0);
+ } catch (EntryPointNotFoundException) {
+ Assert.Ignore ("memfd_create() not available");
+ return;
+ }
+ if (fd < 0 && Stdlib.GetLastError () == Errno.ENOSYS)
+ // Might happen on a new libc + old kernel
+ Assert.Ignore ("memfd_create() returns ENOSYS");
+ if (fd < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ byte b = 42;
+ if (Syscall.write (fd, &b, 1) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Should fail with EPERM because MFD_ALLOW_SEALING was not used
+ var res = Syscall.fcntl(fd, FcntlCommand.F_ADD_SEALS, SealType.F_SEAL_WRITE);
+ Assert.AreEqual (-1, res);
+ Assert.AreEqual (Errno.EPERM, Stdlib.GetLastError ());
+
+ //Stdlib.system ("ls -l /proc/$PPID/fd/");
+
+ if (Syscall.close (fd) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Call memfd_create with MFD_ALLOW_SEALING
+ fd = Syscall.memfd_create ("mono-test", MemfdFlags.MFD_CLOEXEC | MemfdFlags.MFD_ALLOW_SEALING);
+ if (fd < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ if (Syscall.write (fd, &b, 1) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ res = Syscall.fcntl(fd, FcntlCommand.F_GET_SEALS);
+ if (res < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ // Need to convert the result to SealType
+ SealType sealType = NativeConvert.ToSealType (res);
+ Assert.AreEqual ((SealType)0, sealType);
+
+ if (Syscall.fcntl(fd, FcntlCommand.F_ADD_SEALS, SealType.F_SEAL_WRITE) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Should fail with EPERM because the file was sealed for writing
+ var lres = Syscall.write (fd, &b, 1);
+ Assert.AreEqual (-1, lres);
+ Assert.AreEqual (Errno.EPERM, Stdlib.GetLastError ());
+
+ res = Syscall.fcntl(fd, FcntlCommand.F_GET_SEALS);
+ if (res < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ // Need to convert the result to SealType
+ sealType = NativeConvert.ToSealType (res);
+ Assert.AreEqual (SealType.F_SEAL_WRITE, sealType);
+
+ //Stdlib.system ("ls -l /proc/$PPID/fd/");
+
+ if (Syscall.close (fd) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ }
+ }
+}
+
+// vim: noexpandtab
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// End: