Branch data Line data Source code
1 : : /*
2 : : * Should only be included from strace.c, so no include guards.
3 : : */
4 : :
5 : : #include <lualib.h>
6 : : #include <lauxlib.h>
7 : :
8 : : #define L script_L
9 : :
10 : : static struct tcb *
11 : 28740 : func_next_sc(void)
12 : : {
13 : : static struct timeval tv = {};
14 : : static bool first = true;
15 : :
16 : : #define MAYBE_RESTART(res, sig) \
17 : : do { \
18 : : if ((res) >= 0 && ptrace_restart(PTRACE_SYSCALL, current_tcp, sig) < 0) { \
19 : : /* Note: ptrace_restart emitted error message */ \
20 : : exit_code = 1; \
21 : : goto term; \
22 : : } \
23 : : } while (0)
24 : :
25 [ + + ]: 28740 : if (!first) {
26 [ + + ]: 28696 : if (!current_tcp)
27 : 28 : return NULL;
28 : :
29 : 28668 : unsigned int sig = 0;
30 : : int res;
31 [ + + ]: 28668 : if (entering(current_tcp)) {
32 : 28655 : res = syscall_entering_trace(current_tcp, &sig);
33 : 28655 : syscall_entering_finish(current_tcp, res);
34 : : } else {
35 : 13 : res = syscall_exiting_trace(current_tcp, tv, 1);
36 : 13 : syscall_exiting_finish(current_tcp);
37 : : }
38 [ + - ][ - + ]: 28668 : MAYBE_RESTART(res, sig);
39 : : }
40 : 28712 : first = false;
41 : :
42 : : while (1) {
43 : : int status;
44 : : siginfo_t si;
45 : 301473 : enum trace_event ret = next_event(&status, &si);
46 [ + + ]: 301473 : if (ret == TE_SYSCALL_STOP) {
47 : 301172 : unsigned int sig = 0;
48 : : int res;
49 [ + + ]: 301172 : if (entering(current_tcp)) {
50 : 150608 : res = syscall_entering_decode(current_tcp);
51 [ + - - ]: 150608 : switch (res) {
52 : : case 0:
53 : : break;
54 : : case 1:
55 [ + + ]: 150608 : if (current_tcp->qual_flg & QUAL_HOOK_ENTRY)
56 : 28671 : return current_tcp;
57 : 121950 : res = syscall_entering_trace(current_tcp, &sig);
58 : : /* fall through */
59 : : default:
60 : 121950 : syscall_entering_finish(current_tcp, res);
61 : : }
62 : : } else {
63 : 150564 : res = syscall_exiting_decode(current_tcp, &tv);
64 [ + - + ]: 150564 : switch (res) {
65 : : case 0:
66 : : break;
67 : : case 1:
68 [ + + ]: 251 : if (current_tcp->qual_flg & QUAL_HOOK_EXIT)
69 : 13 : return current_tcp;
70 : : /* fall through */
71 : : default:
72 : 238 : res = syscall_exiting_trace(current_tcp, tv, res);
73 : : }
74 : 150551 : syscall_exiting_finish(current_tcp);
75 : : }
76 [ + - ][ - + ]: 272501 : MAYBE_RESTART(res, sig);
77 : : } else {
78 [ + + ]: 301 : if (!dispatch_event(ret, &status, &si))
79 : : goto term;
80 : : }
81 : 272802 : }
82 : : #undef MAYBE_RESTART
83 : : term:
84 : 41 : current_tcp = NULL;
85 : 41 : return NULL;
86 : : }
87 : :
88 : : static bool
89 : 13439 : func_monitor(unsigned int scno, unsigned int pers, bool entry_hook, bool exit_hook)
90 : : {
91 [ + - ][ + - ]: 13439 : if (pers >= SUPPORTED_PERSONALITIES || scno >= nsyscall_vec[pers])
92 : : return false;
93 : 13439 : set_hook_qual(scno, pers, entry_hook, exit_hook);
94 : 13439 : return true;
95 : : }
96 : :
97 : : static void
98 : 16 : prepare_ad_hoc_inject(void)
99 : : {
100 : 16 : struct inject_opts *opts = current_tcp->ad_hoc_inject_opts;
101 [ + + ]: 16 : if (!opts) {
102 : 12 : opts = current_tcp->ad_hoc_inject_opts = xmalloc(sizeof(*opts));
103 : 12 : opts->first = 1;
104 : 12 : opts->step = 1;
105 : : }
106 [ + + ]: 16 : if (!(current_tcp->flags & TCB_AD_HOC_INJECT)) {
107 : 13 : opts->signo = 0;
108 : 13 : opts->rval = INJECT_OPTS_RVAL_DEFAULT;
109 : 13 : current_tcp->qual_flg |= QUAL_INJECT;
110 : 13 : current_tcp->flags |= TCB_AD_HOC_INJECT;
111 : : }
112 : 16 : }
113 : :
114 : : static bool
115 : 4 : func_inject_signo(int signo)
116 : : {
117 [ + - ][ + - ]: 4 : if (!current_tcp || exiting(current_tcp))
118 : : /* Too late! */
119 : : return false;
120 [ + - ][ + - ]: 4 : if (signo <= 0 || signo > SIGRTMAX)
121 : : return false;
122 : 4 : prepare_ad_hoc_inject();
123 : 4 : current_tcp->ad_hoc_inject_opts->signo = signo;
124 : 4 : return true;
125 : : }
126 : :
127 : : static bool
128 : 12 : func_inject_retval(int retval)
129 : : {
130 [ + - ][ + - ]: 12 : if (!current_tcp || exiting(current_tcp))
131 : : /* Too late! */
132 : : return false;
133 [ + - ]: 12 : if (retval < -MAX_ERRNO_VALUE)
134 : : return false;
135 : 12 : prepare_ad_hoc_inject();
136 : 12 : current_tcp->ad_hoc_inject_opts->rval = retval;
137 : 12 : return true;
138 : : }
139 : :
140 : : static int
141 : 25 : func_umove(kernel_ulong_t addr, size_t len, void *laddr)
142 : : {
143 [ + - ]: 25 : return current_tcp ? umoven(current_tcp, addr, len, laddr) : -1;
144 : : }
145 : :
146 : : static int
147 : 0 : func_umove_str(kernel_ulong_t addr, size_t len, char *laddr)
148 : : {
149 [ # # ]: 0 : return current_tcp ? umovestr(current_tcp, addr, len, laddr) : -1;
150 : : }
151 : :
152 : : static int
153 : 20 : func_upoke(kernel_ulong_t addr, size_t len, const void *laddr)
154 : : {
155 [ + - ]: 20 : return current_tcp ? upoken(current_tcp, addr, len, laddr) : -1;
156 : : }
157 : :
158 : : static bool
159 : 0 : func_path_match_arr(const char **set, size_t nset)
160 : : {
161 [ # # ]: 0 : if (!current_tcp)
162 : : return false;
163 : 0 : struct path_set s = {set, nset};
164 : 0 : return pathtrace_match_set(current_tcp, &s);
165 : : }
166 : :
167 : : static const char *
168 : 3 : get_lua_msg(void)
169 : : {
170 : 3 : const char *msg = lua_tostring(L, -1);
171 [ + - ]: 3 : return msg ? msg : "(error object can't be converted to string)";
172 : : }
173 : :
174 : : static void
175 : 924 : assert_lua_impl(int ret, const char *expr, const char *file, int line)
176 : : {
177 [ - + ]: 924 : if (ret == 0)
178 : 924 : return;
179 : 0 : error_msg_and_die("assert_lua(%s) failed at %s:%d: %s", expr, file,
180 : : line, get_lua_msg());
181 : : }
182 : :
183 : : #define assert_lua(expr) assert_lua_impl(expr, #expr, __FILE__, __LINE__)
184 : :
185 : : static void
186 : 130 : check_lua(int ret)
187 : : {
188 [ + + ]: 130 : if (ret == 0)
189 : 127 : return;
190 : 3 : error_msg_and_die("lua: %s", get_lua_msg());
191 : : }
192 : :
193 : : #ifdef LUA_FFILIBNAME
194 : : # define FFILIBNAME LUA_FFILIBNAME
195 : : #else
196 : : /* non-LuaJIT */
197 : : # define FFILIBNAME "ffi"
198 : : #endif
199 : :
200 : : #ifdef LUA_BITLIBNAME
201 : : # define BITLIBNAME LUA_BITLIBNAME
202 : : #else
203 : : /* Lua <= 5.1 (non-LuaJIT) */
204 : : # define BITLIBNAME "bit"
205 : : #endif
206 : :
207 : : static void
208 : 44 : init_luajit(const char *scriptfile)
209 : : {
210 [ - + ]: 44 : if (L)
211 : : /* already initialized? */
212 : 0 : error_msg_and_help("multiple -l arguments");
213 : :
214 [ - + ]: 44 : if (!(L = luaL_newstate()))
215 : 0 : error_msg_and_die("luaL_newstate failed (out of memory?)");
216 : :
217 : 44 : luaL_openlibs(L);
218 : :
219 : 44 : lua_getglobal(L, "require"); /* L: require */
220 : 44 : lua_pushstring(L, FFILIBNAME); /* L: require str */
221 : 44 : assert_lua(lua_pcall(L, 1, 1, 0)); /* L: ffi */
222 : 44 : lua_getfield(L, -1, "cdef"); /* L: ffi cdef */
223 : : luaL_Buffer b;
224 : 44 : luaL_buffinit(L, &b); /* L: ffi cdef ? */
225 : : {
226 : : char buf[128];
227 : 44 : snprintf(buf, sizeof(buf),
228 : : "typedef int%d_t kernel_long_t;"
229 : : "typedef uint%d_t kernel_ulong_t;",
230 : : (int) sizeof(kernel_long_t) * 8,
231 : : (int) sizeof(kernel_ulong_t) * 8);
232 : 44 : luaL_addstring(&b, buf); /* L: ffi cdef ? */
233 : : }
234 : 44 : const char *defs =
235 : : #define FFI_CDEF
236 : : #include "sysent.h"
237 : : #include "defs_shared.h"
238 : : #undef FFI_CDEF
239 : : ;
240 : 44 : luaL_addstring(&b, defs); /* L: ffi cdef ? */
241 : 44 : luaL_pushresult(&b); /* L: ffi cdef str */
242 : 44 : assert_lua(lua_pcall(L, 1, 0, 0)); /* L: ffi */
243 : :
244 : 44 : lua_newtable(L); /* L: ffi table */
245 : :
246 : 44 : lua_getfield(L, -2, "cast"); /* L: ffi table cast */
247 : 44 : lua_remove(L, -3); /* L: table cast */
248 : :
249 : : #define EXPOSE_FUNC(rettype, ptr, name, ...) \
250 : : do { \
251 : : rettype (*fptr_)(__VA_ARGS__) = ptr; \
252 : : lua_pushvalue(L, -1); /* L: table cast cast */ \
253 : : lua_pushstring(L, #rettype " (*)(" #__VA_ARGS__ ")"); \
254 : : /* L: table cast cast str */ \
255 : : lua_pushlightuserdata(L, * (void **) (&fptr_)); \
256 : : /* L: table cast cast str ptr */ \
257 : : assert_lua(lua_pcall(L, 2, 1, 0)); /* L: table cast value */ \
258 : : lua_setfield(L, -3, name); /* L: table cast */ \
259 : : } while (0)
260 : :
261 : 44 : EXPOSE_FUNC(bool, func_monitor, "monitor",
262 : : unsigned int, unsigned int, bool, bool);
263 : 44 : EXPOSE_FUNC(struct tcb *, func_next_sc, "next_sc",
264 : : void);
265 : 44 : EXPOSE_FUNC(bool, func_inject_signo, "inject_signo",
266 : : int);
267 : 44 : EXPOSE_FUNC(bool, func_inject_retval, "inject_retval",
268 : : int);
269 : 44 : EXPOSE_FUNC(int, func_umove, "umove",
270 : : kernel_ulong_t, size_t, void *);
271 : 44 : EXPOSE_FUNC(int, func_umove_str, "umove_str",
272 : : kernel_ulong_t, size_t, char *);
273 : 44 : EXPOSE_FUNC(int, func_upoke, "upoke",
274 : : kernel_ulong_t, size_t, const void *);
275 : 44 : EXPOSE_FUNC(bool, func_path_match_arr, "path_match_arr",
276 : : const char **, size_t);
277 : :
278 : : #undef EXPOSE_FUNC
279 : :
280 : : #define EXPOSE(type, ptr, name) \
281 : : do { \
282 : : /* Get a compilation error/warning on type mismatch */ \
283 : : type tmp_ = ptr; \
284 : : (void) tmp_; \
285 : : lua_pushvalue(L, -1); /* L: table cast cast */ \
286 : : lua_pushstring(L, #type); /* L: table cast cast str */ \
287 : : lua_pushlightuserdata(L, (void *) ptr); /* L: table cast cast str ptr */ \
288 : : assert_lua(lua_pcall(L, 2, 1, 0)); /* L: table cast value */ \
289 : : lua_setfield(L, -3, name); /* L: table cast */ \
290 : : } while (0)
291 : :
292 : 44 : EXPOSE(const struct_sysent *const *, sysent_vec, "sysent_vec");
293 : 44 : EXPOSE(const char *const **, errnoent_vec, "errnoent_vec");
294 : 44 : EXPOSE(const char *const **, signalent_vec, "signalent_vec");
295 : 44 : EXPOSE(const struct_ioctlent *const *, ioctlent_vec, "ioctlent_vec");
296 : :
297 : 44 : EXPOSE(const unsigned int *, nsyscall_vec, /*(!)*/ "nsysent_vec");
298 : 44 : EXPOSE(const unsigned int *, nerrnoent_vec, "nerrnoent_vec");
299 : 44 : EXPOSE(const unsigned int *, nsignalent_vec, "nsignalent_vec");
300 : 44 : EXPOSE(const unsigned int *, nioctlent_vec, "nioctlent_vec");
301 : :
302 : 44 : EXPOSE(const struct syscall_class *, syscall_classes, "syscall_classes");
303 : :
304 : : #undef EXPOSE
305 : :
306 : 44 : lua_pop(L, 1); /* L: table */
307 : :
308 : 44 : lua_pushinteger(L, SUPPORTED_PERSONALITIES); /* L: table int */
309 : 44 : lua_setfield(L, -2, "npersonalities"); /* L: table */
310 : :
311 : 44 : lua_pushinteger(L, MAX_ARGS); /* L: table int */
312 : 44 : lua_setfield(L, -2, "max_args"); /* L: table */
313 : :
314 : 44 : lua_pushinteger(L, PATH_MAX); /* L: table int */
315 : 44 : lua_setfield(L, -2, "path_max"); /* L: table */
316 : :
317 : 44 : lua_setglobal(L, "strace"); /* L: - */
318 : :
319 : 44 : const char *code =
320 : : #include "luajit_lib.h"
321 : : ;
322 : 44 : assert_lua(luaL_loadstring(L, code)); /* L: chunk */
323 : :
324 : 44 : lua_newtable(L); /* L: chunk table */
325 : :
326 : 44 : lua_pushstring(L, FFILIBNAME); /* L: chunk table str */
327 : 44 : lua_setfield(L, -2, "ffilibname"); /* L: chunk table */
328 : 44 : lua_pushstring(L, BITLIBNAME); /* L: chunk table str */
329 : 44 : lua_setfield(L, -2, "bitlibname"); /* L: chunk table */
330 : 44 : lua_pushinteger(L, TCB_INSYSCALL); /* L: chunk table int */
331 : 44 : lua_setfield(L, -2, "tcb_insyscall"); /* L: chunk table */
332 : 44 : lua_pushinteger(L, QUAL_TRACE); /* L: chunk table int */
333 : 44 : lua_setfield(L, -2, "qual_trace"); /* L: chunk table */
334 : 44 : lua_pushinteger(L, QUAL_ABBREV); /* L: chunk table int */
335 : 44 : lua_setfield(L, -2, "qual_abbrev"); /* L: chunk table */
336 : 44 : lua_pushinteger(L, QUAL_VERBOSE); /* L: chunk table int */
337 : 44 : lua_setfield(L, -2, "qual_verbose"); /* L: chunk table */
338 : 44 : lua_pushinteger(L, QUAL_RAW); /* L: chunk table int */
339 : 44 : lua_setfield(L, -2, "qual_raw"); /* L: chunk table */
340 : :
341 : 44 : assert_lua(lua_pcall(L, 1, 1, 0)); /* L: func */
342 : :
343 : 44 : check_lua(luaL_loadfile(L, scriptfile)); /* L: func chunk */
344 : 44 : }
345 : :
346 : : static void ATTRIBUTE_NORETURN
347 : 44 : run_luajit(void)
348 : : {
349 : : /* L: func chunk */
350 : 44 : check_lua(lua_pcall(L, 0, 0, 0)); /* L: func */
351 : 42 : check_lua(lua_pcall(L, 0, 0, 0)); /* L: - */
352 : 41 : terminate();
353 : : }
354 : :
355 : : #undef FFILIBNAME
356 : : #undef BITLIBNAME
357 : : #undef assert_lua
358 : : #undef L
|