/
pycker.py
87 lines (68 loc) · 2.01 KB
/
pycker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import os
import ctypes
import ctypes.util
import argparse
import socket
import subprocess
import sys
MS_PRIVATE = (1 << 18)
MS_REC = 16384
CLONE_NEWNS = 0x00020000
CLONE_NEWPID = 0x20000000
CLONE_NEWUTS = 0x04000000
libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
def unshare(flags):
_unshare = libc.unshare
_unshare.restype = ctypes.c_int
_unshare.argtypes = (ctypes.c_int, )
if _unshare(flags) == -1:
print("Error: in unshare:", os.strerror(ctypes.get_errno()))
return False
return True
def mount(source, target, fs, flags, options):
_mount = libc.mount
_mount.argtypes = (
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.c_ulong,
ctypes.c_char_p
)
if _mount(
source.encode(),
target.encode(),
fs.encode(),
flags,
options.encode()
) == -1:
print("Error in mount:", os.strerror(ctypes.get_errno()))
return False
return True
def umount(target, flags):
_umount = libc.umount2
_umount.argtypes = (ctypes.c_char_p, ctypes.c_int)
if _umount(target.encode(), flags) == -1:
print("Error in umount:", os.strerror(ctypes.get_errno()))
return False
return True
def run(*args):
unshare(CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS)
subprocess.run(["/proc/self/exe", sys.argv[0], "child", *args])
def child(*args):
socket.sethostname("container")
os.chroot(os.path.join(os.getcwd(), "fakeroot"))
os.chdir("/")
#mount("/", "/", "auto", MS_PRIVATE | MS_REC, "")
mount("proc", "/proc", "proc", 0, "")
subprocess.run(args)
umount("/proc", 0)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('action', type=str, help="action to perform")
args, other = parser.parse_known_args()
if args.action == "run":
run(*other)
elif args.action == "child":
child(*other)
else:
parser.print_help()