ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-Clone/Clone.xs
Revision: 1.12
Committed: Wed Apr 8 20:28:06 2026 UTC (5 months, 2 weeks ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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