ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Linux-Clone/Clone.xs
Revision: 1.9
Committed: Tue Sep 6 10:57:01 2022 UTC (20 months, 1 week ago) by root
Branch: MAIN
CVS Tags: rel-1_3
Changes since 1.8: +1 -0 lines
Log Message:
1.3

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <sys/errno.h>
6 #include <sys/mman.h>
7
8 #undef _GNU_SOURCE
9 #define _GNU_SOURCE
10 #include <sched.h>
11 #include <unistd.h>
12 #include <sys/syscall.h>
13
14 #include <sched.h>
15
16 #include <sys/ioctl.h>
17 #include <net/if.h>
18
19 #include <linux/nsfs.h>
20 #include <linux/kcmp.h>
21
22 /* kcmp.h does not define symbols, so there is no way to detect preesence of enum */
23 /* members, so we just hardcode new symbols here. */
24 #ifndef KCMP_EPOLL_TFD
25 #define KCMP_EPOLL_TFD 7
26 #endif
27
28 #ifdef __has_include
29 #if !__has_include("linux/kcmp.h") // use "" as GCC wrongly expands macros
30 #undef SYS_kcmp
31 #endif
32 #endif
33
34 #ifdef SYS_kcmp
35 #include "linux/kcmp.h"
36 #define kcmp(pid1,pid2,type,idx1,idx2) \
37 syscall (SYS_kcmp, (pid_t)pid1, (pid_t)pid2, \
38 (int)type, (unsigned long)idx1, (unsigned long)idx2)
39 #else
40 #define kcmp(pid1,pid2,type,idx1,idx2) \
41 (errno = ENOSYS, -1)
42 #endif
43
44 /* from schmorp.h */
45 static int
46 s_fileno (SV *fh, int wr)
47 {
48 dTHX;
49 SvGETMAGIC (fh);
50
51 if (SvROK (fh))
52 {
53 fh = SvRV (fh);
54 SvGETMAGIC (fh);
55 }
56
57 if (SvTYPE (fh) == SVt_PVGV)
58 return PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh)));
59
60 if (SvOK (fh) && (SvIV (fh) >= 0) && (SvIV (fh) < 0x7fffffffL))
61 return SvIV (fh);
62
63 return -1;
64 }
65
66 static int
67 clone_cb (void *arg)
68 {
69 dSP;
70
71 PUSHMARK (SP);
72
73 PUTBACK;
74 int count = call_sv (sv_2mortal ((SV *)arg), G_SCALAR);
75 SPAGAIN;
76 int retval = count ? SvIV (POPs) : 0;
77 PUTBACK;
78
79 return retval;
80 }
81
82 MODULE = Linux::Clone PACKAGE = Linux::Clone
83
84 PROTOTYPES: ENABLE
85
86 BOOT:
87 HV *stash = gv_stashpv ("Linux::Clone", 1);
88
89 static const struct {
90 const char *name;
91 IV iv;
92 } *civ, const_iv[] = {
93 # define const_iv(name) { # name, (IV)name },
94 # define const_iv_clone(name) { # name, (IV) CLONE_ ## name },
95 # ifdef CSIGNAL
96 const_iv (CSIGNAL)
97 # endif
98 # ifdef CLONE_FILES
99 const_iv_clone (FILES)
100 # endif
101 # ifdef CLONE_FS
102 const_iv_clone (FS)
103 # endif
104 # ifdef CLONE_NEWNS
105 const_iv_clone (NEWNS)
106 # endif
107 # ifdef CLONE_VM
108 const_iv_clone (VM)
109 # endif
110 # ifdef CLONE_THREAD
111 const_iv_clone (THREAD)
112 # endif
113 # ifdef CLONE_SIGHAND
114 const_iv_clone (SIGHAND)
115 # endif
116 # ifdef CLONE_SYSVSEM
117 const_iv_clone (SYSVSEM)
118 # endif
119 # ifdef CLONE_NEWUTS
120 const_iv_clone (NEWUTS)
121 # endif
122 # ifdef CLONE_NEWIPC
123 const_iv_clone (NEWIPC)
124 # endif
125 # ifdef CLONE_NEWNET
126 const_iv_clone (NEWNET)
127 # endif
128 # ifdef CLONE_NEWTIME
129 x
130 const_iv_clone (NEWTIME)
131 # endif
132 # ifdef CLONE_PTRACE
133 const_iv_clone (PTRACE)
134 # endif
135 # ifdef CLONE_VFORK
136 const_iv_clone (VFORK)
137 # endif
138 # ifdef CLONE_SETTLS
139 const_iv_clone (SETTLS)
140 # endif
141 # ifdef CLONE_PARENT_SETTID
142 const_iv_clone (PARENT_SETTID)
143 # endif
144 # ifdef CLONE_CHILD_CLEARTID
145 const_iv_clone (CHILD_CLEARTID)
146 # endif
147 # ifdef CLONE_DETACHED
148 const_iv_clone (DETACHED)
149 # endif
150 # ifdef CLONE_UNTRACED
151 const_iv_clone (UNTRACED)
152 # endif
153 # ifdef CLONE_CHILD_SETTID
154 const_iv_clone (CHILD_SETTID)
155 # endif
156 # ifdef CLONE_NEWUSER
157 const_iv_clone (NEWUSER)
158 # endif
159 # ifdef CLONE_NEWPID
160 const_iv_clone (NEWPID)
161 # endif
162 # ifdef CLONE_IO
163 const_iv_clone (IO)
164 # endif
165 # ifdef CLONE_NEWCGROUP
166 const_iv_clone (NEWCGROUP)
167 # endif
168 # ifdef CLONE_PIDFD
169 const_iv_clone (PIDFD)
170 # endif
171 # ifdef SYS_kcmp
172 const_iv (KCMP_FILE)
173 const_iv (KCMP_VM)
174 const_iv (KCMP_FILES)
175 const_iv (KCMP_FS)
176 const_iv (KCMP_SIGHAND)
177 const_iv (KCMP_IO)
178 const_iv (KCMP_SYSVSEM)
179 const_iv (KCMP_EPOLL_TFD)
180 # endif
181 # ifdef NS_GET_USERNS
182 const_iv (NS_GET_USERNS)
183 # endif
184 # ifdef NS_GET_PARENT
185 const_iv (NS_GET_PARENT)
186 # endif
187 # ifdef NS_GET_NSTYPE
188 const_iv (NS_GET_NSTYPE)
189 # endif
190 # ifdef NS_OWNER_UID
191 const_iv (NS_OWNER_UID
192 # endif
193 };
194
195 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
196 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
197
198 int
199 clone (SV *sub, IV stacksize, int flags, SV *ptid = 0, SV *tls = &PL_sv_undef)
200 CODE:
201 {
202 if (!stacksize)
203 stacksize = 4 << 20;
204
205 pid_t ptid_;
206 char *stack_ptr = mmap (0, stacksize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK, -1, 0);
207
208 #ifndef __hppa
209 stack_ptr += stacksize - 16; /* be safe and put the sp at 16 bytes below the end */
210 #endif
211
212 RETVAL = -1;
213 if (stack_ptr != (void *)-1)
214 {
215 SV *my_sub = newSVsv (sub);
216
217 RETVAL = clone (clone_cb, (void *)stack_ptr, flags, (void *)my_sub, &ptid, SvOK (tls) ? SvPV_nolen (tls) : 0, 0);
218
219 if (ptid) sv_setiv (ptid, (IV)ptid_);
220
221 if ((flags & (CLONE_VM | CLONE_VFORK)) != CLONE_VM)
222 {
223 int old_errno = errno;
224 munmap (stack_ptr, stacksize);
225 errno = old_errno;
226 }
227 }
228 }
229 OUTPUT: RETVAL
230
231 int
232 unshare (int flags)
233 PROTOTYPE: @
234
235 int
236 setns (SV *fh_or_fd, int nstype = 0)
237 C_ARGS: s_fileno (fh_or_fd, 0), nstype
238
239 int
240 pivot_root (SV *new_root, SV *old_root)
241 CODE:
242 RETVAL = syscall (SYS_pivot_root,
243 (const char *)SvPVbyte_nolen (new_root),
244 (const char *)SvPVbyte_nolen (old_root));
245 OUTPUT: RETVAL
246
247 int
248 kcmp (IV pid1, IV pid2, IV type, UV idx1 = 0, UV idx2 = 0)
249
250 int
251 siocsifflags (char *ifname, U32 flags = IFF_UP)
252 CODE:
253 {
254 int saved_errno;
255 struct ifreq ifr;
256 int fd = socket (AF_INET, SOCK_DGRAM, 0);
257 strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
258 RETVAL = ioctl (fd, SIOCSIFFLAGS, &ifr);
259 saved_errno = errno;
260 close (fd);
261 errno = saved_errno;
262 }
263 OUTPUT: RETVAL
264