XNU in Linux userspace

Related tags

Miscellaneous limbo
Overview

limbo

Limbo is an XNU emulator similar to qemu-user; it translates XNU system calls into their Linux equivalent(s). It is capable of executing supported binaries targeting macOS or iOS on Linux without modification.

Limbo is currently only supported on Linux 5.11 or later with the CONFIG_GENERIC_ENTRY option enabled. This is required to capture system calls made by the guest program.

Sufficiently advanced programs, such as Apple Clang, are capable of compiling binaries which can also be run in Limbo.

Installation

Before installing, read the BSD-2-Clause license.

To install, ensure Meson is installed and run the following commands:

meson build
ninja -C build install

This will install Limbo and the associated documentation, but you must install the binfmt.d(5) handlers by copying etc/binfmt.d/Mach-O.conf to /etc/binfmt.d/Mach-O.conf. For development, omit the install option and review CONTRIBUTING.md. The Development section describes how to set up a development environment. The Internals section of the README gives an overview of how Limbo works.

User's Guide

Limbo relies on a userspace like macOS or iOS to operate, so your chroot must be populated, or "bootstrapped", before use. There are a number of options available depending on your use-case. All examples assume that there is an empty folder at $CHROOT, the target chroot.

It does not matter what architecture your bootstrapping Mac is, because Big Sur ships most utilities as Fat Mach-O binaries. However, non-Fat Mach-O binaries are also supported by Limbo, but must match your architecture.

Minimalist

For simple binaries like echo, only the dyld cache and dyld itself is required. Thus on a Big Sur Mac, using scp or rsync, copy dyld_shared_cache_x86_64 into your chroot:

On the Limbo host:

mkdir -p $CHROOT/System/Library/dyld $CHROOT/bin $CHROOT/usr/lib

On the Big Sur Mac:

scp /System/Library/dyld/dyld_shared_cache_x86_64 $HOST:$CHROOT/System/Library/dyld/dyld_shared_cache_x86_64
scp /usr/lib/dyld $HOST:$CHROOT/usr/lib/dyld
scp $(which echo) $HOST:$CHROOT/bin/echo

Then run the program on the Limbo host:

sudo chroot $CHROOT /bin/echo Hello, world

Which should print "Hello, world".

Xcode

Xcode command-line tools are a work-in-progress, but you will find that most tools like clang or ld64 work as expected in their basic configuration if invoked without xcrun (though xcrun itself does work, xcodebuild does not, yet).

First follow the Minimalist guide.

Ensure Xcode.app is installed, then copy it into the chroot with rsync (must be installed on the Limbo host as well). Xcode is large so this may take some time.

scp $(which file) $HOST:$CHROOT/bin/file
rsync -Pav /Applications/Xcode.app $HOST:$CHROOT/Applications

Set your Xcode location for xcrun:

cd $CHROOT
mkdir -p var/db
ln -s /Applications/Xcode.app/Contents/Developer/ var/db/xcode_select_link

Then, compile a C file and check its format with file:

echo "int main() { return 0; }" > $CHROOT/example.c
sudo chroot $CHROOT /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -c example.c -o example.o
sudo chroot $CHROOT /bin/file example.o

Internals

Limbo at its core is fundamentally simple, the complexity comes from the incongruity between Linux and the XNU kernel.

When an application is spawned by the kernel and it detects Mach-O magic, it spawns Limbo to "wrap" the executable by passing the path to the target program as an argument to Limbo.

The first thing Limbo does is parse its own ELF header and enumerates the executable segments to notify the kernel of the memory regions that are allowed to perform system calls using a Linux 5.11 feature known as Syscall User Dispatch. Any system calls that occur outside of this region result in a SIGSYS. Limbo then sets a SIGSYS handler as the entry point into the XNU emulation routine.

Next, Limbo loads the dyld shared cache and rebases it to the load address. However, on Linux, the stack address actually collides with the default load address of the dyld cache, so Limbo remaps its own stack out of the way in a two-stage setup process. As well, the [vdso] and [vvar] special mappings also overlap, so they are simply unmapped (though this introduces some complications and reduces the glibc wrappers Limbo can call).

Limbo then parses the Mach-O file and reads the load commands to look for the LC_LOAD_DYLINKER which specifies the program invoked by the kernel to link the target application. Then, that program is mapped into memory, the stack is set up, and Limbo executes the entry point of dyld.

Once dyld is started, it takes over the process and Limbo code is only entered when a system call is made.

The XNU kernel is a hybrid kernel with a BSD and Mach subsystem, which is reflected in Limbo's structure: bsd, osfmk (Mach) and mdep (Machine-dependent). When Limbo is interrupted, it determines the subsystem of the syscall and dispatches it into its appropriate handler, the subsystem then determines which syscall was executed and dispatches it again where it is handled.


Special thanks to David Weinstein for suggesting the name Limbo.

You might also like...
A beginner friendly desktop UI for Tasmota flashed devices for Windows, macOS and Linux.
A beginner friendly desktop UI for Tasmota flashed devices for Windows, macOS and Linux.

TasmoManager A beginner friendly desktop UI for Tasmota flashed devices for Windows, macOS and Linux. Features Native Tasmota device discovery (via ta

 Slackware for Windows Subsystem for Linux (WSL)
Slackware for Windows Subsystem for Linux (WSL)

WSLackware: Slackware on Windows! Slackware for Windows Subsystem for Linux (WSL) WSLackware is an unofficial version of Slackware for Windows Subsyst

Linux kernel module to fight against police terror

protecc is a Linux kernel module that will shut down your computer when a predefined USB device is removed from the system.

Graphs the disk IO in a linux terminal.
Graphs the disk IO in a linux terminal.

diskgraph Monitor for disk IO Introduction The diskgraph tool will graph disk IO under linux, in a terminal. Examples: $ ./diskgraph /dev/nvme0n1 $ ./

Linux USB driver for the MOTU AVB series interfaces

motu-avb Linux USB driver for the MOTU AVB series interfaces Kernel parameters: samplerate: set the samplerate (its currently fixed at module load) de

BK0010/BK0011 Emulator for Linux

htmlhead meta http-equiv="content-type" content="text/html;charset=koi8-r" /head bodypre Этот эмулятор БК-0010 (пока только БК-0010, у мен

Notes and codes for Linux Kernel (SJTU-CS353)

Linux-Kernel-notes Notes and codes for Linux Kernel (SJTU-CS353) Lab 01: Module Programming 02: Process Management 03: Memory Management Notes Lec 1.

Linux kernel module for Onion Omega2 to control WS2811/WS2812 LEDs

omega2-ws2811-lkm Linux kernel module for Onion Omega2 to control WS2811/WS2812 LEDs. It's using a bit-banging, so you can use any GPIO pin. Also, it

Linux kernel labs

Linux Kernel Labs This repo illustrates how to write Linux kernel module labs safely and gracefully in a simple and concise way. Contrary to most work

Comments
  • graphical support

    graphical support

    Hey there!

    Just as a pure curiosity - is it even hypothetically possible for the project to support graphics? Perhaps via populating more of the chroot, and running something like XQuartz?

    opened by Luminoso-256 1
  • arm64 support

    arm64 support

    The readme says:

    It is capable of executing supported binaries targeting macOS or iOS on Linux without modification.

    Which made me think that limbo supports the arm64 architecture, since most of iOS binaries target that platform.

    However, it looks like that's not the case -- e.g . linker.c has a line like this:

    #include <mach/i386/thread_status.h>
    

    which doesn't work on arm64, and the alternative would be to include mach/machine/thread_status.h.

    Are there any plans to support arm64?

    opened by qmfrederik 6
Owner
Computer prankster
null
This is a Linux userspace driver for the AverMedia LGX2 (GC551)

LGX2 Userspace driver This software is little more than a POC and no guarantees of functionality are given and it may even be dangerous to use this so

Chris Sawczuk 19 Dec 15, 2022
Hobbyist Operating System targeting x86_64 systems. Includes userspace, Virtual File System, An InitFS (tarfs), Lua port, easy porting, a decent LibC and LibM, and a shell that supports: piping, file redirection, and more.

SynnixOS Epic Hobby OS targeting x86_64 CPUs, it includes some hacked together functionality for most essential OSs although, with interactivity via Q

RaidTheWeb 42 Oct 28, 2022
waved is aimed at becoming a userspace driver for the reMarkable 2 E-Ink controller.

waved waved is aimed at becoming a userspace driver for the reMarkable 2 E-Ink controller. Disclaimer: This is still a prototype. It might damage your

Mattéo Delabre 38 Oct 10, 2022
Userspace I/O library for Xilinx AXI S2MM DMA

Userspace DMA I/O This library should simplify the use of the Xilinx AXI DMA controller when used in S2MM (Stream to Memory-Mapped) mode. A typical us

MicroTCA Technology Lab 4 Sep 20, 2022
Proof of concept userspace filesystem that executes filenames as shell commands and makes the result accessible though reading the file.

ExecFS Proof of concept userspace filesystem that executes filenames as shell commands and makes the result accessible though reading the file. $ ./ex

Camel Coder 42 Jan 7, 2023
A userspace TCP/IP stack based on dpdk

oceanus oceanus is a userspace TCP/IP stack based on dpdk. Quick Start build DPDK wget http://fast.dpdk.org/rel/dpdk-19.11.12.tar.xz tar xvf dpdk-19.1

菜菜 3 Jul 13, 2022
The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2)

Introduction The WSL2-Linux-Kernel repo contains the kernel source code and configuration files for the WSL2 kernel. Reporting Bugs If you discover an

Microsoft 6.3k Jan 8, 2023
Linux x86_64 Process Injection Utility | Manipulate Processes With Customized Payloads (beta)

K55 - Linux x86_64 Process Injection Utility (C++11) About K55 (pronounced: "kay fifty-five") The K55 payload injection tool is used for injecting x86

Josh Schiavone 57 Sep 5, 2022
Quick fix to iphone usb tethering with ios14 or higher for Linux kernel lower than 5.10.4

Quick fix to Linux Iphone USB tethering with IOS 14 or higher (Tested with ubuntu 18.04, kernel 5.4.0-65, if you fail in the build, please download yo

null 24 Sep 18, 2022