1 /* radare - LGPL - Copyright 2014-2020 - pancake */
2
3 /* this helper api is here because it depends on r_util and r_socket */
4 /* we should find a better place for it. r_io? */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <fcntl.h>
9 #include <r_socket.h>
10 #include <r_util.h>
11 #include <r_lib.h>
12 #include <r_cons.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15
16 #if __APPLE__ && LIBC_HAVE_FORK
17 #if !__POWERPC__
18 #include <spawn.h>
19 #endif
20 #include <sys/wait.h>
21 #include <mach/exception_types.h>
22 #include <mach/mach_init.h>
23 #include <mach/mach_port.h>
24 #include <mach/mach_traps.h>
25 #include <mach/task.h>
26 #include <mach/task_info.h>
27 #include <mach/thread_act.h>
28 #include <mach/thread_info.h>
29 #include <mach/vm_map.h>
30 #include <mach-o/loader.h>
31 #include <mach-o/nlist.h>
32 #endif
33
34 #if __UNIX__
35 #include <sys/ioctl.h>
36 #include <sys/resource.h>
37 #include <grp.h>
38 #include <errno.h>
39 #if defined(__sun)
40 #include <sys/filio.h>
41 #endif
42 #if __linux__ && !__ANDROID__
43 #include <sys/personality.h>
44 #include <pty.h>
45 #include <utmp.h>
46 #endif
47 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__)
48 #include <util.h>
49 #elif defined(__FreeBSD__) || defined(__DragonFly__)
50 #include <sys/sysctl.h>
51 #include <libutil.h>
52 #endif
53 #endif
54 #ifdef _MSC_VER
55 #include <direct.h> // to compile chdir in msvc windows
56 #include <process.h> // to compile execv in msvc windows
57 #define pid_t int
58 #endif
59
60 #if EMSCRIPTEN
61 #undef HAVE_PTY
62 #define HAVE_PTY 0
63 #else
64 #define HAVE_PTY __UNIX__ && !__ANDROID__ && LIBC_HAVE_FORK && !__sun
65 #endif
66
67
68 #if HAVE_PTY
69 static int (*dyn_openpty)(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) = NULL;
70 static int (*dyn_login_tty)(int fd) = NULL;
71 static id_t (*dyn_forkpty)(int *amaster, char *name, struct termios *termp, struct winsize *winp) = NULL;
dyn_init(void)72 static void dyn_init(void) {
73 if (!dyn_openpty) {
74 dyn_openpty = r_lib_dl_sym (NULL, "openpty");
75 }
76 if (!dyn_login_tty) {
77 dyn_openpty = r_lib_dl_sym (NULL, "login_tty");
78 }
79 if (!dyn_forkpty) {
80 dyn_openpty = r_lib_dl_sym (NULL, "forkpty");
81 }
82 }
83
84 #endif
85
r_run_new(const char * str)86 R_API RRunProfile *r_run_new(const char *str) {
87 RRunProfile *p = R_NEW0 (RRunProfile);
88 if (p) {
89 r_run_reset (p);
90 if (str) {
91 r_run_parsefile (p, str);
92 }
93 }
94 return p;
95 }
96
r_run_reset(RRunProfile * p)97 R_API void r_run_reset(RRunProfile *p) {
98 r_return_if_fail (p);
99 memset (p, 0, sizeof (RRunProfile));
100 p->_aslr = -1;
101 }
102
r_run_parse(RRunProfile * pf,const char * profile)103 R_API bool r_run_parse(RRunProfile *pf, const char *profile) {
104 r_return_val_if_fail (pf && profile, false);
105 char *p, *o, *str = strdup (profile);
106 if (!str) {
107 return false;
108 }
109 r_str_replace_char (str, '\r',0);
110 p = str;
111 while (p) {
112 if ((o = strchr (p, '\n'))) {
113 *o++ = 0;
114 }
115 r_run_parseline (pf, p);
116 p = o;
117 }
118 free (str);
119 return true;
120 }
121
r_run_free(RRunProfile * r)122 R_API void r_run_free(RRunProfile *r) {
123 if (r) {
124 free (r->_system);
125 free (r->_program);
126 free (r->_runlib);
127 free (r->_runlib_fcn);
128 free (r->_stdio);
129 free (r->_stdin);
130 free (r->_stdout);
131 free (r->_stderr);
132 free (r->_chgdir);
133 free (r->_chroot);
134 free (r->_libpath);
135 free (r->_preload);
136 free (r);
137 }
138 }
139
140 #if __UNIX__
set_limit(int n,int a,ut64 b)141 static void set_limit(int n, int a, ut64 b) {
142 if (n) {
143 struct rlimit cl = {b, b};
144 setrlimit (RLIMIT_CORE, &cl);
145 } else {
146 struct rlimit cl = {0, 0};
147 setrlimit (a, &cl);
148 }
149 }
150 #endif
151
getstr(const char * src)152 static char *getstr(const char *src) {
153 int len;
154 char *ret = NULL;
155
156 switch (*src) {
157 case '\'':
158 ret = strdup (src+1);
159 if (ret) {
160 len = strlen (ret);
161 if (len > 0) {
162 len--;
163 if (ret[len] == '\'') {
164 ret[len] = 0;
165 return ret;
166 }
167 eprintf ("Missing \"\n");
168 }
169 free (ret);
170 }
171 return NULL;
172 case '"':
173 ret = strdup (src + 1);
174 if (ret) {
175 len = strlen (ret);
176 if (len > 0) {
177 len--;
178 if (ret[len] == '"') {
179 ret[len] = 0;
180 r_str_unescape (ret);
181 return ret;
182 }
183 eprintf ("Missing \"\n");
184 }
185 free (ret);
186 }
187 return NULL;
188 case '@':
189 {
190 char *pat = strchr (src + 1, '@');
191 if (pat) {
192 size_t len;
193 long i, rep;
194 *pat++ = 0;
195 rep = strtol (src + 1, NULL, 10);
196 len = strlen (pat);
197 if (rep > 0) {
198 char *buf = malloc (rep);
199 if (buf) {
200 for (i = 0; i < rep; i++) {
201 buf[i] = pat[i % len];
202 }
203 }
204 return buf;
205 }
206 }
207 // slurp file
208 return r_file_slurp (src + 1, NULL);
209 }
210 case '`':
211 {
212 char *msg = strdup (src + 1);
213 int msg_len = strlen (msg);
214 if (msg_len > 0) {
215 msg [msg_len - 1] = 0;
216 char *ret = r_sys_cmd_str (msg, NULL, NULL);
217 r_str_trim_tail (ret);
218 free (msg);
219 return ret;
220 }
221 free (msg);
222 return strdup ("");
223 }
224 case '!':
225 {
226 char *a = r_sys_cmd_str (src + 1, NULL, NULL);
227 r_str_trim_tail (a);
228 return a;
229 }
230 case ':':
231 if (src[1] == '!') {
232 ret = r_sys_cmd_str (src + 1, NULL, NULL);
233 r_str_trim_tail (ret); // why no head :?
234 } else {
235 ret = strdup (src);
236 }
237 len = r_hex_str2bin (src + 1, (ut8*)ret);
238 if (len > 0) {
239 ret[len] = 0;
240 return ret;
241 }
242 eprintf ("Invalid hexpair string\n");
243 free (ret);
244 return NULL;
245 }
246 r_str_unescape ((ret = strdup (src)));
247 return ret;
248 }
249
parseBool(const char * e)250 static int parseBool(const char *e) {
251 return (strcmp (e, "yes")?
252 (strcmp (e, "on")?
253 (strcmp (e, "true")?
254 (strcmp (e, "1")?
255 0: 1): 1): 1): 1);
256 }
257
258 // TODO: move into r_util? r_run_... ? with the rest of funcs?
setASLR(RRunProfile * r,int enabled)259 static void setASLR(RRunProfile *r, int enabled) {
260 #if __linux__
261 r_sys_aslr (enabled);
262 #if HAVE_DECL_ADDR_NO_RANDOMIZE && !__ANDROID__
263 if (personality (ADDR_NO_RANDOMIZE) == -1) {
264 #endif
265 r_sys_aslr (0);
266 #if HAVE_DECL_ADDR_NO_RANDOMIZE && !__ANDROID__
267 }
268 #endif
269 #elif __APPLE__
270 // TOO OLD setenv ("DYLD_NO_PIE", "1", 1);
271 // disable this because its
272 const char *argv0 = r->_system ? r->_system
273 : r->_program ? r->_program
274 : r->_args[0] ? r->_args[0]
275 : "/path/to/exec";
276 eprintf ("To disable aslr patch mach0.hdr.flags with:\n"
277 "r2 -qwnc 'wx 000000 @ 0x18' %s\n", argv0);
278 // f MH_PIE=0x00200000; wB-MH_PIE @ 24\n");
279 // for osxver>=10.7
280 // "unset the MH_PIE bit in an already linked executable" with --no-pie flag of the script
281 // the right way is to disable the aslr bit in the spawn call
282 #elif __FreeBSD__ || __NetBSD__ || __DragonFly__
283 r_sys_aslr (enabled);
284 #else
285 // not supported for this platform
286 #endif
287 }
288
289 #if __APPLE__ && !__POWERPC__
290 #else
291 #if HAVE_PTY
restore_saved_fd(int saved,bool restore,int fd)292 static void restore_saved_fd(int saved, bool restore, int fd) {
293 if (saved == -1) {
294 return;
295 }
296 if (restore) {
297 dup2 (saved, fd);
298 }
299 close (saved);
300 }
301 #endif
302
handle_redirection_proc(const char * cmd,bool in,bool out,bool err)303 static int handle_redirection_proc(const char *cmd, bool in, bool out, bool err) {
304 #if HAVE_PTY
305 if (!dyn_forkpty) {
306 // No forkpty api found, maybe we should fallback to just fork without any pty allocated
307 return -1;
308 }
309 // use PTY to redirect I/O because pipes can be problematic in
310 // case of interactive programs.
311 int saved_stdin = dup (STDIN_FILENO);
312 if (saved_stdin == -1) {
313 return -1;
314 }
315 int saved_stdout = dup (STDOUT_FILENO);
316 if (saved_stdout == -1) {
317 close (saved_stdin);
318 return -1;
319 }
320
321 int fdm, pid = dyn_forkpty (&fdm, NULL, NULL, NULL);
322 if (pid == -1) {
323 close (saved_stdin);
324 close (saved_stdout);
325 return -1;
326 }
327 const char *tn = ttyname (fdm);
328 if (!tn) {
329 close (saved_stdin);
330 close (saved_stdout);
331 return -1;
332 }
333 int fds = open (tn, O_RDWR);
334 if (fds == -1) {
335 close (saved_stdin);
336 close (saved_stdout);
337 return -1;
338 }
339 if (pid == 0) {
340 close (fdm);
341 // child process
342 if (in) {
343 dup2 (fds, STDIN_FILENO);
344 }
345 if (out) {
346 dup2 (fds, STDOUT_FILENO);
347 }
348 // child - program to run
349
350 // necessary because otherwise you can read the same thing you
351 // wrote on fdm.
352 struct termios t;
353 tcgetattr (fds, &t);
354 cfmakeraw (&t);
355 tcsetattr (fds, TCSANOW, &t);
356
357 int code = r_sys_cmd (cmd);
358 restore_saved_fd (saved_stdin, in, STDIN_FILENO);
359 restore_saved_fd (saved_stdout, out, STDOUT_FILENO);
360 exit (code);
361 } else {
362 close (fds);
363 if (in) {
364 dup2 (fdm, STDIN_FILENO);
365 }
366 if (out) {
367 dup2 (fdm, STDOUT_FILENO);
368 }
369 // parent process
370 int status;
371 waitpid (pid, &status, 0);
372 }
373
374 // parent
375 close (saved_stdin);
376 close (saved_stdout);
377 return 0;
378 #else
379 #ifdef _MSC_VER
380 #pragma message ("TODO: handle_redirection_proc: Not implemented for this platform")
381 #else
382 #warning handle_redirection_proc : unimplemented for this platform
383 #endif
384 return -1;
385 #endif
386 }
387 #endif
388
handle_redirection(const char * cmd,bool in,bool out,bool err)389 static int handle_redirection(const char *cmd, bool in, bool out, bool err) {
390 #if __APPLE__ && !__POWERPC__
391 //XXX handle this in other layer since things changes a little bit
392 //this seems like a really good place to refactor stuff
393 return 0;
394 #else
395 if (!cmd || !*cmd) {
396 return 0;
397 }
398 if (cmd[0] == '"') {
399 #if __UNIX__
400 if (in) {
401 int pipes[2];
402 if (pipe (pipes) != -1) {
403 size_t cmdl = strlen (cmd)-2;
404 if (write (pipes[1], cmd + 1, cmdl) != cmdl) {
405 eprintf ("[ERROR] rarun2: Cannot write to the pipe\n");
406 close (0);
407 return 1;
408 }
409 if (write (pipes[1], "\n", 1) != 1) {
410 eprintf ("[ERROR] rarun2: Cannot write to the pipe\n");
411 close (0);
412 return 1;
413 }
414 close (0);
415 dup2 (pipes[0], 0);
416 } else {
417 eprintf ("[ERROR] rarun2: Cannot create pipe\n");
418 }
419 }
420 #else
421 #ifdef _MSC_VER
422 #pragma message ("string redirection handle not yet done")
423 #else
424 #warning quoted string redirection handle not yet done
425 #endif
426 #endif
427 } else if (cmd[0] == '!') {
428 // redirection to a process
429 return handle_redirection_proc (cmd + 1, in, out, err);
430 } else {
431 // redirection to a file
432 int f, flag = 0, mode = 0;
433 flag |= in ? O_RDONLY : 0;
434 flag |= out ? O_WRONLY | O_CREAT : 0;
435 flag |= err ? O_WRONLY | O_CREAT : 0;
436 #ifdef __WINDOWS__
437 mode = _S_IREAD | _S_IWRITE;
438 #else
439 mode = S_IRUSR | S_IWUSR;
440 #endif
441 f = open (cmd, flag, mode);
442 if (f < 0) {
443 eprintf ("[ERROR] rarun2: Cannot open: %s\n", cmd);
444 return 1;
445 }
446 #define DUP(x) { close(x); dup2(f,x); }
447 if (in) {
448 DUP(0);
449 }
450 if (out) {
451 DUP(1);
452 }
453 if (err) {
454 DUP(2);
455 }
456 close (f);
457 }
458 return 0;
459 #endif
460 }
461
r_run_parsefile(RRunProfile * p,const char * b)462 R_API bool r_run_parsefile(RRunProfile *p, const char *b) {
463 r_return_val_if_fail (p && b, false);
464 char *s = r_file_slurp (b, NULL);
465 if (s) {
466 bool ret = r_run_parse (p, s);
467 free (s);
468 return ret;
469 }
470 return 0;
471 }
472
r_run_parseline(RRunProfile * p,const char * b)473 R_API bool r_run_parseline(RRunProfile *p, const char *b) {
474 int must_free = false;
475 char *e = strchr (b, '=');
476 if (!e || *b == '#') {
477 return 0;
478 }
479 *e++ = 0;
480 if (*e == '$') {
481 must_free = true;
482 e = r_sys_getenv (e);
483 }
484 if (!e) {
485 return 0;
486 }
487 if (!strcmp (b, "program")) {
488 p->_args[0] = p->_program = strdup (e);
489 } else if (!strcmp (b, "daemon")) {
490 p->_daemon = true;
491 } else if (!strcmp (b, "system")) {
492 p->_system = strdup (e);
493 } else if (!strcmp (b, "runlib")) {
494 p->_runlib = strdup (e);
495 } else if (!strcmp (b, "runlib.fcn")) {
496 p->_runlib_fcn = strdup (e);
497 } else if (!strcmp (b, "aslr")) {
498 p->_aslr = parseBool (e);
499 } else if (!strcmp (b, "pid")) {
500 p->_pid = atoi (e);
501 } else if (!strcmp (b, "pidfile")) {
502 p->_pidfile = strdup (e);
503 } else if (!strcmp (b, "connect")) {
504 p->_connect = strdup (e);
505 } else if (!strcmp (b, "listen")) {
506 p->_listen = strdup (e);
507 } else if (!strcmp (b, "pty")) {
508 p->_pty = parseBool (e);
509 } else if (!strcmp (b, "stdio")) {
510 if (e[0] == '!') {
511 p->_stdio = strdup (e);
512 } else {
513 p->_stdout = strdup (e);
514 p->_stderr = strdup (e);
515 p->_stdin = strdup (e);
516 }
517 } else if (!strcmp (b, "stdout")) {
518 p->_stdout = strdup (e);
519 } else if (!strcmp (b, "stdin")) {
520 p->_stdin = strdup (e);
521 } else if (!strcmp (b, "stderr")) {
522 p->_stderr = strdup (e);
523 } else if (!strcmp (b, "input")) {
524 p->_input = strdup (e);
525 } else if (!strcmp (b, "chdir")) {
526 p->_chgdir = strdup (e);
527 } else if (!strcmp (b, "core")) {
528 p->_docore = parseBool (e);
529 } else if (!strcmp (b, "fork")) {
530 p->_dofork = parseBool (e);
531 } else if (!strcmp (b, "sleep")) {
532 p->_r2sleep = atoi (e);
533 } else if (!strcmp (b, "maxstack")) {
534 p->_maxstack = atoi (e);
535 } else if (!strcmp (b, "maxproc")) {
536 p->_maxproc = atoi (e);
537 } else if (!strcmp (b, "maxfd")) {
538 p->_maxfd = atoi (e);
539 } else if (!strcmp (b, "bits")) {
540 p->_bits = atoi (e);
541 } else if (!strcmp (b, "chroot")) {
542 p->_chroot = strdup (e);
543 } else if (!strcmp (b, "libpath")) {
544 p->_libpath = strdup (e);
545 } else if (!strcmp (b, "preload")) {
546 p->_preload = strdup (e);
547 } else if (!strcmp (b, "r2preload")) {
548 p->_r2preload = parseBool (e);
549 } else if (!strcmp (b, "r2preweb")) {
550 r_sys_setenv ("RARUN2_WEB", "yes");
551 } else if (!strcmp (b, "setuid")) {
552 p->_setuid = strdup (e);
553 } else if (!strcmp (b, "seteuid")) {
554 p->_seteuid = strdup (e);
555 } else if (!strcmp (b, "setgid")) {
556 p->_setgid = strdup (e);
557 } else if (!strcmp (b, "setegid")) {
558 p->_setegid = strdup (e);
559 } else if (!strcmp (b, "nice")) {
560 p->_nice = atoi (e);
561 } else if (!strcmp (b, "timeout")) {
562 p->_timeout = atoi (e);
563 } else if (!strcmp (b, "timeoutsig")) {
564 p->_timeout_sig = r_signal_from_string (e);
565 } else if (!memcmp (b, "arg", 3)) {
566 int n = atoi (b + 3);
567 if (n >= 0 && n < R_RUN_PROFILE_NARGS) {
568 p->_args[n] = getstr (e);
569 p->_argc++;
570 } else {
571 eprintf ("Out of bounds args index: %d\n", n);
572 }
573 } else if (!strcmp (b, "envfile")) {
574 char *p, buf[1024];
575 size_t len;
576 FILE *fd = r_sandbox_fopen (e, "r");
577 if (!fd) {
578 eprintf ("Cannot open '%s'\n", e);
579 if (must_free == true) {
580 free (e);
581 }
582 return false;
583 }
584 for (;;) {
585 if (!fgets (buf, sizeof (buf), fd)) {
586 break;
587 }
588 if (feof (fd)) {
589 break;
590 }
591 p = strchr (buf, '=');
592 if (p) {
593 *p++ = 0;
594 len = strlen (p);
595 if (len > 0 && p[len - 1] == '\n') {
596 p[len - 1] = 0;
597 }
598 if (len > 1 && p[len - 2] == '\r') {
599 p[len - 2] = 0;
600 }
601 r_sys_setenv (buf, p);
602 }
603 }
604 fclose (fd);
605 } else if (!strcmp (b, "unsetenv")) {
606 r_sys_setenv (e, NULL);
607 } else if (!strcmp (b, "setenv")) {
608 char *V, *v = strchr (e, '=');
609 if (v) {
610 *v++ = 0;
611 V = getstr (v);
612 r_sys_setenv (e, V);
613 free (V);
614 }
615 } else if (!strcmp(b, "clearenv")) {
616 r_sys_clearenv ();
617 }
618 if (must_free == true) {
619 free (e);
620 }
621 return true;
622 }
623
r_run_help(void)624 R_API const char *r_run_help(void) {
625 return
626 "program=/bin/ls\n"
627 "arg1=/bin\n"
628 "# arg2=hello\n"
629 "# arg3=\"hello\\nworld\"\n"
630 "# arg4=:048490184058104849\n"
631 "# arg5=:!ragg2 -p n50 -d 10:0x8048123\n"
632 "# arg6=@arg.txt\n"
633 "# arg7=@300@ABCD # 300 chars filled with ABCD pattern\n"
634 "# system=r2 -\n"
635 "# daemon=false\n"
636 "# aslr=no\n"
637 "setenv=FOO=BAR\n"
638 "# unsetenv=FOO\n"
639 "# clearenv=true\n"
640 "# envfile=environ.txt\n"
641 "timeout=3\n"
642 "# timeoutsig=SIGTERM # or 15\n"
643 "# connect=localhost:8080\n"
644 "# listen=8080\n"
645 "# pty=false\n"
646 "# fork=true\n"
647 "# bits=32\n"
648 "# pid=0\n"
649 "# pidfile=/tmp/foo.pid\n"
650 "# #sleep=0\n"
651 "# #maxfd=0\n"
652 "# #execve=false\n"
653 "# #maxproc=0\n"
654 "# #maxstack=0\n"
655 "# #core=false\n"
656 "# #stdio=blah.txt\n"
657 "# #stderr=foo.txt\n"
658 "# stdout=foo.txt\n"
659 "# stdin=input.txt # or !program to redirect input from another program\n"
660 "# input=input.txt\n"
661 "# chdir=/\n"
662 "# chroot=/mnt/chroot\n"
663 "# libpath=$PWD:/tmp/lib\n"
664 "# r2preload=yes\n"
665 "# preload=/lib/libfoo.so\n"
666 "# setuid=2000\n"
667 "# seteuid=2000\n"
668 "# setgid=2001\n"
669 "# setegid=2001\n"
670 "# nice=5\n";
671 }
672
673 #if HAVE_PTY
fd_forward(int in_fd,int out_fd,char ** buff)674 static int fd_forward(int in_fd, int out_fd, char **buff) {
675 int size = 0;
676
677 if (ioctl (in_fd, FIONREAD, &size) == -1) {
678 perror ("ioctl");
679 return -1;
680 }
681 if (!size) { // child process exited or socket is closed
682 return -1;
683 }
684
685 char *new_buff = realloc (*buff, size);
686 if (!new_buff) {
687 eprintf ("Failed to allocate buffer for redirection");
688 return -1;
689 }
690 *buff = new_buff;
691 if (read (in_fd, *buff, size) != size) {
692 perror ("read");
693 return -1;
694 }
695 if (write (out_fd, *buff, size) != size) {
696 perror ("write");
697 return -1;
698 }
699
700 return 0;
701 }
702 #endif
703
redirect_socket_to_stdio(RSocket * sock)704 static int redirect_socket_to_stdio(RSocket *sock) {
705 close (0);
706 close (1);
707 close (2);
708
709 dup2 (sock->fd, 0);
710 dup2 (sock->fd, 1);
711 dup2 (sock->fd, 2);
712
713 return 0;
714 }
715
716 #if __WINDOWS__
exit_process(RThread * th)717 static RThreadFunctionRet exit_process(RThread *th) {
718 // eprintf ("\nrarun2: Interrupted by timeout\n");
719 exit (0);
720 }
721 #endif
722
redirect_socket_to_pty(RSocket * sock)723 static int redirect_socket_to_pty(RSocket *sock) {
724 #if HAVE_PTY
725 // directly duplicating the fds using dup2() creates problems
726 // in case of interactive applications
727 int fdm = -1, fds = -1;
728
729 if (dyn_openpty && dyn_openpty (&fdm, &fds, NULL, NULL, NULL) == -1) {
730 perror ("opening pty");
731 return -1;
732 }
733
734 pid_t child_pid = r_sys_fork ();
735
736 if (child_pid == -1) {
737 eprintf ("cannot fork\n");
738 if (fdm != -1) {
739 close (fdm);
740 }
741 if (fds != -1) {
742 close (fds);
743 }
744 return -1;
745 }
746
747 if (child_pid == 0) {
748 // child process
749 close (fds);
750
751 char *buff = NULL;
752 int sockfd = sock->fd;
753 int max_fd = fdm > sockfd ? fdm : sockfd;
754
755 while (true) {
756 fd_set readfds;
757 FD_ZERO (&readfds);
758 FD_SET (fdm, &readfds);
759 FD_SET (sockfd, &readfds);
760
761 if (select (max_fd + 1, &readfds, NULL, NULL, NULL) == -1) {
762 perror ("select error");
763 break;
764 }
765
766 if (FD_ISSET (fdm, &readfds)) {
767 if (fd_forward (fdm, sockfd, &buff) != 0) {
768 break;
769 }
770 }
771
772 if (FD_ISSET (sockfd, &readfds)) {
773 if (fd_forward (sockfd, fdm, &buff) != 0) {
774 break;
775 }
776 }
777 }
778
779 free (buff);
780 if (fdm != -1) {
781 close (fdm);
782 fdm = -1;
783 }
784 r_socket_free (sock);
785 exit (0);
786 }
787
788 // parent
789 r_socket_close_fd (sock);
790 if (dyn_login_tty) {
791 dyn_login_tty (fds);
792 }
793 if (fdm != -1) {
794 close (fdm);
795 }
796
797 // disable the echo on slave stdin
798 struct termios t;
799 tcgetattr (0, &t);
800 cfmakeraw (&t);
801 tcsetattr (0, TCSANOW, &t);
802
803 return 0;
804 #else
805 // Fallback to socket to I/O redirection
806 return redirect_socket_to_stdio (sock);
807 #endif
808 }
809
r_run_config_env(RRunProfile * p)810 R_API int r_run_config_env(RRunProfile *p) {
811 int ret;
812
813 #if HAVE_PTY
814 dyn_init ();
815 #endif
816
817 if (!p->_program && !p->_system && !p->_runlib) {
818 eprintf ("No program, system or runlib rule defined\n");
819 return 1;
820 }
821 // when IO is redirected to a process, handle them together
822 if (handle_redirection (p->_stdio, true, true, false) != 0) {
823 return 1;
824 }
825 if (handle_redirection (p->_stdin, true, false, false) != 0) {
826 return 1;
827 }
828 if (handle_redirection (p->_stdout, false, true, false) != 0) {
829 return 1;
830 }
831 if (handle_redirection (p->_stderr, false, false, true) != 0) {
832 return 1;
833 }
834 if (p->_aslr != -1) {
835 setASLR (p, p->_aslr);
836 }
837 #if __UNIX__
838 set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY);
839 if (p->_maxfd) {
840 set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd);
841 }
842 #ifdef RLIMIT_NPROC
843 if (p->_maxproc) {
844 set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc);
845 }
846 #endif
847 if (p->_maxstack) {
848 set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack);
849 }
850 #else
851 if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack)
852 eprintf ("Warning: setrlimits not supported for this platform\n");
853 #endif
854 if (p->_connect) {
855 char *q = strchr (p->_connect, ':');
856 if (q) {
857 RSocket *fd = r_socket_new (0);
858 *q = 0;
859 if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) {
860 eprintf ("Cannot connect\n");
861 return 1;
862 }
863 if (p->_pty) {
864 if (redirect_socket_to_pty (fd) != 0) {
865 eprintf ("socket redirection failed\n");
866 r_socket_free (fd);
867 return 1;
868 }
869 } else {
870 redirect_socket_to_stdio (fd);
871 }
872 } else {
873 eprintf ("Invalid format for connect. missing ':'\n");
874 return 1;
875 }
876 }
877 if (p->_listen) {
878 RSocket *child, *fd = r_socket_new (0);
879 bool is_child = false;
880 if (!r_socket_listen (fd, p->_listen, NULL)) {
881 eprintf ("rarun2: cannot listen\n");
882 r_socket_free (fd);
883 return 1;
884 }
885 while (true) {
886 child = r_socket_accept (fd);
887 if (child) {
888 is_child = true;
889
890 if (p->_dofork && !p->_dodebug) {
891 pid_t child_pid = r_sys_fork ();
892 if (child_pid == -1) {
893 eprintf("rarun2: cannot fork\n");
894 r_socket_free (child);
895 r_socket_free (fd);
896 return 1;
897 } else if (child_pid != 0){
898 // parent code
899 is_child = false;
900 }
901 }
902
903 if (is_child) {
904 r_socket_close_fd (fd);
905 eprintf ("connected\n");
906 if (p->_pty) {
907 if (redirect_socket_to_pty (child) != 0) {
908 eprintf ("socket redirection failed\n");
909 r_socket_free (child);
910 r_socket_free (fd);
911 return 1;
912 }
913 } else {
914 redirect_socket_to_stdio (child);
915 }
916 break;
917 } else {
918 r_socket_close_fd (child);
919 }
920 }
921 }
922 if (!is_child) {
923 r_socket_free (child);
924 }
925 r_socket_free (fd);
926 }
927 if (p->_r2sleep != 0) {
928 r_sys_sleep (p->_r2sleep);
929 }
930 #if __UNIX__
931 if (p->_chroot) {
932 if (chdir (p->_chroot) == -1) {
933 eprintf ("Cannot chdir to chroot in %s\n", p->_chroot);
934 return 1;
935 } else {
936 if (chroot (".") == -1) {
937 eprintf ("Cannot chroot to %s\n", p->_chroot);
938 return 1;
939 } else {
940 // Silenting pedantic meson flags...
941 if (chdir ("/") == -1) {
942 eprintf ("Cannot chdir to /\n");
943 return 1;
944 }
945 if (p->_chgdir) {
946 if (chdir (p->_chgdir) == -1) {
947 eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir);
948 return 1;
949 }
950 }
951 }
952 }
953 } else if (p->_chgdir) {
954 if (chdir (p->_chgdir) == -1) {
955 eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir);
956 return 1;
957 }
958 }
959 #else
960 if (p->_chgdir) {
961 ret = chdir (p->_chgdir);
962 if (ret < 0) {
963 return 1;
964 }
965 }
966 if (p->_chroot) {
967 ret = chdir (p->_chroot);
968 if (ret < 0) {
969 return 1;
970 }
971 }
972 #endif
973 #if __UNIX__
974 if (p->_setuid) {
975 ret = setgroups (0, NULL);
976 if (ret < 0) {
977 return 1;
978 }
979 ret = setuid (atoi (p->_setuid));
980 if (ret < 0) {
981 return 1;
982 }
983 }
984 if (p->_seteuid) {
985 ret = seteuid (atoi (p->_seteuid));
986 if (ret < 0) {
987 return 1;
988 }
989 }
990 if (p->_setgid) {
991 ret = setgid (atoi (p->_setgid));
992 if (ret < 0) {
993 return 1;
994 }
995 }
996 if (p->_input) {
997 char *inp;
998 int f2[2];
999 if (pipe (f2) != -1) {
1000 close (0);
1001 dup2 (f2[0], 0);
1002 } else {
1003 eprintf ("[ERROR] rarun2: Cannot create pipe\n");
1004 return 1;
1005 }
1006 inp = getstr (p->_input);
1007 if (inp) {
1008 size_t inpl = strlen (inp);
1009 if (write (f2[1], inp, inpl) != inpl) {
1010 eprintf ("[ERROR] rarun2: Cannot write to the pipe\n");
1011 }
1012 close (f2[1]);
1013 free (inp);
1014 } else {
1015 eprintf ("Invalid input\n");
1016 }
1017 }
1018 #endif
1019 if (p->_r2preload) {
1020 if (p->_preload) {
1021 eprintf ("WARNING: Only one library can be opened at a time\n");
1022 }
1023 #ifdef __WINDOWS__
1024 p->_preload = r_str_r2_prefix (R_JOIN_2_PATHS (R2_LIBDIR, "libr2."R_LIB_EXT));
1025 #else
1026 p->_preload = strdup (R2_LIBDIR"/libr2."R_LIB_EXT);
1027 #endif
1028 }
1029 if (p->_libpath) {
1030 #if __WINDOWS__
1031 eprintf ("rarun2: libpath unsupported for this platform\n");
1032 #elif __HAIKU__
1033 r_sys_setenv ("LIBRARY_PATH", p->_libpath);
1034 #elif __APPLE__
1035 r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath);
1036 #else
1037 r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath);
1038 #endif
1039 }
1040 if (p->_preload) {
1041 #if __APPLE__
1042 // 10.6
1043 #ifndef __MAC_10_7
1044 r_sys_setenv ("DYLD_PRELOAD", p->_preload);
1045 #endif
1046 r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload);
1047 // 10.8
1048 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1");
1049 #else
1050 r_sys_setenv ("LD_PRELOAD", p->_preload);
1051 #endif
1052 }
1053 if (p->_timeout) {
1054 #if __UNIX__
1055 int mypid = getpid ();
1056 if (!r_sys_fork ()) {
1057 int use_signal = p->_timeout_sig;
1058 if (use_signal < 1) {
1059 use_signal = SIGKILL;
1060 }
1061 sleep (p->_timeout);
1062 if (!kill (mypid, 0)) {
1063 // eprintf ("\nrarun2: Interrupted by timeout\n");
1064 }
1065 kill (mypid, use_signal);
1066 exit (0);
1067 }
1068 #else
1069 if (p->_timeout_sig < 1 || p->_timeout_sig == 9) {
1070 r_th_new (exit_process, NULL, p->_timeout);
1071 } else {
1072 eprintf ("timeout with signal not supported for this platform\n");
1073 }
1074 #endif
1075 }
1076 return 0;
1077 }
1078
1079 // NOTE: return value is like in unix return code (0 = ok, 1 = not ok)
r_run_start(RRunProfile * p)1080 R_API int r_run_start(RRunProfile *p) {
1081 #if LIBC_HAVE_FORK
1082 if (p->_execve) {
1083 exit (execv (p->_program, (char* const*)p->_args));
1084 }
1085 #endif
1086 #if __APPLE__ && !__POWERPC__ && LIBC_HAVE_FORK
1087 posix_spawnattr_t attr = {0};
1088 pid_t pid = -1;
1089 int ret;
1090 posix_spawnattr_init (&attr);
1091 if (p->_args[0]) {
1092 char **envp = r_sys_get_environ();
1093 ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED;
1094 spflags |= POSIX_SPAWN_SETEXEC;
1095 if (p->_aslr == 0) {
1096 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
1097 spflags |= _POSIX_SPAWN_DISABLE_ASLR;
1098 }
1099 (void)posix_spawnattr_setflags (&attr, spflags);
1100 if (p->_bits) {
1101 size_t copied = 1;
1102 cpu_type_t cpu;
1103 #if __i386__ || __x86_64__
1104 cpu = CPU_TYPE_I386;
1105 if (p->_bits == 64) {
1106 cpu |= CPU_ARCH_ABI64;
1107 }
1108 #else
1109 cpu = CPU_TYPE_ANY;
1110 #endif
1111 posix_spawnattr_setbinpref_np (
1112 &attr, 1, &cpu, &copied);
1113 }
1114 ret = posix_spawnp (&pid, p->_args[0],
1115 NULL, &attr, p->_args, envp);
1116 switch (ret) {
1117 case 0:
1118 break;
1119 case 22:
1120 eprintf ("posix_spawnp: Invalid argument\n");
1121 break;
1122 case 86:
1123 eprintf ("posix_spawnp: Unsupported architecture\n");
1124 break;
1125 default:
1126 eprintf ("posix_spawnp: unknown error %d\n", ret);
1127 perror ("posix_spawnp");
1128 break;
1129 }
1130 exit (ret);
1131 }
1132 #endif
1133 if (p->_system) {
1134 if (p->_pid) {
1135 eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n");
1136 }
1137 if (p->_daemon) {
1138 #if __WINDOWS__
1139 // eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n");
1140 #else
1141 pid_t child = r_sys_fork ();
1142 if (child == -1) {
1143 perror ("fork");
1144 exit (1);
1145 }
1146 if (child) {
1147 if (p->_pidfile) {
1148 char pidstr[32];
1149 snprintf (pidstr, sizeof (pidstr), "%d\n", child);
1150 r_file_dump (p->_pidfile,
1151 (const ut8*)pidstr,
1152 strlen (pidstr), 0);
1153 }
1154 exit (0);
1155 }
1156 setsid ();
1157 if (p->_timeout) {
1158 #if __UNIX__
1159 int mypid = getpid ();
1160 if (!r_sys_fork ()) {
1161 int use_signal = p->_timeout_sig;
1162 if (use_signal < 1) {
1163 use_signal = SIGKILL;
1164 }
1165 sleep (p->_timeout);
1166 if (!kill (mypid, 0)) {
1167 // eprintf ("\nrarun2: Interrupted by timeout\n");
1168 }
1169 kill (mypid, use_signal);
1170 exit (0);
1171 }
1172 #else
1173 eprintf ("timeout not supported for this platform\n");
1174 #endif
1175 }
1176 #endif
1177 #if __UNIX__
1178 close(0);
1179 close(1);
1180 exit (execl ("/bin/sh","/bin/sh", "-c", p->_system, NULL));
1181 #else
1182 exit (r_sys_cmd (p->_system));
1183 #endif
1184 } else {
1185 if (p->_pidfile) {
1186 eprintf ("Warning: pidfile doesnt work with 'system'.\n");
1187 }
1188 exit (r_sys_cmd (p->_system));
1189 }
1190 }
1191 if (p->_program) {
1192 if (!r_file_exists (p->_program)) {
1193 char *progpath = r_file_path (p->_program);
1194 if (progpath && *progpath) {
1195 free (p->_program);
1196 p->_program = progpath;
1197 } else {
1198 free (progpath);
1199 eprintf ("rarun2: %s: file not found\n", p->_program);
1200 return 1;
1201 }
1202 }
1203 #if __UNIX__
1204 // XXX HACK close all non-tty fds
1205 { int i;
1206 for (i = 3; i < 1024; i++) {
1207 close (i);
1208 }
1209 }
1210 // TODO: use posix_spawn
1211 if (p->_setgid) {
1212 int ret = setgid (atoi (p->_setgid));
1213 if (ret < 0) {
1214 return 1;
1215 }
1216 }
1217 if (p->_pid) {
1218 eprintf ("PID: %d\n", getpid ());
1219 }
1220 if (p->_pidfile) {
1221 char pidstr[32];
1222 snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ());
1223 r_file_dump (p->_pidfile,
1224 (const ut8*)pidstr,
1225 strlen (pidstr), 0);
1226 }
1227 #endif
1228
1229 if (p->_nice) {
1230 #if __UNIX__ && !defined(__HAIKU__)
1231 if (nice (p->_nice) == -1) {
1232 return 1;
1233 }
1234 #else
1235 eprintf ("nice not supported for this platform\n");
1236 #endif
1237 }
1238 if (p->_daemon) {
1239 #if __WINDOWS__
1240 eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n");
1241 #else
1242 pid_t child = r_sys_fork ();
1243 if (child == -1) {
1244 perror ("fork");
1245 exit (1);
1246 }
1247 if (child) {
1248 if (p->_pidfile) {
1249 char pidstr[32];
1250 snprintf (pidstr, sizeof (pidstr), "%d\n", child);
1251 r_file_dump (p->_pidfile,
1252 (const ut8*)pidstr,
1253 strlen (pidstr), 0);
1254 exit (0);
1255 }
1256 }
1257 setsid ();
1258 #if !LIBC_HAVE_FORK
1259 exit (execv (p->_program, (char* const*)p->_args));
1260 #endif
1261 #endif
1262 }
1263 // TODO: must be HAVE_EXECVE
1264 #if LIBC_HAVE_FORK
1265 exit (execv (p->_program, (char* const*)p->_args));
1266 #endif
1267 }
1268 if (p->_runlib) {
1269 if (!p->_runlib_fcn) {
1270 eprintf ("No function specified. Please set runlib.fcn\n");
1271 return 1;
1272 }
1273 void *addr = r_lib_dl_open (p->_runlib);
1274 if (!addr) {
1275 eprintf ("Could not load the library '%s'\n", p->_runlib);
1276 return 1;
1277 }
1278 void (*fcn)(void) = r_lib_dl_sym (addr, p->_runlib_fcn);
1279 if (!fcn) {
1280 eprintf ("Could not find the function '%s'\n", p->_runlib_fcn);
1281 return 1;
1282 }
1283 switch (p->_argc) {
1284 case 0:
1285 fcn ();
1286 break;
1287 case 1:
1288 r_run_call1 (fcn, p->_args[1]);
1289 break;
1290 case 2:
1291 r_run_call2 (fcn, p->_args[1], p->_args[2]);
1292 break;
1293 case 3:
1294 r_run_call3 (fcn, p->_args[1], p->_args[2], p->_args[3]);
1295 break;
1296 case 4:
1297 r_run_call4 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4]);
1298 break;
1299 case 5:
1300 r_run_call5 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1301 p->_args[5]);
1302 break;
1303 case 6:
1304 r_run_call6 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1305 p->_args[5], p->_args[6]);
1306 break;
1307 case 7:
1308 r_run_call7 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1309 p->_args[5], p->_args[6], p->_args[7]);
1310 break;
1311 case 8:
1312 r_run_call8 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1313 p->_args[5], p->_args[6], p->_args[7], p->_args[8]);
1314 break;
1315 case 9:
1316 r_run_call9 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1317 p->_args[5], p->_args[6], p->_args[7], p->_args[8], p->_args[9]);
1318 break;
1319 case 10:
1320 r_run_call10 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4],
1321 p->_args[5], p->_args[6], p->_args[7], p->_args[8], p->_args[9], p->_args[10]);
1322 break;
1323 default:
1324 eprintf ("Too many arguments.\n");
1325 return 1;
1326 }
1327 r_lib_dl_close (addr);
1328 }
1329 return 0;
1330 }
1331
r_run_get_environ_profile(char ** env)1332 R_API char *r_run_get_environ_profile(char **env) {
1333 if (!env) {
1334 return NULL;
1335 }
1336 RStrBuf *sb = r_strbuf_new (NULL);
1337 while (*env) {
1338 char *k = strdup (*env);
1339 char *v = strchr (k, '=');
1340 if (v) {
1341 *v++ = 0;
1342 v = r_str_escape_latin1 (v, false, true, true);
1343 if (v) {
1344 r_strbuf_appendf (sb, "setenv=%s=\"%s\"\n", k, v);
1345 free (v);
1346 }
1347 }
1348 free (k);
1349 env++;
1350 }
1351 return r_strbuf_drain (sb);
1352 }
1353