R_API int r_run_start(RRunProfile *p) { #if __APPLE__ posix_spawnattr_t attr = {0}; pid_t pid = -1; #endif int ret; if (!p->_program && !p->_system) { printf ("No program or system rule defined\n"); return 1; } if (p->_stdin) { int f = open (p->_stdin, O_RDONLY); if (f < 0) return 1; close (0); dup2 (f, 0); } if (p->_stdout) { int f = open (p->_stdout, O_WRONLY); if (f < 0) return 1; close (1); dup2 (f, 1); } if (p->_stderr) { int f = open (p->_stderr, O_WRONLY); if (f < 0) return 1; close (2); dup2 (f, 2); } if (p->_aslr != -1) setASLR (p->_aslr); #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); #ifdef RLIMIT_NPROC if (p->_maxproc) set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); #endif if (p->_maxstack) set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } eprintf ("connected\n"); close (0); close (1); close (2); dup2 (fd->fd, 0); dup2 (fd->fd, 1); dup2 (fd->fd, 2); } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } child = r_socket_accept (fd); if (child) { eprintf ("connected\n"); close (0); close (1); close (2); dup2 (child->fd, 0); dup2 (child->fd, 1); dup2 (child->fd, 2); } } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) return 1; } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) return 1; } #if __UNIX__ if (p->_chroot) { if (chroot (p->_chroot)) { eprintf ("rarun2: cannot chroot\n"); return 1; } chdir("/"); } if (p->_setuid) { ret = setgroups(0, NULL); if (ret < 0) return 1; ret = setuid (atoi (p->_setuid)); if (ret < 0) return 1; } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) return 1; } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_input) { int f2[2]; pipe (f2); close (0); dup2 (f2[0], 0); parseinput (p->_input); write (f2[1], p->_input, strlen (p->_input)); } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 r_sys_setenv ("DYLD_PRELOAD", p->_preload); r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!fork ()) { sleep (p->_timeout); if (!kill (mypid, 0)) eprintf ("\nrarun2: Interrupted by timeout\n"); kill (mypid, SIGKILL); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } #if __APPLE__ posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i=3; i<10; i++) close (i); } // TODO: use posix_spawn if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ errno = 0; ret = nice(p->_nice); if (ret == -1) { if (errno != 0) { return 1; } } #else eprintf ("nice not supported for this platform\n"); #endif } exit (execv (p->_program, (char* const*)p->_args)); } return 0; }
R_API int r_run_config_env(RRunProfile *p) { int ret; if (!p->_program && !p->_system && !p->_runlib) { printf ("No program, system or runlib rule defined\n"); return 1; } // when IO is redirected to a process, handle them together if (handle_redirection (p->_stdio, true, true, false) != 0) { return 1; } if (handle_redirection (p->_stdin, true, false, false) != 0) { return 1; } if (handle_redirection (p->_stdout, false, true, false) != 0) { return 1; } if (handle_redirection (p->_stderr, false, false, true) != 0) { return 1; } if (p->_aslr != -1) { setASLR (p, p->_aslr); } #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) { set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); } #ifdef RLIMIT_NPROC if (p->_maxproc) { set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); } #endif if (p->_maxstack) { set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); } #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } if (p->_pty) { if (redirect_socket_to_pty (fd) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (fd); } } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); bool is_child = false; if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } while (true) { child = r_socket_accept (fd); if (child) { is_child = true; if (p->_dofork && !p->_dodebug) { #ifdef _MSC_VER int child_pid = r_sys_fork (); #else pid_t child_pid = r_sys_fork (); #endif if (child_pid == -1) { eprintf("rarun2: cannot fork\n"); r_socket_free (child); r_socket_free (fd); return 1; } else if (child_pid != 0){ // parent code is_child = false; } } if (is_child) { r_socket_close_fd (fd); eprintf ("connected\n"); if (p->_pty) { if (redirect_socket_to_pty (child) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (child); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (child); } break; } else { r_socket_close_fd (child); } } } if (!is_child) { r_socket_free (child); } r_socket_free (fd); } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } #if __UNIX__ if (p->_chroot) { if (chdir (p->_chroot) == -1) { eprintf ("Cannot chdir to chroot in %s\n", p->_chroot); return 1; } else { if (chroot (".") == -1) { eprintf ("Cannot chroot to %s\n", p->_chroot); return 1; } else { // Silenting pedantic meson flags... if (chdir ("/") == -1) { eprintf ("Cannot chdir to /\n"); return 1; } if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } } } } else if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } #else if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) { return 1; } } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) { return 1; } } #endif #if __UNIX__ if (p->_setuid) { ret = setgroups (0, NULL); if (ret < 0) { return 1; } ret = setuid (atoi (p->_setuid)); if (ret < 0) { return 1; } } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) { return 1; } } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) { return 1; } } if (p->_input) { char *inp; int f2[2]; if (pipe (f2) != -1) { close (0); dup2 (f2[0], 0); } else { eprintf ("[ERROR] rarun2: Cannot create pipe\n"); return 1; } inp = getstr (p->_input); if (inp) { size_t inpl = strlen (inp); if (write (f2[1], inp, inpl) != inpl) { eprintf ("[ERROR] rarun2: Cannot write to the pipe\n"); } close (f2[1]); free (inp); } else { eprintf ("Invalid input\n"); } } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 #ifndef __MAC_10_7 r_sys_setenv ("DYLD_PRELOAD", p->_preload); #endif r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!r_sys_fork ()) { int use_signal = p->_timeout_sig; if (use_signal < 1) { use_signal = SIGKILL; } sleep (p->_timeout); if (!kill (mypid, 0)) { eprintf ("\nrarun2: Interrupted by timeout\n"); } kill (mypid, use_signal); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } return 0; }