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

# User Rev Content
1 root 1.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 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.7 #include <linux/nsfs.h>
20 root 1.8 #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 root 1.7
28 root 1.4 #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 root 1.3 #ifdef SYS_kcmp
35 root 1.4 #include "linux/kcmp.h"
36 root 1.3 #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 root 1.1
44 root 1.2 /* 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 root 1.1 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 root 1.4 # define const_iv(name) { # name, (IV)name },
94     # define const_iv_clone(name) { # name, (IV) CLONE_ ## name },
95 root 1.6 # ifdef CSIGNAL
96     const_iv (CSIGNAL)
97     # endif
98 root 1.1 # ifdef CLONE_FILES
99 root 1.4 const_iv_clone (FILES)
100 root 1.1 # endif
101     # ifdef CLONE_FS
102 root 1.4 const_iv_clone (FS)
103 root 1.1 # endif
104     # ifdef CLONE_NEWNS
105 root 1.4 const_iv_clone (NEWNS)
106 root 1.1 # endif
107     # ifdef CLONE_VM
108 root 1.4 const_iv_clone (VM)
109 root 1.1 # endif
110     # ifdef CLONE_THREAD
111 root 1.4 const_iv_clone (THREAD)
112 root 1.1 # endif
113     # ifdef CLONE_SIGHAND
114 root 1.4 const_iv_clone (SIGHAND)
115 root 1.1 # endif
116     # ifdef CLONE_SYSVSEM
117 root 1.4 const_iv_clone (SYSVSEM)
118 root 1.1 # endif
119     # ifdef CLONE_NEWUTS
120 root 1.4 const_iv_clone (NEWUTS)
121 root 1.1 # endif
122     # ifdef CLONE_NEWIPC
123 root 1.4 const_iv_clone (NEWIPC)
124 root 1.1 # endif
125     # ifdef CLONE_NEWNET
126 root 1.4 const_iv_clone (NEWNET)
127 root 1.1 # endif
128 root 1.8 # ifdef CLONE_NEWTIME
129     x
130     const_iv_clone (NEWTIME)
131     # endif
132 root 1.1 # ifdef CLONE_PTRACE
133 root 1.4 const_iv_clone (PTRACE)
134 root 1.1 # endif
135     # ifdef CLONE_VFORK
136 root 1.4 const_iv_clone (VFORK)
137 root 1.1 # endif
138     # ifdef CLONE_SETTLS
139 root 1.4 const_iv_clone (SETTLS)
140 root 1.1 # endif
141     # ifdef CLONE_PARENT_SETTID
142 root 1.4 const_iv_clone (PARENT_SETTID)
143 root 1.1 # endif
144     # ifdef CLONE_CHILD_CLEARTID
145 root 1.4 const_iv_clone (CHILD_CLEARTID)
146 root 1.1 # endif
147     # ifdef CLONE_DETACHED
148 root 1.4 const_iv_clone (DETACHED)
149 root 1.1 # endif
150     # ifdef CLONE_UNTRACED
151 root 1.4 const_iv_clone (UNTRACED)
152 root 1.1 # endif
153     # ifdef CLONE_CHILD_SETTID
154 root 1.4 const_iv_clone (CHILD_SETTID)
155 root 1.1 # endif
156     # ifdef CLONE_NEWUSER
157 root 1.4 const_iv_clone (NEWUSER)
158 root 1.1 # endif
159     # ifdef CLONE_NEWPID
160 root 1.4 const_iv_clone (NEWPID)
161 root 1.1 # endif
162     # ifdef CLONE_IO
163 root 1.4 const_iv_clone (IO)
164 root 1.1 # endif
165 root 1.2 # ifdef CLONE_NEWCGROUP
166 root 1.4 const_iv_clone (NEWCGROUP)
167 root 1.3 # endif
168 root 1.5 # ifdef CLONE_PIDFD
169     const_iv_clone (PIDFD)
170     # endif
171 root 1.3 # 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 root 1.8 const_iv (KCMP_EPOLL_TFD)
180 root 1.2 # endif
181 root 1.7 # 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 root 1.1 };
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 root 1.2 if (!stacksize)
203 root 1.1 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 root 1.6 OUTPUT: RETVAL
230 root 1.1
231 root 1.2 int
232     unshare (int flags)
233 root 1.9 PROTOTYPE: @
234 root 1.2
235     int
236     setns (SV *fh_or_fd, int nstype = 0)
237     C_ARGS: s_fileno (fh_or_fd, 0), nstype
238 root 1.3
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 root 1.6 OUTPUT: RETVAL
246 root 1.3
247     int
248     kcmp (IV pid1, IV pid2, IV type, UV idx1 = 0, UV idx2 = 0)
249    
250 root 1.6 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