Skip to content

Instantly share code, notes, and snippets.

@jld
Created April 25, 2018 02:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jld/aef5f46d9f986f564ab59020fdce4f53 to your computer and use it in GitHub Desktop.
Save jld/aef5f46d9f986f564ab59020fdce4f53 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import os, sys, ctypes
CLONE_NEWNS = 0x00020000
CLONE_NEWUSER = 0x10000000
CLONE_NEWPID = 0x20000000
c = ctypes.CDLL("libc.so.6", use_errno=True)
def errwrap(f):
def wrapped(*args):
ret = f(*args)
if ret == -1:
errno = ctypes.get_errno()
raise OSError(errno, os.strerror(errno))
return ret
return wrapped
unshare = errwrap(c.unshare)
setns = errwrap(c.setns)
mount = errwrap(c.mount)
def enterns(pid, nsname, nsflag):
fd = os.open("/proc/%d/ns/%s" % (pid, nsname), os.O_RDONLY)
try:
setns(fd, nsflag)
finally:
os.close(fd)
def do_fork(exit_on_fail = True):
pid = os.fork()
if pid == 0:
return True
wpid, status = os.waitpid(pid, 0)
if exit_on_fail:
if (status & 255) != 0:
exit(128 | status)
if status != 0:
exit(status >> 8)
return False
def setup(pid):
enterns(pid, "user", CLONE_NEWUSER)
enterns(pid, "pid", CLONE_NEWPID)
unshare(CLONE_NEWNS)
if do_fork():
mount("proc", "/proc", "proc", 0, 0)
os._exit(0)
def main(argv):
target = int(argv[1])
cmd = argv[2:]
setup(target)
if do_fork():
os.execvp(cmd[0], cmd)
os._exit(127)
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment