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) and unshare(2) 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 | |
… | |
… | |
24 | Linux::Clone::NEWNS (in unshare, implies FS) |
24 | Linux::Clone::NEWNS (in unshare, implies FS) |
25 | Linux::Clone::VM (in unshare, implies SIGHAND) |
25 | Linux::Clone::VM (in unshare, implies SIGHAND) |
26 | Linux::Clone::THREAD (in unshare, implies VM, SIGHAND) |
26 | Linux::Clone::THREAD (in unshare, implies VM, SIGHAND) |
27 | Linux::Clone::SIGHAND |
27 | Linux::Clone::SIGHAND |
28 | Linux::Clone::SYSVSEM |
28 | Linux::Clone::SYSVSEM |
|
|
29 | Linux::Clone::NEWUSER (in unshare, implies CLONE_THREAD) |
|
|
30 | Linux::Clone::NEWPID |
29 | Linux::Clone::NEWUTS |
31 | Linux::Clone::NEWUTS |
30 | Linux::Clone::NEWIPC |
32 | Linux::Clone::NEWIPC |
31 | Linux::Clone::NEWNET |
33 | Linux::Clone::NEWNET |
|
|
34 | Linux::Clone::NEWCGROUP |
|
|
35 | Linux::Clone::NEWTIME |
32 | |
36 | |
33 | Example: unshare the network namespace and prove that by calling ifconfig, |
37 | Example: unshare the network namespace and prove that by calling ifconfig, |
34 | showing only an unconfigured lo interface. |
38 | showing only the unconfigured lo interface. |
35 | |
39 | |
36 | Linux::Clone::unshare Linux::Clone::NEWNET |
40 | Linux::Clone::unshare Linux::Clone::NEWNET |
37 | and "unshare: $!"; |
41 | and "unshare: $!"; |
|
|
42 | Linux::Clone::configure_loopback; |
38 | system "ifconfig -a"; |
43 | system "ifconfig"; |
39 | |
44 | |
40 | Example: unshare the network namespace, initialise the loopback interface, |
45 | Example: unshare the network namespace, initialise the loopback interface, |
41 | create a veth interface pair, put one interface into the parent processes |
46 | create a veth interface pair, put one interface into the parent processes |
42 | namespace (use ifconfig -a from another shell), configure the other |
47 | namespace (use ifconfig -a from another shell), configure the other |
43 | interface with 192.168.99.2 -> 192.168.99.1 and start a shell. |
48 | interface with 192.168.99.2 -> 192.168.99.1 and start a shell. |
… | |
… | |
46 | |
51 | |
47 | # unshare our network namespace |
52 | # unshare our network namespace |
48 | Linux::Clone::unshare Linux::Clone::NEWNET |
53 | Linux::Clone::unshare Linux::Clone::NEWNET |
49 | and "unshare: $!"; |
54 | and "unshare: $!"; |
50 | |
55 | |
|
|
56 | Linux::Clone::configure_loopback; |
|
|
57 | |
51 | my $ppid = getppid; |
58 | my $ppid = getppid; |
52 | |
59 | |
53 | system " |
60 | system " |
54 | # configure loopback interface |
|
|
55 | ip link set lo up |
|
|
56 | ip route add 127.0.0.0/8 dev lo |
|
|
57 | |
|
|
58 | # create veth pair |
61 | # create veth pair |
59 | ip link add name veth_master type veth peer name veth_slave |
62 | ip link add name veth_master type veth peer name veth_slave |
60 | |
63 | |
61 | # move veth_master to our parent process' namespace |
64 | # move veth_master to our parent process' namespace |
62 | ip link set veth_master netns $ppid |
65 | ip link set veth_master netns $ppid |
… | |
… | |
85 | use Linux::Clone; |
88 | use Linux::Clone; |
86 | |
89 | |
87 | Linux::Clone::unshare Linux::Clone::NEWNS |
90 | Linux::Clone::unshare Linux::Clone::NEWNS |
88 | and die "unshare: $!"; |
91 | and die "unshare: $!"; |
89 | |
92 | |
90 | # now bind-mount /lib over /etc and ls -l /etc - scary |
93 | # now bind-mount /lib over /etc and ls -l /etc - looks scary |
91 | system "mount -n --bind /lib /etc"; |
94 | system "mount -n --bind /lib /etc"; |
92 | system "ls -l /etc"; |
95 | system "ls -l /etc"; |
93 | |
96 | |
94 | =item $retval = Linux::Clone::clone $coderef, $stacksize, $flags[, $ptid, $tls, $ctid] |
97 | =item $retval = Linux::Clone::clone $coderef, $stacksize, $flags[, $ptid, $tls, $ctid] |
95 | |
98 | |
… | |
… | |
120 | Linux::Clone::VFORK |
123 | Linux::Clone::VFORK |
121 | Linux::Clone::SETTLS (not yet implemented) |
124 | Linux::Clone::SETTLS (not yet implemented) |
122 | Linux::Clone::PARENT_SETTID (not yet implemented) |
125 | Linux::Clone::PARENT_SETTID (not yet implemented) |
123 | Linux::Clone::CHILD_SETTID (not yet implemented) |
126 | Linux::Clone::CHILD_SETTID (not yet implemented) |
124 | Linux::Clone::CHILD_CLEARTID (not yet implemented) |
127 | Linux::Clone::CHILD_CLEARTID (not yet implemented) |
|
|
128 | Linux::Clone::PIDFD (not yet implemented) |
125 | Linux::Clone::DETACHED |
129 | Linux::Clone::DETACHED |
126 | Linux::Clone::UNTRACED |
130 | Linux::Clone::UNTRACED |
127 | Linux::Clone::NEWUSER |
|
|
128 | Linux::Clone::NEWPID |
|
|
129 | Linux::Clone::IO |
131 | Linux::Clone::IO |
|
|
132 | Linux::Clone::CSIGNAL exit signal mask |
130 | |
133 | |
131 | Note that for practical reasons you basically must not use |
134 | Note that for practical reasons you basically must not use |
132 | C<Linux::Clone::VM> or C<Linux::Clone::VFORK>, as perl is unlikely to cope |
135 | C<Linux::Clone::VM> or C<Linux::Clone::VFORK>, as perl is unlikely to cope |
133 | with that. |
136 | with that. |
134 | |
137 | |
… | |
… | |
137 | Example: do a fork-like clone, sharing nothing, slightly confusing perl |
140 | Example: do a fork-like clone, sharing nothing, slightly confusing perl |
138 | and your libc, and exit immediately. |
141 | and your libc, and exit immediately. |
139 | |
142 | |
140 | my $pid = Linux::Clone::clone sub { warn "in child"; 77 }, 0, POSIX::SIGCHLD; |
143 | my $pid = Linux::Clone::clone sub { warn "in child"; 77 }, 0, POSIX::SIGCHLD; |
141 | |
144 | |
|
|
145 | =item Linux::Clone::setns $fh_or_fd[, $nstype] |
|
|
146 | |
|
|
147 | Calls setns(2) on the file descriptor (or file handle) C<$fh_or_fd>. If |
|
|
148 | C<$nstype> is missing, then C<0> is used. |
|
|
149 | |
|
|
150 | The argument C<$nstype> can be C<0>, C<Linux::Clone::NEWIPC>, |
|
|
151 | C<Linux::Clone::NEWNET>, C<Linux::Clone::NEWUTS>, C<Linux::Clone::NEWCGROUP>, |
|
|
152 | C<Linux::Clone::NEWNS>, C<Linux::Clone::NEWPID> or C<Linux::Clone::NEWUSER>. |
|
|
153 | |
|
|
154 | =item Linux::Clone::pivot_root $new_root, $old_root |
|
|
155 | |
|
|
156 | Calls pivot_root(2) - refer to its manpage for details. |
|
|
157 | |
|
|
158 | =item Linux::Clone::kcmp $pid1, $pid2, $type[, $idx1, $idx2] |
|
|
159 | |
|
|
160 | Calls kcmp(2) - refer to its manpage for details on operations. |
|
|
161 | |
|
|
162 | The following C<$type> constants are available if the kcmp syscall number |
|
|
163 | was available during compilation: |
|
|
164 | |
|
|
165 | C<Linux::Clone::KCMP_FILE>, C<Linux::Clone::KCMP_VM>, C<Linux::Clone::KCMP_FILES>, |
|
|
166 | C<Linux::Clone::KCMP_FS>, C<Linux::Clone::KCMP_SIGHAND>, C<Linux::Clone::KCMP_IO>, |
|
|
167 | C<Linux::Clone::KCMP_SYSVSEM> and C<Linux::Clone::KCMP_EPOLL_TFD>. |
|
|
168 | |
|
|
169 | =item Linux::Clone::configure_loopback |
|
|
170 | |
|
|
171 | Configures a working loopback interface (basically, does the equivalent of |
|
|
172 | "ifconfig lo up" which automatically adds ipv4/ipv6 addresses and routes), |
|
|
173 | which can be useful to get a network namespace going. |
|
|
174 | |
|
|
175 | Dies on error and returns nothing. |
|
|
176 | |
|
|
177 | =item C<ioctl> symbols |
|
|
178 | |
|
|
179 | The following ioctl symbols are also provided by this module (see L<ioctl_ns(8)>). |
|
|
180 | |
|
|
181 | Linux::Clone::NS_GET_USERNS |
|
|
182 | Linux::Clone::NS_GET_PARENT |
|
|
183 | Linux::Clone::NS_GET_NSTYPE |
|
|
184 | Linux::Clone::NS_OWNER_UID |
|
|
185 | |
142 | =back |
186 | =back |
143 | |
187 | |
144 | =cut |
188 | =cut |
145 | |
189 | |
146 | package Linux::Clone; |
190 | package Linux::Clone; |
147 | |
191 | |
148 | # use common::sense; |
192 | # use common::sense; |
149 | |
193 | |
150 | BEGIN { |
194 | BEGIN { |
151 | our $VERSION = '0.01'; |
195 | our $VERSION = '1.3'; |
152 | |
196 | |
153 | require XSLoader; |
197 | require XSLoader; |
154 | XSLoader::load (__PACKAGE__, $VERSION); |
198 | XSLoader::load (__PACKAGE__, $VERSION); |
155 | } |
199 | } |
156 | |
200 | |
|
|
201 | sub configure_loopback() { |
|
|
202 | siocsifflags "lo" |
|
|
203 | and die "Linux::Clone::configure_looopback: unable to bring up loopback interface: $!\n"; |
|
|
204 | } |
|
|
205 | |
157 | 1; |
206 | 1; |
|
|
207 | |
|
|
208 | =head1 SEE ALSO |
|
|
209 | |
|
|
210 | L<IO::AIO> has some related functions, such as C<pidfd_send_signal>, and |
|
|
211 | some unrelated fucntions that might be useful. |
|
|
212 | |
|
|
213 | L<cgroup_namespaces(7)>, L<pid_namespaces(7)>, L<user_namespaces(7)>, L<time_namespaces(7)>, |
|
|
214 | L<ip-netns(8)>, L<lsns(8)>, L<switch_root(8)>, L<ioctl_ns(2)>. |
158 | |
215 | |
159 | =head1 AUTHOR |
216 | =head1 AUTHOR |
160 | |
217 | |
161 | Marc Lehmann <schmorp@schmorp.de> |
218 | Marc Lehmann <schmorp@schmorp.de> |
162 | http://home.schmorp.de/ |
219 | http://home.schmorp.de/ |