This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
namespace fault | |
{ | |
// Warning: I did the minimum required to get a sample working | |
// Warning: Be careful using this. | |
public class LinuxSystem | |
{ | |
private const string LIBC_6 = "libc"; | |
[DllImport(LIBC_6, EntryPoint = "syscall", SetLastError = true)] | |
public static extern long syscall1(long number, int a0); | |
[DllImport(LIBC_6, EntryPoint = "ioctl", SetLastError = true)] | |
public static extern int ioctl(int fd, int cmd, ref uffdio_api arg); | |
[DllImport(LIBC_6, EntryPoint = "ioctl", SetLastError = true)] | |
public static extern int ioctl(int fd, int cmd, ref uffdio_register arg); | |
[DllImport(LIBC_6, EntryPoint = "mmap64", SetLastError = true)] | |
public static extern nint mmap64(nint start, nuint length, | |
MmapProts prot, MmapFlags flags, int fd, long offset); | |
[Flags] | |
public enum MmapFlags : int | |
{ | |
MAP_SHARED = 0x01, // Share changes. | |
MAP_PRIVATE = 0x02, // Changes are private. | |
MAP_TYPE = 0x0f, // Mask for type of mapping. | |
MAP_FIXED = 0x10, // Interpret addr exactly. | |
MAP_FILE = 0, | |
MAP_ANONYMOUS = 0x20, // Don't use a file. | |
MAP_ANON = MAP_ANONYMOUS, | |
// These are Linux-specific. | |
MAP_GROWSDOWN = 0x00100, // Stack-like segment. | |
MAP_DENYWRITE = 0x00800, // ETXTBSY | |
MAP_EXECUTABLE = 0x01000, // Mark it as an executable. | |
MAP_LOCKED = 0x02000, // Lock the mapping. | |
MAP_NORESERVE = 0x04000, // Don't check for reservations. | |
MAP_POPULATE = 0x08000, // Populate (prefault) pagetables. | |
MAP_NONBLOCK = 0x10000, // Do not block on IO. | |
} | |
[Flags] | |
public enum MmapProts : int | |
{ | |
PROT_READ = 0x1, // Page can be read. | |
PROT_WRITE = 0x2, // Page can be written. | |
PROT_EXEC = 0x4, // Page can be executed. | |
PROT_NONE = 0x0, // Page can not be accessed. | |
PROT_GROWSDOWN = 0x01000000, // Extend change to start of | |
// growsdown vma (mprotect only). | |
PROT_GROWSUP = 0x02000000, // Extend change to start of | |
// growsup vma (mprotect only). | |
} | |
public const int SYS_userfaultfd = 323; | |
public const ulong UFFD_API = 170; | |
public const int UFFDIO_API = unchecked((int)3222841919); | |
public const int UFFDIO_REGISTER = unchecked((int)3223366144); | |
public const int UFFDIO_REGISTER_MODE_MISSING = 1; | |
public const int UFFD_API_RANGE_IOCTLS = 28; | |
public const int UFFD_EVENT_PAGEFAULT = 18; | |
[Flags] | |
public enum OpenFlags : int | |
{ | |
O_RDONLY = 0x00000000, | |
O_WRONLY = 0x00000001, | |
O_RDWR = 0x00000002, | |
O_NONBLOCK = 0x00000800, | |
} | |
public struct uffdio_api | |
{ | |
public ulong api; /* Requested API version (input) */ | |
public ulong features; /* Requested features (input/output) */ | |
public ulong ioctls; /* Available ioctl() operations (output) */ | |
}; | |
public struct uffdio_range | |
{ | |
public ulong start; /* Start of range */ | |
public ulong len; /* Length of range (bytes) */ | |
}; | |
public struct uffdio_register | |
{ | |
public uffdio_range range; | |
public ulong mode; /* Desired mode of operation (input) */ | |
public ulong ioctls; /* Available ioctl() operations (output) */ | |
}; | |
public struct uffd_msg_pagefault_feat | |
{ | |
public uint ptid; | |
} | |
public struct uffd_msg_fork | |
{ | |
public uint ufd; | |
} | |
public struct uffd_msg_remap | |
{ | |
public ulong from; | |
public ulong to; | |
public ulong len; | |
} | |
public struct uffd_msg_remove | |
{ | |
public ulong start; | |
public ulong end; | |
} | |
public struct uffd_msg_pagefault | |
{ | |
public ulong flags; | |
public ulong address; | |
public uffd_msg_pagefault_feat feat; | |
} | |
[StructLayout(LayoutKind.Explicit)] | |
public unsafe struct uffd_msg | |
{ | |
[FieldOffset(0)] | |
public byte @event; | |
[FieldOffset(1)] | |
public fixed byte reserved[7]; | |
[FieldOffset(8)] | |
public uffd_msg_pagefault pagefault; | |
[FieldOffset(8)] | |
public uffd_msg_fork fork; | |
[FieldOffset(8)] | |
public uffd_msg_remap remap; | |
[FieldOffset(8)] | |
public uffd_msg_remove remove; | |
} | |
public static int userfaultfd(OpenFlags flags) | |
{ | |
return (int)syscall1(SYS_userfaultfd, (int)flags); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment