Skip to content

Instantly share code, notes, and snippets.

@ayende

ayende/LinuxSystem.cs Secret

Created Jul 12, 2021
Embed
What would you like to do?
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