Cloning process support in python

Is there syscall clone(2) support (not os.fork ) in Python? I want to play with Linux namespaces under Python, but it seems that there is no information about it.

Changes:

I think ctypes with libc is the answer, but I still have not succeeded. fork works without problems, since it has no arguments how this code works:

 from ctypes import * libc = CDLL("libc.so.6") libc.fork() 

With the clone, I'm trying to do this:

 from ctypes import * def f(): print "In callback." return 0 libc = CDLL("libc.so.6") f_c = CFUNCTYPE(c_int)(f) print libc.getpid() print libc.clone(f_c) print get_errno() 

The clone really has this signature:

int clone (int (* fn) (void *), void * child_stack, int flags, void arg, ... / pid _t * ptid, struct user_desc * tls, pid_t * ctid * /);

I still need to pass * child_stack and flags, but I have no idea how to do this. Any help?

Additional changes:

I got it now:

 from ctypes import * def f(): print "In callback." return 0 libc = CDLL("libc.so.6") f_c = CFUNCTYPE(c_int)(f) stack = c_char_p(" " * 1024 * 1024) libc.clone(f_c, c_void_p(cast(stack, c_void_p).value + 1024 * 1024), 0) 

It really works, but I suppose I'm making a big hole in my system with the stack, is there a cleaner way to do this?

Changes:

Almost done by adding the correct flag for newpid:

 from ctypes import * libc = CDLL("libc.so.6") def f(): print libc.getpid() return 0 f_c = CFUNCTYPE(c_int)(f) stack = c_char_p(" " * 1024 * 1024) libc.clone(f_c, c_void_p(cast(stack, c_void_p).value + 1024 * 1024), 0x20000000) 

This does not work only for root and prints nice 1.

And after this post, the stack looks fine: http://code.google.com/p/chromium/wiki/LinuxPidNamespaceSupport

+8
python
source share
2 answers

Well, finally, I think I got the answer, just usign ctypes with libc,

This is a simple proof of concept:

 from ctypes import * libc = CDLL("libc.so.6") # Create stack. stack = c_char_p(" " * 8096) def f(): print libc.getpid() return 0 # Conver function to c type returning an integer. f_c = CFUNCTYPE(c_int)(f) # We need the top of the stack. stack_top = c_void_p(cast(stack, c_void_p).value + 8096) # Call clone with the NEWPID Flag libc.clone(f_c, stack_top, 0x20000000) 

This must be done by root.

+6
source share

If you want to have fork (), but with new namespace semantics, you can directly call syscall SYS_clone . Note: if you do this, the os.getpid() method will return the wrong process id in the child, because glibc caches the id process and does not know about calling SYS_clone to invalidate its cache.

Assuming x86_64 ( NR_clone == 56 , NR_getpid == 39 ), you can call libc.syscall(56, signal.SIGCHLD|0x000200000, 0 0 0) in fork and then libc.syscall(39) to get the current The PID of the child process is forked.

0
source share

All Articles