1 | =head1 NAME |
1 | =head1 NAME |
2 | |
2 | |
3 | Linux::Clone - an interface to the linux clone(2) and unshare(2) syscalls |
3 | Linux::Clone - an interface to the linux clone, unshare, setns, pivot_root and kcmp syscalls |
4 | |
4 | |
5 | =head1 SYNOPSIS |
5 | =head1 SYNOPSIS |
6 | |
6 | |
7 | use Linux::Clone; |
7 | use Linux::Clone; |
8 | |
8 | |
9 | =head1 DESCRIPTION |
9 | =head1 DESCRIPTION |
10 | |
10 | |
11 | This module exposes the linux clone(2), unshare(2) and related syscalls to |
11 | This module exposes the linux clone(2), unshare(2) and some related |
12 | Perl. |
12 | syscalls to Perl. |
13 | |
13 | |
14 | =over 4 |
14 | =over 4 |
15 | |
15 | |
16 | =item $retval = unshare $flags |
16 | =item $retval = unshare $flags |
17 | |
17 | |
… | |
… | |
32 | Linux::Clone::NEWIPC |
32 | Linux::Clone::NEWIPC |
33 | Linux::Clone::NEWNET |
33 | Linux::Clone::NEWNET |
34 | Linux::Clone::NEWCGROUP |
34 | Linux::Clone::NEWCGROUP |
35 | |
35 | |
36 | Example: unshare the network namespace and prove that by calling ifconfig, |
36 | Example: unshare the network namespace and prove that by calling ifconfig, |
37 | showing only an unconfigured lo interface. |
37 | showing only the unconfigured lo interface. |
38 | |
38 | |
39 | Linux::Clone::unshare Linux::Clone::NEWNET |
39 | Linux::Clone::unshare Linux::Clone::NEWNET |
40 | and "unshare: $!"; |
40 | and "unshare: $!"; |
|
|
41 | Linux::Clone::configure_loopback; |
41 | system "ifconfig -a"; |
42 | system "ifconfig"; |
42 | |
43 | |
43 | Example: unshare the network namespace, initialise the loopback interface, |
44 | Example: unshare the network namespace, initialise the loopback interface, |
44 | create a veth interface pair, put one interface into the parent processes |
45 | create a veth interface pair, put one interface into the parent processes |
45 | namespace (use ifconfig -a from another shell), configure the other |
46 | namespace (use ifconfig -a from another shell), configure the other |
46 | interface with 192.168.99.2 -> 192.168.99.1 and start a shell. |
47 | interface with 192.168.99.2 -> 192.168.99.1 and start a shell. |
… | |
… | |
49 | |
50 | |
50 | # unshare our network namespace |
51 | # unshare our network namespace |
51 | Linux::Clone::unshare Linux::Clone::NEWNET |
52 | Linux::Clone::unshare Linux::Clone::NEWNET |
52 | and "unshare: $!"; |
53 | and "unshare: $!"; |
53 | |
54 | |
|
|
55 | Linux::Clone::configure_loopback; |
|
|
56 | |
54 | my $ppid = getppid; |
57 | my $ppid = getppid; |
55 | |
58 | |
56 | system " |
59 | system " |
57 | # configure loopback interface |
|
|
58 | ip link set lo up |
|
|
59 | ip route add 127.0.0.0/8 dev lo |
|
|
60 | |
|
|
61 | # create veth pair |
60 | # create veth pair |
62 | ip link add name veth_master type veth peer name veth_slave |
61 | ip link add name veth_master type veth peer name veth_slave |
63 | |
62 | |
64 | # move veth_master to our parent process' namespace |
63 | # move veth_master to our parent process' namespace |
65 | ip link set veth_master netns $ppid |
64 | ip link set veth_master netns $ppid |
… | |
… | |
88 | use Linux::Clone; |
87 | use Linux::Clone; |
89 | |
88 | |
90 | Linux::Clone::unshare Linux::Clone::NEWNS |
89 | Linux::Clone::unshare Linux::Clone::NEWNS |
91 | and die "unshare: $!"; |
90 | and die "unshare: $!"; |
92 | |
91 | |
93 | # now bind-mount /lib over /etc and ls -l /etc - scary |
92 | # now bind-mount /lib over /etc and ls -l /etc - looks scary |
94 | system "mount -n --bind /lib /etc"; |
93 | system "mount -n --bind /lib /etc"; |
95 | system "ls -l /etc"; |
94 | system "ls -l /etc"; |
96 | |
95 | |
97 | =item $retval = Linux::Clone::clone $coderef, $stacksize, $flags[, $ptid, $tls, $ctid] |
96 | =item $retval = Linux::Clone::clone $coderef, $stacksize, $flags[, $ptid, $tls, $ctid] |
98 | |
97 | |
… | |
… | |
123 | Linux::Clone::VFORK |
122 | Linux::Clone::VFORK |
124 | Linux::Clone::SETTLS (not yet implemented) |
123 | Linux::Clone::SETTLS (not yet implemented) |
125 | Linux::Clone::PARENT_SETTID (not yet implemented) |
124 | Linux::Clone::PARENT_SETTID (not yet implemented) |
126 | Linux::Clone::CHILD_SETTID (not yet implemented) |
125 | Linux::Clone::CHILD_SETTID (not yet implemented) |
127 | Linux::Clone::CHILD_CLEARTID (not yet implemented) |
126 | Linux::Clone::CHILD_CLEARTID (not yet implemented) |
|
|
127 | Linux::Clone::PIDFD (not yet implemented) |
128 | Linux::Clone::DETACHED |
128 | Linux::Clone::DETACHED |
129 | Linux::Clone::UNTRACED |
129 | Linux::Clone::UNTRACED |
130 | Linux::Clone::IO |
130 | Linux::Clone::IO |
|
|
131 | Linux::Clone::CSIGNAL exit signal mask |
131 | |
132 | |
132 | Note that for practical reasons you basically must not use |
133 | Note that for practical reasons you basically must not use |
133 | C<Linux::Clone::VM> or C<Linux::Clone::VFORK>, as perl is unlikely to cope |
134 | C<Linux::Clone::VM> or C<Linux::Clone::VFORK>, as perl is unlikely to cope |
134 | with that. |
135 | with that. |
135 | |
136 | |
… | |
… | |
143 | =item Linux::Clone::setns $fh_or_fd[, $nstype] |
144 | =item Linux::Clone::setns $fh_or_fd[, $nstype] |
144 | |
145 | |
145 | Calls setns(2) on the file descriptor (or file handle) C<$fh_or_fd>. If |
146 | Calls setns(2) on the file descriptor (or file handle) C<$fh_or_fd>. If |
146 | C<$nstype> is missing, then C<0> is used. |
147 | C<$nstype> is missing, then C<0> is used. |
147 | |
148 | |
148 | At the time of this writing, C<$nstype> can be C<0>, C<Linux::Clone::NEWIPC>, |
149 | The argument C<$nstype> can be C<0>, C<Linux::Clone::NEWIPC>, |
149 | C<Linux::Clone::NEWNET>, C<Linux::Clone::NEUTS>, C<Linux::Clone::NEWCGROUP>, |
150 | C<Linux::Clone::NEWNET>, C<Linux::Clone::NEWUTS>, C<Linux::Clone::NEWCGROUP>, |
150 | C<Linux::Clone::NEWNS>, C<Linux::Clone::NEWPID> or C<Linux::Clone::NEWUSER>. |
151 | C<Linux::Clone::NEWNS>, C<Linux::Clone::NEWPID> or C<Linux::Clone::NEWUSER>. |
151 | |
152 | |
|
|
153 | =item Linux::Clone::pivot_root $new_root, $old_root |
|
|
154 | |
|
|
155 | Calls pivot_root(2) - refer to its manpage for details. |
|
|
156 | |
|
|
157 | =item Linux::Clone::kcmp $pid1, $pid2, $type[, $idx1, $idx2] |
|
|
158 | |
|
|
159 | Calls kcmp(2) - refer to its manpage for details on operations. |
|
|
160 | |
|
|
161 | The following C<$type> constants are available if the kcmp syscall number |
|
|
162 | was available during compilation: |
|
|
163 | |
|
|
164 | C<Linux::Clone::KCMP_FILE>, C<Linux::Clone::KCMP_VM>, C<Linux::Clone::KCMP_FILES>, |
|
|
165 | C<Linux::Clone::KCMP_FS>, C<Linux::Clone::KCMP_SIGHAND>, C<Linux::Clone::KCMP_IO> and |
|
|
166 | C<Linux::Clone::KCMP_SYSVSEM>. |
|
|
167 | |
|
|
168 | =item Linux::Clone::configure_loopback |
|
|
169 | |
|
|
170 | Configures a working loopback interface (basically, does the equivalent of |
|
|
171 | "ifconfig lo up" which automatically adds ipv4/ipv6 addresses and routes), |
|
|
172 | which can be useful to get a network namespace going. |
|
|
173 | |
|
|
174 | Dies on error and returns nothing. |
|
|
175 | |
152 | =back |
176 | =back |
153 | |
177 | |
154 | =cut |
178 | =cut |
155 | |
179 | |
156 | package Linux::Clone; |
180 | package Linux::Clone; |
157 | |
181 | |
158 | # use common::sense; |
182 | # use common::sense; |
159 | |
183 | |
160 | BEGIN { |
184 | BEGIN { |
161 | our $VERSION = '1.0'; |
185 | our $VERSION = '1.3'; |
162 | |
186 | |
163 | require XSLoader; |
187 | require XSLoader; |
164 | XSLoader::load (__PACKAGE__, $VERSION); |
188 | XSLoader::load (__PACKAGE__, $VERSION); |
165 | } |
189 | } |
166 | |
190 | |
|
|
191 | sub configure_loopback() { |
|
|
192 | siocsifflags "lo" |
|
|
193 | and die "Linux::Clone::configure_looopback: unable to bring up loopback interface: $!\n"; |
|
|
194 | } |
|
|
195 | |
167 | 1; |
196 | 1; |
168 | |
197 | |
169 | =head1 AUTHOR |
198 | =head1 AUTHOR |
170 | |
199 | |
171 | Marc Lehmann <schmorp@schmorp.de> |
200 | Marc Lehmann <schmorp@schmorp.de> |