| 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 |