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(); } }