Skip to content

Instantly share code, notes, and snippets.

@milkey-mouse
Created October 24, 2024 20:56
Show Gist options
  • Save milkey-mouse/610aaca7332a18ad6657e2fbb584c58c to your computer and use it in GitHub Desktop.
Save milkey-mouse/610aaca7332a18ad6657e2fbb584c58c to your computer and use it in GitHub Desktop.
Simple example of "pretending you're root" with unshare(CLONE_NEWNS) in Python
from contextlib import contextmanager
import ctypes
import ctypes.util
import os
MS_BIND = 4096
MS_REC = 16384
MS_PRIVATE = 1 << 18
libc: ctypes.CDLL = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) # type: ignore
def mount(
source: bytes,
target: bytes,
fs: bytes,
flags: int,
data: bytes | None = None,
):
if libc.mount(
ctypes.c_char_p(source),
ctypes.c_char_p(target),
ctypes.c_char_p(fs),
ctypes.c_ulong(flags),
ctypes.c_char_p(data) if data is not None else ctypes.c_void_p(0),
):
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno))
@contextmanager
def umounter():
try:
yield
finally:
if libc.umount(ctypes.c_char_p(target)):
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno))
return umounter()
def unshare_namespaces():
# get these before we unshare(), which will immediately map us to 65534
uid, gid = os.getuid(), os.getgid()
os.unshare(os.CLONE_NEWUSER | os.CLONE_NEWNS)
with open("/proc/self/setgroups", "w") as f:
print("deny", file=f)
with open("/proc/self/uid_map", "w") as f:
print(0, uid, 1, file=f)
with open("/proc/self/gid_map", "w") as f:
print(0, gid, 1, file=f)
# as of this point, we're now "root" (within the new userns)
mount(b"none", b"/", b"", MS_REC | MS_PRIVATE) # prevent mount propagation
mount(b"tmpfs", b"/tmp", b"tmpfs", 0, b"size=100%,mode=1777") # new tmpfs destroyed on process exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment