line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT |
2
|
|
|
|
|
|
|
#include "easyxs/easyxs.h" |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
// Cribbed from Socket.xs: |
5
|
|
|
|
|
|
|
/* STRUCT_OFFSET should have come from from perl.h, but if not, |
6
|
|
|
|
|
|
|
* roll our own (not using offsetof() since that is C99). */ |
7
|
|
|
|
|
|
|
#ifndef STRUCT_OFFSET |
8
|
|
|
|
|
|
|
# define STRUCT_OFFSET(s,m) (Size_t)(&(((s *)0)->m)) |
9
|
|
|
|
|
|
|
#endif |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#define STRUCT_MEMBER_SIZE(s,m) sizeof(((s *)0)->m) |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#define SA_FAMILY_END_OFFSET ( \ |
14
|
|
|
|
|
|
|
STRUCT_OFFSET(struct sockaddr, sa_family) \ |
15
|
|
|
|
|
|
|
+ STRUCT_MEMBER_SIZE(struct sockaddr, sa_family) \ |
16
|
|
|
|
|
|
|
) |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
// Modern Win32 releases do support UNIX sockets via afunix.h, |
19
|
|
|
|
|
|
|
// but that header file isn’t available on MinGW. Socket.xs defines |
20
|
|
|
|
|
|
|
// the necessary structs and constants directly; if needed we could |
21
|
|
|
|
|
|
|
// take that approach, but for now let’s just forgo UNIX socket support |
22
|
|
|
|
|
|
|
// unless there’s sys/un.h. |
23
|
|
|
|
|
|
|
#ifdef I_SYS_UN // cf. perl5 Porting/Glossary |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#define HAS_UNIX_SOCKETS 1 |
26
|
|
|
|
|
|
|
#include |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
#define SUN_PATH_LEN STRUCT_MEMBER_SIZE(struct sockaddr_un, sun_path) |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#else |
31
|
|
|
|
|
|
|
#define HAS_UNIX_SOCKETS 0 |
32
|
|
|
|
|
|
|
#endif |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
#include |
35
|
|
|
|
|
|
|
#include |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#include "ppport.h" |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#define DEBUG 0 |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
/* A duplicate of PL_ppaddr as we find it at BOOT time. |
42
|
|
|
|
|
|
|
We can thus overwrite PL_ppaddr with our own wrapper functions. |
43
|
|
|
|
|
|
|
This interacts better with wrap_op_checker(), which doesn’t provide |
44
|
|
|
|
|
|
|
a good way to call the op’s (now-overwritten) op_ppaddr callback. |
45
|
|
|
|
|
|
|
*/ |
46
|
|
|
|
|
|
|
static Perl_ppaddr_t ORIG_PL_ppaddr[OP_max]; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
#define MYPKG "Filesys::Restrict" |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
/* An idempotent variant of dMARK that allows us to inspect the |
51
|
|
|
|
|
|
|
mark stack without changing it: */ |
52
|
|
|
|
|
|
|
#ifndef dMARK_TOPMARK |
53
|
|
|
|
|
|
|
#define dMARK_TOPMARK SV **mark = PL_stack_base + TOPMARK |
54
|
|
|
|
|
|
|
#endif |
55
|
|
|
|
|
|
|
|
56
|
161
|
|
|
|
|
|
static inline SV* _get_callback(pTHX) { |
57
|
161
|
|
|
|
|
|
SV* callback = get_sv(MYPKG "::_AUTHORIZE", 0); |
58
|
|
|
|
|
|
|
|
59
|
161
|
50
|
|
|
|
|
if (callback && !SvOK(callback)) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
60
|
5
|
|
|
|
|
|
callback = NULL; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
161
|
|
|
|
|
|
return callback; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#define _IS_FILEHANDLE(expr) ( \ |
67
|
|
|
|
|
|
|
(SvTYPE(expr) == SVt_PVGV) || \ |
68
|
|
|
|
|
|
|
(SvROK(expr) && SvTYPE(SvRV(expr)) == SVt_PVGV) || \ |
69
|
|
|
|
|
|
|
(SvTYPE(expr) == SVt_PVIO) || \ |
70
|
|
|
|
|
|
|
(SvROK(expr) && SvTYPE(SvRV(expr)) == SVt_PVIO) \ |
71
|
|
|
|
|
|
|
) |
72
|
|
|
|
|
|
|
|
73
|
25
|
|
|
|
|
|
bool _is_pipe_open(pTHX_ const char* str, STRLEN len) { |
74
|
25
|
100
|
|
|
|
|
if (len >= 2) { |
75
|
17
|
50
|
|
|
|
|
if (memEQ("|-", str, 2)) return true; |
76
|
17
|
50
|
|
|
|
|
if (memEQ("-|", str, 2)) return true; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
25
|
|
|
|
|
|
return false; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
#define _IS_SCALAR_REF(sv) (SvROK(sv) && (SvTYPE(SvRV(sv)) < SVt_PVGV)) |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
// Returns NULL to indicate no path. |
85
|
13
|
|
|
|
|
|
static SV* _get_path_from_3arg_open(pTHX_ SV* mode, SV* expr) { |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
// 3-arg open with undef 3rd arg opens an anonymous tempfile. |
88
|
13
|
100
|
|
|
|
|
if (!SvOK(expr)) return NULL; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
// Ignore scalar-reference paths, which indicate an “open” |
91
|
|
|
|
|
|
|
// of a Perl scalar. |
92
|
12
|
100
|
|
|
|
|
if (_IS_SCALAR_REF(expr)) return NULL; |
|
|
50
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
12
|
50
|
|
|
|
|
if (!SvPOK(mode)) croak("mode isn’t a string?!?"); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
STRLEN modelen; |
97
|
12
|
50
|
|
|
|
|
const char* modestr = SvPVbyte(mode, modelen); |
98
|
|
|
|
|
|
|
|
99
|
12
|
50
|
|
|
|
|
if (_is_pipe_open(aTHX_ modestr, modelen)) return NULL; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
// If the last character of the mode is '=' then expr is a |
102
|
|
|
|
|
|
|
// file descriptor or filehandle, so we shouldn’t care. |
103
|
12
|
100
|
|
|
|
|
if (NULL != strchr(modestr, '&')) return NULL; |
104
|
|
|
|
|
|
|
|
105
|
13
|
|
|
|
|
|
return expr; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
13
|
|
|
|
|
|
static SV* _get_path_from_2arg_open(pTHX_ SV* expr) { |
109
|
|
|
|
|
|
|
STRLEN len; |
110
|
13
|
50
|
|
|
|
|
const char* str = SvPVbyte(expr, len); |
111
|
|
|
|
|
|
|
|
112
|
13
|
50
|
|
|
|
|
if (_is_pipe_open(aTHX_ str, len)) return NULL; |
113
|
|
|
|
|
|
|
|
114
|
13
|
50
|
|
|
|
|
if (len < 1) return NULL; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
// Special cases: |
117
|
13
|
50
|
|
|
|
|
if (len == 2) { |
118
|
0
|
0
|
|
|
|
|
if (memEQ(str, ">-", 2)) return NULL; // opens STDOUT |
119
|
0
|
0
|
|
|
|
|
if (memEQ(str, "<-", 2)) return NULL; // opens STDIN |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
13
|
|
|
|
|
|
STRLEN idx = 0; |
123
|
|
|
|
|
|
|
|
124
|
13
|
100
|
|
|
|
|
if (str[idx] == '+') idx++; |
125
|
|
|
|
|
|
|
|
126
|
13
|
100
|
|
|
|
|
if (str[idx] == '<') { |
127
|
5
|
|
|
|
|
|
idx++; |
128
|
|
|
|
|
|
|
} |
129
|
8
|
50
|
|
|
|
|
else if (str[idx] == '>') { |
130
|
8
|
|
|
|
|
|
idx++; |
131
|
|
|
|
|
|
|
|
132
|
8
|
100
|
|
|
|
|
if (str[idx] == '>') idx++; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
else { |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
// For now ignore anything that isn’t +>, +>>, +<, >, >>, or <. |
137
|
0
|
|
|
|
|
|
return NULL; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
// Duplicating a filehandle or file descriptor is always OK. |
141
|
13
|
50
|
|
|
|
|
if (str[idx] == '&') return NULL; |
142
|
|
|
|
|
|
|
|
143
|
13
|
|
|
|
|
|
return newSVpvn_flags( |
144
|
|
|
|
|
|
|
str + idx, |
145
|
|
|
|
|
|
|
len - idx, |
146
|
|
|
|
|
|
|
SVs_TEMP |
147
|
|
|
|
|
|
|
); |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
195
|
|
|
|
|
|
static inline void _prep_stack(pTHX_ SV** args, unsigned argscount) { |
151
|
195
|
|
|
|
|
|
dSP; |
152
|
|
|
|
|
|
|
|
153
|
195
|
|
|
|
|
|
ENTER; |
154
|
195
|
|
|
|
|
|
SAVETMPS; |
155
|
|
|
|
|
|
|
|
156
|
195
|
50
|
|
|
|
|
PUSHMARK(SP); |
157
|
195
|
50
|
|
|
|
|
EXTEND(SP, argscount); |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
unsigned a; |
160
|
|
|
|
|
|
|
|
161
|
585
|
100
|
|
|
|
|
for (a=0; a < argscount; a++) PUSHs(args[a]); |
162
|
|
|
|
|
|
|
|
163
|
195
|
|
|
|
|
|
PUTBACK; |
164
|
195
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
138
|
|
|
|
|
|
static inline void _authorize(pTHX_ int OPID, SV* path_sv, SV* callback_sv) { |
167
|
138
|
|
|
|
|
|
const char* opname = PL_op_desc[OPID]; |
168
|
|
|
|
|
|
|
|
169
|
138
|
|
|
|
|
|
dSP; |
170
|
|
|
|
|
|
|
|
171
|
138
|
|
|
|
|
|
SV* args[] = { |
172
|
138
|
|
|
|
|
|
newSVpvn_flags(opname, strlen(opname), SVs_TEMP), |
173
|
|
|
|
|
|
|
path_sv, |
174
|
|
|
|
|
|
|
}; |
175
|
|
|
|
|
|
|
|
176
|
138
|
|
|
|
|
|
_prep_stack(aTHX_ args, 2); |
177
|
|
|
|
|
|
|
|
178
|
138
|
|
|
|
|
|
I32 returns = call_sv( callback_sv, G_SCALAR ); |
179
|
|
|
|
|
|
|
|
180
|
138
|
|
|
|
|
|
SPAGAIN; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
bool authorized; |
183
|
|
|
|
|
|
|
|
184
|
138
|
50
|
|
|
|
|
if (returns) { |
185
|
138
|
|
|
|
|
|
SV* got = POPs; |
186
|
138
|
50
|
|
|
|
|
authorized = SvTRUE(got); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
else { |
189
|
0
|
|
|
|
|
|
authorized = false; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
138
|
|
|
|
|
|
PUTBACK; |
193
|
138
|
50
|
|
|
|
|
FREETMPS; |
194
|
138
|
|
|
|
|
|
LEAVE; |
195
|
|
|
|
|
|
|
|
196
|
138
|
100
|
|
|
|
|
if (!authorized) { |
197
|
57
|
|
|
|
|
|
_prep_stack(aTHX_ args, 2); |
198
|
|
|
|
|
|
|
|
199
|
57
|
|
|
|
|
|
call_pv( MYPKG "::_CROAK", G_VOID | G_DISCARD ); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
// We should never get here: |
202
|
|
|
|
|
|
|
assert(0); |
203
|
|
|
|
|
|
|
} |
204
|
81
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
// open() is such a funny beast that it gets its own wrapper. |
207
|
26
|
|
|
|
|
|
static OP* _wrapped_pp_OP_OPEN(pTHX) { |
208
|
26
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); |
209
|
26
|
50
|
|
|
|
|
if (callback) { |
210
|
26
|
|
|
|
|
|
dSP; |
211
|
26
|
|
|
|
|
|
dMARK_TOPMARK; |
212
|
|
|
|
|
|
|
|
213
|
26
|
|
|
|
|
|
int numargs = SP - MARK; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
SV* path; |
216
|
|
|
|
|
|
|
|
217
|
26
|
|
|
|
|
|
switch (numargs) { |
218
|
|
|
|
|
|
|
case 1: |
219
|
0
|
|
|
|
|
|
path = NULL; |
220
|
0
|
|
|
|
|
|
break; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
case 2: |
223
|
13
|
|
|
|
|
|
path = _get_path_from_2arg_open(aTHX_ MARK[2]); |
224
|
13
|
|
|
|
|
|
break; |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
case 3: |
227
|
13
|
|
|
|
|
|
path = _get_path_from_3arg_open(aTHX_ MARK[2], MARK[3]); |
228
|
|
|
|
|
|
|
|
229
|
13
|
|
|
|
|
|
break; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
default: |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
// Shouldn’t happen, but just in case … |
234
|
0
|
|
|
|
|
|
croak("Bad # of args: %d", numargs); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
26
|
100
|
|
|
|
|
if (path) { |
238
|
21
|
|
|
|
|
|
_authorize(aTHX_ OP_OPEN, path, callback); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
17
|
|
|
|
|
|
return ORIG_PL_ppaddr[OP_OPEN](aTHX); |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
# if 0 |
246
|
|
|
|
|
|
|
// require() also gets its own wrapper since it depends on @INC. |
247
|
|
|
|
|
|
|
static OP* _wrapped_pp_OP_REQUIRE(pTHX) { |
248
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); |
249
|
|
|
|
|
|
|
if (callback) { |
250
|
|
|
|
|
|
|
dSP; |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
SV* required = *SP; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
STRLEN reqlen; |
255
|
|
|
|
|
|
|
const char* required_str = SvPVbyte(required, reqlen); |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
if (reqlen && NULL != strchr("./", required_str[0])) { |
258
|
|
|
|
|
|
|
_authorize(aTHX_ OP_REQUIRE, required, callback); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OP_REQUIRE](aTHX); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
#endif |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
#define MAKE_LAST_ARG_WRAPPER(OPID, CHECK_FH) \ |
267
|
|
|
|
|
|
|
static OP* _wrapped_pp_##OPID(pTHX) { \ |
268
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); \ |
269
|
|
|
|
|
|
|
if (callback) { \ |
270
|
|
|
|
|
|
|
dSP; \ |
271
|
|
|
|
|
|
|
if (!CHECK_FH || !_IS_FILEHANDLE(*SP)) { \ |
272
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, *SP, callback); \ |
273
|
|
|
|
|
|
|
} \ |
274
|
|
|
|
|
|
|
} \ |
275
|
|
|
|
|
|
|
\ |
276
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OPID](aTHX); \ |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
#define MAKE_LAST_ARG_WRAPPER_CHECK_FH(OPID) \ |
280
|
|
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER(OPID, 1) |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
#define MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OPID) \ |
283
|
|
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER(OPID, 0) |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#define MAKE_2ARG_WRAPPER(OPID) \ |
286
|
|
|
|
|
|
|
static OP* _wrapped_pp_##OPID(pTHX) { \ |
287
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); \ |
288
|
|
|
|
|
|
|
if (callback) { \ |
289
|
|
|
|
|
|
|
dSP; \ |
290
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, *SP, callback); \ |
291
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, *(SP - 1), callback); \ |
292
|
|
|
|
|
|
|
} \ |
293
|
|
|
|
|
|
|
\ |
294
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OPID](aTHX); \ |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
// ---------------------------------------------------------------------- |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
#define _MY_SET_SP_AND_MARK(OP_MAXARG) \ |
300
|
|
|
|
|
|
|
dSP; \ |
301
|
|
|
|
|
|
|
dMARK_TOPMARK; \ |
302
|
|
|
|
|
|
|
\ |
303
|
|
|
|
|
|
|
/* The compiler will optimize this away \ |
304
|
|
|
|
|
|
|
for MAKE_FIRST_ARG_OPEN_LIST_WRAPPER: \ |
305
|
|
|
|
|
|
|
*/ \ |
306
|
|
|
|
|
|
|
if (OP_MAXARG) \ |
307
|
|
|
|
|
|
|
if (SP < MARK || (SP - MARK) > OP_MAXARG) { \ |
308
|
|
|
|
|
|
|
unsigned numargs = MAXARG; \ |
309
|
|
|
|
|
|
|
MARK = SP; \ |
310
|
|
|
|
|
|
|
while (numargs--) MARK--; \ |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
/* For ops that take an indefinite number of args. */ |
314
|
|
|
|
|
|
|
#define MAKE_FIRST_ARG_OPEN_LIST_WRAPPER(OPID) \ |
315
|
|
|
|
|
|
|
MAKE_SINGLE_ARG_LIST_WRAPPER(OPID, 0, 0) |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
/* For ops whose number of string args is a fixed range. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
NB: In some perls, some list opts don’t set MARK. In those cases we |
320
|
|
|
|
|
|
|
fall back to MAXARG. As of now mkdir is the known “offender”, and |
321
|
|
|
|
|
|
|
only on Alpine Linux 3.11 & 3.12 (not 3.13). |
322
|
|
|
|
|
|
|
*/ |
323
|
|
|
|
|
|
|
#define MAKE_SINGLE_ARG_LIST_WRAPPER(OPID, ARG_INDEX, OP_MAXARG) \ |
324
|
|
|
|
|
|
|
static OP* _wrapped_pp_##OPID(pTHX) { \ |
325
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); \ |
326
|
|
|
|
|
|
|
if (callback) { \ |
327
|
|
|
|
|
|
|
_MY_SET_SP_AND_MARK(OP_MAXARG) \ |
328
|
|
|
|
|
|
|
\ |
329
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, MARK[1 + ARG_INDEX], callback); \ |
330
|
|
|
|
|
|
|
} \ |
331
|
|
|
|
|
|
|
\ |
332
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OPID](aTHX); \ |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
3
|
|
|
|
|
|
static OP* _wrapped_pp_OP_TRUNCATE(pTHX) { |
336
|
3
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); |
337
|
3
|
50
|
|
|
|
|
if (callback) { |
338
|
3
|
|
|
|
|
|
dSP; |
339
|
3
|
|
|
|
|
|
SV* first_arg = *(SP - 1); |
340
|
|
|
|
|
|
|
|
341
|
3
|
50
|
|
|
|
|
if (!_IS_FILEHANDLE(first_arg)) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
342
|
2
|
|
|
|
|
|
_authorize(aTHX_ OP_TRUNCATE, first_arg, callback); |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
2
|
|
|
|
|
|
return ORIG_PL_ppaddr[OP_TRUNCATE](aTHX); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
#define MAKE_ALL_ARGS_LIST_WRAPPER_CHECK_FH(OPID, ARG_INDEX) \ |
350
|
|
|
|
|
|
|
static OP* _wrapped_pp_##OPID(pTHX) { \ |
351
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); \ |
352
|
|
|
|
|
|
|
if (callback) { \ |
353
|
|
|
|
|
|
|
_MY_SET_SP_AND_MARK(0) \ |
354
|
|
|
|
|
|
|
\ |
355
|
|
|
|
|
|
|
MARK += ARG_INDEX; \ |
356
|
|
|
|
|
|
|
while (++MARK <= SP) { \ |
357
|
|
|
|
|
|
|
if (!_IS_FILEHANDLE(*MARK)) { \ |
358
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, *MARK, callback); \ |
359
|
|
|
|
|
|
|
} \ |
360
|
|
|
|
|
|
|
} \ |
361
|
|
|
|
|
|
|
} \ |
362
|
|
|
|
|
|
|
\ |
363
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OPID](aTHX); \ |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
/* For ops where only the last arg is a string. */ |
367
|
|
|
|
|
|
|
#define MAKE_SOCKET_OP_WRAPPER(OPID) \ |
368
|
|
|
|
|
|
|
static OP* _wrapped_pp_##OPID(pTHX) { \ |
369
|
|
|
|
|
|
|
SV* callback = _get_callback(aTHX); \ |
370
|
|
|
|
|
|
|
if (callback) { \ |
371
|
|
|
|
|
|
|
dSP; \ |
372
|
|
|
|
|
|
|
STRLEN pathlen; \ |
373
|
|
|
|
|
|
|
const char* path = _get_local_socket_path(aTHX_ SP[0], &pathlen); \ |
374
|
|
|
|
|
|
|
if (path) { \ |
375
|
|
|
|
|
|
|
SV* path_sv = newSVpvn_flags(path, pathlen, SVs_TEMP); \ |
376
|
|
|
|
|
|
|
_authorize(aTHX_ OPID, path_sv, callback); \ |
377
|
|
|
|
|
|
|
} \ |
378
|
|
|
|
|
|
|
} \ |
379
|
|
|
|
|
|
|
\ |
380
|
|
|
|
|
|
|
return ORIG_PL_ppaddr[OPID](aTHX); \ |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
6
|
|
|
|
|
|
static const char* _get_local_socket_path(pTHX_ SV* sockname_sv, STRLEN *pathlen) { |
384
|
6
|
|
|
|
|
|
char* path = NULL; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
#if HAS_UNIX_SOCKETS |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
STRLEN sockname_len; |
389
|
6
|
50
|
|
|
|
|
const char* sockname_str = SvPVbyte(sockname_sv, sockname_len); |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
// Let Perl handle the failure state: |
392
|
6
|
50
|
|
|
|
|
if (sockname_len >= SA_FAMILY_END_OFFSET) { |
393
|
6
|
|
|
|
|
|
sa_family_t family = ( (struct sockaddr*) sockname_str )->sa_family; |
394
|
|
|
|
|
|
|
|
395
|
6
|
50
|
|
|
|
|
if (family == AF_UNIX) { |
396
|
6
|
|
|
|
|
|
path = ( (struct sockaddr_un*) sockname_str )->sun_path; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
// We could compute pathlen via strlen(), but that would break |
399
|
|
|
|
|
|
|
// Linux abstract-namespace sockets. We could start at the end |
400
|
|
|
|
|
|
|
// of sun_path and find the first non-NUL, but that breaks in |
401
|
|
|
|
|
|
|
// macOS (at least), which doesn’t zero out the rest of |
402
|
|
|
|
|
|
|
// sun_path. |
403
|
|
|
|
|
|
|
// |
404
|
|
|
|
|
|
|
// So, we make a special exception for leading-NUL. :( |
405
|
|
|
|
|
|
|
// |
406
|
6
|
100
|
|
|
|
|
if (path[0] == '\0') { |
407
|
1
|
|
|
|
|
|
*pathlen = 1 + strnlen(1 + path, SUN_PATH_LEN - 1); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
else { |
410
|
5
|
|
|
|
|
|
*pathlen = strnlen(path, SUN_PATH_LEN); |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
#endif |
415
|
|
|
|
|
|
|
|
416
|
6
|
|
|
|
|
|
return path; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
7
|
50
|
|
|
|
|
MAKE_SOCKET_OP_WRAPPER(OP_BIND); |
|
|
50
|
|
|
|
|
|
420
|
3
|
50
|
|
|
|
|
MAKE_SOCKET_OP_WRAPPER(OP_CONNECT); |
|
|
50
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
422
|
6
|
50
|
|
|
|
|
MAKE_SINGLE_ARG_LIST_WRAPPER(OP_SYSOPEN, 1, 4); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
423
|
|
|
|
|
|
|
|
424
|
0
|
0
|
|
|
|
|
MAKE_FIRST_ARG_OPEN_LIST_WRAPPER(OP_EXEC); |
425
|
6
|
50
|
|
|
|
|
MAKE_FIRST_ARG_OPEN_LIST_WRAPPER(OP_SYSTEM); |
426
|
|
|
|
|
|
|
|
427
|
0
|
0
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_LSTAT); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
428
|
2
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_STAT); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
429
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTRREAD); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
430
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTRWRITE); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
431
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTREXEC); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
432
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTEREAD); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
433
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTEWRITE); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
434
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTEEXEC); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
435
|
7
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTIS); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
436
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTSIZE); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
437
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTMTIME); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
438
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTATIME); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
439
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTCTIME); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
440
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTROWNED); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
441
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTEOWNED); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
442
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTZERO); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
443
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTSOCK); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
444
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTCHR); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
445
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTBLK); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
446
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTFILE); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
447
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTDIR); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
448
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTPIPE); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
449
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTSUID); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
450
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTSGID); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
451
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTSVTX); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
452
|
3
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTLINK); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
453
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTTEXT); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
454
|
5
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_FTBINARY); |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
455
|
0
|
0
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_CHECK_FH(OP_CHDIR); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
456
|
13
|
50
|
|
|
|
|
MAKE_ALL_ARGS_LIST_WRAPPER_CHECK_FH(OP_CHOWN, 2); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
457
|
0
|
0
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_CHROOT); |
458
|
10
|
50
|
|
|
|
|
MAKE_ALL_ARGS_LIST_WRAPPER_CHECK_FH(OP_UNLINK, 0); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
459
|
16
|
50
|
|
|
|
|
MAKE_ALL_ARGS_LIST_WRAPPER_CHECK_FH(OP_CHMOD, 1); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
460
|
13
|
50
|
|
|
|
|
MAKE_ALL_ARGS_LIST_WRAPPER_CHECK_FH(OP_UTIME, 2); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
461
|
5
|
50
|
|
|
|
|
MAKE_2ARG_WRAPPER(OP_RENAME); |
462
|
5
|
50
|
|
|
|
|
MAKE_2ARG_WRAPPER(OP_LINK); |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
// symlink() is special: its “target” (the first arg) and doesn’t |
465
|
|
|
|
|
|
|
// need to refer to a valid filesystem node. |
466
|
0
|
0
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_SYMLINK); |
467
|
|
|
|
|
|
|
|
468
|
3
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_READLINK); |
469
|
16
|
100
|
|
|
|
|
MAKE_SINGLE_ARG_LIST_WRAPPER(OP_MKDIR, 0, 2); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
470
|
3
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_RMDIR); |
471
|
3
|
50
|
|
|
|
|
MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_OPEN_DIR); |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
// MAKE_LAST_ARG_WRAPPER_NO_CHECK_FH(OP_DOFILE); |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */ |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
#define MAKE_BOOT_WRAPPER(OPID) \ |
478
|
|
|
|
|
|
|
ORIG_PL_ppaddr[OPID] = PL_ppaddr[OPID]; \ |
479
|
|
|
|
|
|
|
PL_ppaddr[OPID] = _wrapped_pp_##OPID; |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
//---------------------------------------------------------------------- |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
bool initialized = false; |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
MODULE = Filesys::Restrict PACKAGE = Filesys::Restrict |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
BOOT: |
490
|
|
|
|
|
|
|
/* In theory this is for PL_check rather than PL_ppaddr, but per |
491
|
|
|
|
|
|
|
Paul Evans in practice this mutex gets used for other stuff, too. |
492
|
|
|
|
|
|
|
Paul says a race here should be exceptionally rare, so for pre-5.16 |
493
|
|
|
|
|
|
|
perls (which lack this mutex) let’s just skip it. |
494
|
|
|
|
|
|
|
*/ |
495
|
|
|
|
|
|
|
#ifdef OP_CHECK_MUTEX_LOCK |
496
|
|
|
|
|
|
|
OP_CHECK_MUTEX_LOCK; |
497
|
|
|
|
|
|
|
#endif |
498
|
6
|
50
|
|
|
|
|
if (!initialized) { |
499
|
6
|
|
|
|
|
|
initialized = true; |
500
|
|
|
|
|
|
|
|
501
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_OPEN); |
502
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_SYSOPEN); |
503
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_TRUNCATE); |
504
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_EXEC); |
505
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_SYSTEM); |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
if (HAS_UNIX_SOCKETS) { |
508
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_BIND); |
509
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_CONNECT); |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
6
|
|
|
|
|
|
HV *stash = gv_stashpv(MYPKG, FALSE); |
513
|
6
|
|
|
|
|
|
newCONSTSUB(stash, "_HAS_UNIX_SOCKETS", boolSV(HAS_UNIX_SOCKETS)); |
514
|
|
|
|
|
|
|
|
515
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_LSTAT); |
516
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_STAT); |
517
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTRREAD); |
518
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTRWRITE); |
519
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTREXEC); |
520
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTEREAD); |
521
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTEWRITE); |
522
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTEEXEC); |
523
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTIS); |
524
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTSIZE); |
525
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTMTIME); |
526
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTATIME); |
527
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTCTIME); |
528
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTROWNED); |
529
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTEOWNED); |
530
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTZERO); |
531
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTSOCK); |
532
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTCHR); |
533
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTBLK); |
534
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTFILE); |
535
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTDIR); |
536
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTPIPE); |
537
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTSUID); |
538
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTSGID); |
539
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTSVTX); |
540
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTLINK); |
541
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTTEXT); |
542
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_FTBINARY); |
543
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_CHDIR); |
544
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_CHOWN); |
545
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_CHROOT); |
546
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_UNLINK); |
547
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_CHMOD); |
548
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_UTIME); |
549
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_RENAME); |
550
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_LINK); |
551
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_SYMLINK); |
552
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_READLINK); |
553
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_MKDIR); |
554
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_RMDIR); |
555
|
6
|
|
|
|
|
|
MAKE_BOOT_WRAPPER(OP_OPEN_DIR); |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
// MAKE_BOOT_WRAPPER(OP_REQUIRE); |
558
|
|
|
|
|
|
|
// MAKE_BOOT_WRAPPER(OP_DOFILE); |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
#ifdef OP_CHECK_MUTEX_UNLOCK |
561
|
|
|
|
|
|
|
OP_CHECK_MUTEX_UNLOCK; |
562
|
|
|
|
|
|
|
#endif |