Exemplo n.º 1
0
R_API int r_socket_spawn (RSocket *s, const char *cmd, unsigned int timeout) {
	// XXX TODO: dont use sockets, we can achieve the same with pipes
	const int port = 2000 + r_num_rand (2000);
	int childPid = r_sys_fork();
	if (childPid == 0) {
		char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true);
		r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port);
		free (a);
#if 0
		// TODO: use the api
		char *profile = r_str_newf (
				"system=%s\n"
				"listen=%d\n", cmd, port);
		RRunProfile *rp = r_run_new (profile);
		r_run_start (rp);
		r_run_free (rp);
		free (profile);
#endif
		eprintf ("r_socket_spawn: %s is dead\n", cmd);
		exit (0);
	}
	r_sys_sleep (1);
	r_sys_usleep (timeout);
	char aport[32];
	sprintf (aport, "%d", port);
	// redirect stdin/stdout/stderr
	return r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000);
}
Exemplo n.º 2
0
R_API struct r_socket_proc_t *r_socket_proc_open(char* const argv[]) {
#if __UNIX__ && LIBC_HAVE_FORK
	RSocketProc *sp = R_NEW (RSocketProc);
#ifdef O_CLOEXEC
	const int flags = O_CLOEXEC; //O_NONBLOCK|O_CLOEXEC;
#else
	const int flags = 0; //O_NONBLOCK|O_CLOEXEC;
#endif

	if (!sp) {
		return NULL;
	}

	if (pipe (sp->fd0)==-1) {
		perror ("pipe");
		goto error;
	}
	if (fcntl (sp->fd0[0], flags) < 0) {
		goto error;
	}
	if (fcntl (sp->fd0[1], flags) < 0) {
		goto error;
	}

	if (pipe (sp->fd1)==-1) {
		perror ("pipe");
		goto error;
	}
	if (fcntl (sp->fd1[0], flags) < 0) {
		goto error;
	}
	if (fcntl (sp->fd1[1], flags) < 0) {
		goto error;
	}

	sp->pid = r_sys_fork ();
	switch (sp->pid) {
	case 0:
		close (0);
		dup2 (sp->fd0[0], 0);
		close (1);
		dup2 (sp->fd1[1], 1);
		execv (argv[0], argv);
		exit (1);
		break;
	case -1:
		perror ("fork");
		r_socket_proc_close (sp);
		goto error;
		//r_socket_block_time (sp, false, 0);
	}
	return sp;
error:
	free (sp);
	return NULL;
#else
	return NULL;
#endif
}
Exemplo n.º 3
0
Arquivo: sys.c Projeto: agatti/radare2
R_API int r_sys_run(const ut8 *buf, int len) {
	const int sz = 4096;
	int pdelta, ret, (*cb)();
#if USE_FORK
	int st, pid;
#endif
// TODO: define R_SYS_ALIGN_FORWARD in r_util.h
	ut8 *ptr, *p = malloc ((sz + len) << 1);
	ptr = p;
	pdelta = ((size_t)(p)) & (4096 - 1);
	if (pdelta) {
		ptr += (4096 - pdelta);
	}
	if (!ptr || !buf) {
		eprintf ("r_sys_run: Cannot run empty buffer\n");
		free (p);
		return false;
	}
	memcpy (ptr, buf, len);
	r_mem_protect (ptr, sz, "rx");
	//r_mem_protect (ptr, sz, "rwx"); // try, ignore if fail
	cb = (int (*)())ptr;
#if USE_FORK
#if __UNIX__ || __CYGWIN__ && !defined(MINGW32)
	pid = r_sys_fork ();
#else
	pid = -1;
#endif
	if (pid < 0) {
		return cb ();
	}
	if (!pid) {
		ret = cb ();
		exit (ret);
		return ret;
	}
	st = 0;
	waitpid (pid, &st, 0);
	if (WIFSIGNALED (st)) {
		int num = WTERMSIG(st);
		eprintf ("Got signal %d\n", num);
		ret = num;
	} else {
		ret = WEXITSTATUS (st);
	}
#else
	ret = (*cb) ();
#endif
	free (p);
	return ret;
}
Exemplo n.º 4
0
R_API int r_sys_cmdbg (const char *str) {
#if __UNIX__
	int ret, pid = r_sys_fork ();
	if (pid == -1) return -1;
	if (pid) return pid;
	ret = r_sandbox_system (str, 0);
	eprintf ("{exit: %d, pid: %d, cmd: \"%s\"}", ret, pid, str);
	exit (0);
	return -1;
#else
#warning r_sys_cmdbg is not implemented for this platform
	return -1;
#endif
}
Exemplo n.º 5
0
R_API bool r_socket_spawn(RSocket *s, const char *cmd, unsigned int timeout) {
	// XXX TODO: dont use sockets, we can achieve the same with pipes
	const int port = 2000 + r_num_rand (2000);
	int childPid = r_sys_fork ();
	if (childPid == 0) {
		char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true);
		int res = r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port);
		free (a);
#if 0
		// TODO: use the api
		char *profile = r_str_newf (
				"system=%s\n"
				"listen=%d\n", cmd, port);
		RRunProfile *rp = r_run_new (profile);
		r_run_start (rp);
		r_run_free (rp);
		free (profile);
#endif
		if (res != 0) {
			eprintf ("r_socket_spawn: rarun2 failed\n");
			exit (1);
		}
		eprintf ("r_socket_spawn: %s is dead\n", cmd);
		exit (0);
	}
	r_sys_sleep (1);
	r_sys_usleep (timeout);

	char aport[32];
	sprintf (aport, "%d", port);
	// redirect stdin/stdout/stderr
	bool sock = r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000);
	if (!sock) {
		return false;
	}
#if __UNIX__
	r_sys_sleep (4);
	r_sys_usleep (timeout);

	int status = 0;
	int ret = waitpid (childPid, &status, WNOHANG);
	if (ret != 0) {
		r_socket_close (s);
		return false;
	}
#endif
	return true;
}
Exemplo n.º 6
0
Arquivo: sys.c Projeto: agatti/radare2
R_API int r_sys_cmdbg (const char *str) {
#if __UNIX__ || __CYGWIN && !defined(MINGW32)
	int ret, pid = r_sys_fork ();
	if (pid == -1) {
		return -1;
	}
	if (pid) {
		return pid;
	}
	ret = r_sandbox_system (str, 0);
	eprintf ("{exit: %d, pid: %d, cmd: \"%s\"}", ret, pid, str);
	exit (0);
	return -1;
#else
#ifdef _MSC_VER
#pragma message ("r_sys_cmdbg is not implemented for this platform")
#else
#warning r_sys_cmdbg is not implemented for this platform
#endif
	return -1;
#endif
}
Exemplo n.º 7
0
// __UNIX__ (not windows)
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	char **argv;
	int ret, status, pid = r_sys_fork ();
	switch (pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
#if __APPLE__
		signal (SIGTRAP, SIG_IGN); //NEED BY STEP 
#endif
#if __APPLE__ || __BSD__
/* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
		signal (SIGABRT, inferior_abort_handler);
		if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
#else
		if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
#endif
			r_sys_perror ("ptrace-traceme");
			exit (MAGIC_EXIT);
		}
		if (io->runprofile && *(io->runprofile)) {
			char *expr = NULL;
			int i;
			RRunProfile *rp = r_run_new (NULL);
			argv = r_str_argv (cmd, NULL);
			for (i=0; argv[i]; i++) {
				rp->_args[i] = argv[i];
			}
			rp->_args[i] = NULL;
			rp->_program = argv[0];
			if (io->runprofile && *io->runprofile) {
				if (!r_run_parsefile (rp, io->runprofile)) {
					eprintf ("Can't find profile '%s'\n", io->runprofile);
					exit (MAGIC_EXIT);
				}
			}
			if (bits==64)
				r_run_parseline (rp, expr=strdup ("bits=64"));
			else if (bits==32)
				r_run_parseline (rp, expr=strdup ("bits=32"));
			free (expr);
			r_run_start (rp);
			r_run_free (rp);
			// double free wtf
			//	r_str_argv_free (argv);
			exit (1);
		} else {
			// TODO: Add support to redirect filedescriptors
			// TODO: Configure process environment
			char *_cmd = strdup (cmd);
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
#if __APPLE__
			 {
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
				ut32 ps_flags = POSIX_SPAWN_SETEXEC;
				posix_spawnattr_t attr = {0};
				size_t copied = 1;
				cpu_type_t cpu;
				pid_t p = -1;
				int ret;

				int useASLR = 1;
				posix_spawnattr_init (&attr);
				if (useASLR != -1) {
					if (useASLR) {
						// enable aslr if not enabled? really?
					} else {
						ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
					}
				}
				(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __i386__ || __x86_64__
				cpu = CPU_TYPE_I386;
				if (bits == 64)
					cpu |= CPU_ARCH_ABI64;
#else
				cpu = CPU_TYPE_ANY;
#endif
				posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
				ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL);
				switch (ret) {
				case 0:
					eprintf ("Success\n");
					break;
				case 22:
					eprintf ("posix_spawnp: Invalid argument\n");
					break;
				case 86:
					eprintf ("Unsupported architecture\n");
					break;
				default:
					eprintf ("posix_spawnp: unknown error %d\n", ret);
					perror ("posix_spawnp");
					break;
				}
				/* only required if no SETEXEC called
				   if (p != -1)
				   wait (p);
				 */
				exit (MAGIC_EXIT); /* error */
			 }
#else
			 if (argv && *argv) {
				 execvp (argv[0], argv);
			 } else {
				 eprintf ("Invalid execvp\n");
			 }
#endif
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
                	ret = wait (&status);
			if (ret == -1)
				return -1;
			if (ret != pid)
				eprintf ("Wait event received by different pid %d\n", ret);
		} while (ret!=pid);
		if (WIFSTOPPED (status))
			eprintf ("Process with PID %d started...\n", (int)pid);
		if (WEXITSTATUS (status) == MAGIC_EXIT)
			pid = -1;
		// XXX kill (pid, SIGSTOP);
		break;
	}
	eprintf ("PID = %d\n", pid);
	return pid;
}
#endif

static int __plugin_open(RIO *io, const char *file, ut8 many) {
	if (!strncmp (file, "dbg://", 6) && file[6])
		return R_TRUE;
	return R_FALSE;
}

static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
	char uri[128];
	if (__plugin_open (io, file,  0)) {
		const char *pidfile = file + 6;
		char *endptr;
		int pid = (int)strtol (pidfile, &endptr, 10);
		if (endptr == pidfile || pid < 0) pid = -1;

		if (pid == -1) {
			pid = fork_and_ptraceme (io, io->bits, file+6);
			if (pid == -1)
				return NULL;
#if __WINDOWS__
			sprintf (uri, "w32dbg://%d", pid);
#elif __APPLE__
			sprintf (uri, "mach://%d", pid);
#else
			// TODO: use io_procpid here? faster or what?
			sprintf (uri, "ptrace://%d", pid);
#endif
			my_io_redirect (io, file, uri);
		} else {
			sprintf (uri, "attach://%d", pid);
			my_io_redirect (io, file, uri);
		}
		return NULL;
	}
	my_io_redirect (io, file, NULL);
	return NULL;
}
Exemplo n.º 8
0
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
	char buffer[1024], *outputptr = NULL;
	char *inputptr = (char *)input;
	int pid, bytes = 0, status;
	int sh_in[2], sh_out[2], sh_err[2];

	if (len) *len = 0;
	if (pipe (sh_in))
		return R_FALSE;
	if (output) {
		if (pipe (sh_out)) {
			close (sh_in[0]);
			close (sh_in[1]);
			close (sh_out[0]);
			close (sh_out[1]);
			return R_FALSE;
		}
	}
	if (pipe (sh_err)) {
		close (sh_in[0]);
		close (sh_in[1]);
		return R_FALSE;
	}

	switch ((pid = r_sys_fork ())) {
	case -1:
		return R_FALSE;
	case 0:
		dup2 (sh_in[0], 0);
		close (sh_in[0]);
		close (sh_in[1]);
		if (output) {
			dup2 (sh_out[1], 1);
			close (sh_out[0]);
			close (sh_out[1]);
		}
		if (sterr) dup2 (sh_err[1], 2); else close (2);
		close (sh_err[0]); close (sh_err[1]);
		exit (r_sandbox_system (cmd, 0));
	default:
		outputptr = strdup ("");
		if (!outputptr)
			return R_FALSE;
		if (sterr) {
			*sterr = strdup ("");
			if (!*sterr) {
				free (outputptr);
				return R_FALSE;
			}
		}
		if (output) close (sh_out[1]);
		close (sh_err[1]);
		close (sh_in[0]);
		if (!inputptr || !*inputptr)
			close (sh_in[1]);

		// we should handle broken pipes somehow better
		signal (SIGPIPE, SIG_IGN);
		for (;;) {
			fd_set rfds, wfds;
			int nfd;

			FD_ZERO (&rfds);
			FD_ZERO (&wfds);
			if (output)
				FD_SET (sh_out[0], &rfds);
			if (sterr)
				FD_SET (sh_err[0], &rfds);
			if (inputptr && *inputptr)
				FD_SET (sh_in[1], &wfds);
			memset (buffer, 0, sizeof (buffer));
			nfd = select (sh_err[0] + 1, &rfds, &wfds, NULL, NULL);
			if (nfd < 0)
				break;
			if (output && FD_ISSET (sh_out[0], &rfds)) {
				if ((bytes = read (sh_out[0], buffer, sizeof (buffer)-1)) == 0) break;
				buffer[sizeof(buffer) - 1] = '\0';
				if (len) *len += bytes;
				outputptr = r_str_concat (outputptr, buffer);
			} else if (FD_ISSET (sh_err[0], &rfds) && sterr) {
				if (read (sh_err[0], buffer, sizeof (buffer)-1) == 0) break;
				buffer[sizeof(buffer) - 1] = '\0';
				*sterr = r_str_concat (*sterr, buffer);
			} else if (FD_ISSET (sh_in[1], &wfds) && inputptr && *inputptr) {
				int inputptr_len = strlen (inputptr);
				bytes = write (sh_in[1], inputptr, inputptr_len);
				if (bytes != inputptr_len) {
					break;
				}
				inputptr += bytes;
				if (!*inputptr) {
					close (sh_in[1]);
					/* If neither stdout nor stderr should be captured,
					 * abort now - nothing more to do for select(). */
					if (!output && !sterr) break;
				}
			}
		}
		if (output)
			close (sh_out[0]);
		close (sh_err[0]);
		close (sh_in[1]);
		waitpid (pid, &status, 0);
		if (status != 0) {
			char *escmd = r_str_escape (cmd);
			eprintf ("%s: failed command '%s'\n", __func__, escmd);
			free (escmd);
			return R_FALSE;
		}

		if (output) *output = outputptr;
		else free (outputptr);
		return R_TRUE;
	}
	return R_FALSE;
}
Exemplo n.º 9
0
Arquivo: pipe.c Projeto: 0x2F/radare2
static int lang_pipe_run(RLang *lang, const char *code, int len) {
#if __UNIX__
	int safe_in = dup (0);
	int child, ret;
	int input[2];
	int output[2];
	pipe (input);
	pipe (output);

	env ("R2PIPE_IN", input[0]);
	env ("R2PIPE_OUT", output[1]);

	child = r_sys_fork ();
	if (child == -1) {
		/* error */
	} else if (child == 0) {
		/* children */
#if 1
		r_sandbox_system (code, 1);
#else
		/* DEMO */
		char buf[1024];
		/* kid stuff here */
		while (1) {
			write (output[1], "pd 3\n", 6);
			res = read (input[0], buf, sizeof (buf)-1);
			if (res <1) break;
			printf ("---> ((%s))\n", buf);
			sleep (1);
		}
#endif
		write (input[1], "", 1);
		close (input[0]);
		close (input[1]);
		close (output[0]);
		close (output[1]);
		exit (0);
		return R_FALSE;
	} else {
		/* parent */
		char *res, buf[1024];

		/* Close pipe ends not required in the parent */
		close(output[1]);
		close(input[0]);

		r_cons_break (NULL, NULL);
		for (;;) {
			if (r_cons_singleton ()->breaked) {
				break;
			}
			memset (buf, 0, sizeof (buf));
			ret = read (output[0], buf, sizeof (buf)-1);
			if (ret <1 || !buf[0]) {
				break;
			}
			buf[sizeof (buf)-1] = 0;
			res = lang->cmd_str ((RCore*)lang->user, buf);
			//eprintf ("%d %s\n", ret, buf);
			if (res) {
				write (input[1], res, strlen (res)+1);
				free (res);
			} else {
				eprintf ("r_lang_pipe: NULL reply for (%s)\n", buf);
				write (input[1], "", 1); // NULL byte
			}
		}
		/* workaround to avoid stdin closed */
		if (safe_in != -1)
			close (safe_in);
		safe_in = open (ttyname(0), O_RDONLY);
		if (safe_in != -1) {
			dup2 (safe_in, 0);
		} else eprintf ("Cannot open ttyname(0) %s\n", ttyname(0));
		r_cons_break_end ();
	}

	close (input[0]);
	close (input[1]);
	close (output[0]);
	close (output[1]);
	if (safe_in != -1)
		close (safe_in);
	waitpid (child, NULL, 0);
	return R_TRUE;
#else
#if __WINDOWS__
	HANDLE hPipeInOut = NULL;
	HANDLE hproc=NULL;
	DWORD dwRead, dwWritten;
	CHAR buf[1024];
	BOOL bSuccess = FALSE;
	int res=0;
	sprintf(buf,"R2PIPE_IN%x",_getpid());
	SetEnvironmentVariable("R2PIPE_PATH",buf);
	sprintf(buf,"\\\\.\\pipe\\R2PIPE_IN%x",_getpid());
	hPipeInOut = CreateNamedPipe(buf,
		PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | \
		PIPE_READMODE_MESSAGE | \
		PIPE_NOWAIT,PIPE_UNLIMITED_INSTANCES,
		sizeof (buf), sizeof (buf), 0, NULL);
	hproc=myCreateChildProcess (code);
	if (hproc==NULL) {
		//eprintf("Error spawning process: %s\n",code);
		return R_TRUE;
	}
	r_cons_break (NULL, NULL);
	for (;;)
	{
		res = ConnectNamedPipe(hPipeInOut, NULL);
		if (GetLastError()==ERROR_PIPE_CONNECTED) {
			//eprintf("new client\n");
			break;
		}
		if (r_cons_singleton ()->breaked) {
			TerminateProcess(hproc,0);
			break;
		}

	}
	for (;;) {
		if (r_cons_singleton ()->breaked) {
			TerminateProcess(hproc,0);
			break;
		}
		memset (buf, 0, sizeof (buf));
		bSuccess = ReadFile( hPipeInOut, buf, sizeof (buf), &dwRead, NULL);
	  	if (dwRead!=0) {
			buf[sizeof(buf)-1] = 0;
			res = lang->cmd_str ((RCore*)lang->user, buf);
			if (res) {
				WriteFile(hPipeInOut, res, strlen (res)+1, &dwWritten, NULL);
				free (res);
			} else {
				WriteFile(hPipeInOut, "", 1, &dwWritten, NULL);
			}
	  	}
	}
	CloseHandle(hPipeInOut);
	r_cons_break_end ();
	return R_TRUE;
#endif
#endif
}
Exemplo n.º 10
0
Arquivo: run.c Projeto: f0829/radare2
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;
}
Exemplo n.º 11
0
Arquivo: run.c Projeto: f0829/radare2
static int redirect_socket_to_pty(RSocket *sock) {
#if HAVE_PTY
	// directly duplicating the fds using dup2() creates problems
	// in case of interactive applications
	int fdm, fds;

	if (openpty (&fdm, &fds, NULL, NULL, NULL) == -1) {
		perror ("opening pty");
		return -1;
	}

	pid_t child_pid = r_sys_fork ();

	if (child_pid == -1) {
		eprintf ("cannot fork\n");
		close(fdm);
		close(fds);
		return -1;
	}

	if (child_pid == 0) {
		// child process
		close (fds);

		char *buff = NULL;
		int sockfd = sock->fd;
		int max_fd = fdm > sockfd ? fdm : sockfd;

		while (true) {
			fd_set readfds;
			FD_ZERO (&readfds);
			FD_SET (fdm, &readfds);
			FD_SET (sockfd, &readfds);

			if (select (max_fd + 1, &readfds, NULL, NULL, NULL) == -1) {
				perror ("select error");
				break;
			}

			if (FD_ISSET (fdm, &readfds)) {
				if (fd_forward (fdm, sockfd, &buff) != 0) {
					break;
				}
			}

			if (FD_ISSET (sockfd, &readfds)) {
				if (fd_forward (sockfd, fdm, &buff) != 0) {
					break;
				}
			}
		}

		free (buff);
		close (fdm);
		r_socket_free (sock);
		exit (0);
	}

	// parent
	r_socket_close_fd (sock);
	login_tty (fds);
	close (fdm);

	// disable the echo on slave stdin
	struct termios t;
	tcgetattr (0, &t);
	cfmakeraw (&t);
	tcsetattr (0, TCSANOW, &t);

	return 0;
#else
	// Fallback to socket to I/O redirection
	return redirect_socket_to_stdio (sock);
#endif
}
Exemplo n.º 12
0
// __UNIX__ (not windows)
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
#if __APPLE__ && !__POWERPC__
	pid_t p = -1;
	posix_spawn_file_actions_t fileActions;
	ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
	sigset_t no_signals;
	sigset_t all_signals;
	size_t copied = 1;
	cpu_type_t cpu = CPU_TYPE_ANY;
	posix_spawnattr_t attr = {0};
	posix_spawnattr_init (&attr);

	sigemptyset (&no_signals);
	sigfillset (&all_signals);
	posix_spawnattr_setsigmask (&attr, &no_signals);
	posix_spawnattr_setsigdefault (&attr, &all_signals);

	posix_spawn_file_actions_init (&fileActions);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);

	ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
	ps_flags |= POSIX_SPAWN_START_SUSPENDED;
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
	if (!runprofile) {
		int ret, useASLR = io->aslr;
		char *_cmd = io->args
			? r_str_appendf (strdup (cmd), " %s", io->args)
			: strdup (cmd);
		argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return -1;
		}
		if (!*argv) {
			r_str_argv_free (argv);
			free (_cmd);
			eprintf ("Invalid execvp\n");
			return -1;
		}
		if (useASLR != -1) {
			if (!useASLR) {
				ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
			}
		}
		(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __x86_64__
		if (bits == 32) {
			cpu = CPU_TYPE_I386;
			// cpu |= CPU_ARCH_ABI64;
		}
#endif
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		{
			char *dst = r_file_readlink (argv[0]);
			if (dst) {
				argv[0] = dst;
			}
		}
		ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL);
		handle_posix_error (ret);
		posix_spawn_file_actions_destroy (&fileActions);
		r_str_argv_free (argv);
		free (_cmd);
		return p;
	} else {
		int ret;
		argv = r_str_argv (cmd, NULL);
		if (!argv) {
			posix_spawn_file_actions_destroy (&fileActions);
			return -1;
		}
		RRunProfile *rp = _get_run_profile (io, bits, argv);
		if (!rp) {
			r_str_argv_free (argv);
			posix_spawn_file_actions_destroy (&fileActions);
			return -1;
		}
		handle_posix_redirection (rp, &fileActions);
		if (rp->_args[0]) {
			if (!rp->_aslr) {
				ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
			}
#if __x86_64__
			if (rp->_bits == 32) {
				cpu = CPU_TYPE_I386;
			}
#endif
			(void)posix_spawnattr_setflags (&attr, ps_flags);
			posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
			ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL);
			handle_posix_error (ret);
		}
		r_str_argv_free (argv);
		r_run_free (rp);
		posix_spawn_file_actions_destroy (&fileActions);
		return p;
	}
	posix_spawn_file_actions_destroy (&fileActions);
	return -1;
#endif
	int ret, status, child_pid;
	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			argv = r_str_argv (cmd, NULL);
			if (!argv) {
				exit(1);
			}
			RRunProfile *rp = _get_run_profile (io, bits, argv);
			if (!rp) {
				r_str_argv_free (argv);
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_appendf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++)
					(void)close (i);
				execvp (argv[0], argv);
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status)) {
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		}
		if (WEXITSTATUS (status) == MAGIC_EXIT) {
			child_pid = -1;
		}
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
}
Exemplo n.º 13
0
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;
	}
	// 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->_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;
		}
		while (true) {
			child = r_socket_accept (fd);
			if (child) {
				int is_child = true;

				if (p->_dofork && !p->_dodebug) {
					pid_t child_pid = r_sys_fork ();
					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");
					close (0);
					close (1);
					close (2);
					dup2 (child->fd, 0);
					dup2 (child->fd, 1);
					dup2 (child->fd, 2);
					break;
				} else {
					r_socket_close_fd (child);
				}
			}
		}
	}
	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) {
		char *inp;
		int f2[2];
		pipe (f2);
		close (0);
		dup2 (f2[0], 0);
		inp = getstr (p->_input);
		if (inp) {
			write (f2[1], inp, strlen (inp));
			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
		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 (!r_sys_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__ && !defined(__HAIKU__)
			if (nice (p->_nice) == -1) {
				return 1;
			}
#else
			eprintf ("nice not supported for this platform\n");
#endif
		}
		exit (execv (p->_program, (char* const*)p->_args));
	}
	return 0;
}
Exemplo n.º 14
0
static void trace_me () {
#if __APPLE__
	signal (SIGTRAP, SIG_IGN); //NEED BY STEP
#endif
#if __APPLE__ || __BSD__
/* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
	signal (SIGABRT, inferior_abort_handler);
	if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
#else
	if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
#endif
		r_sys_perror ("ptrace-traceme");
		exit (MAGIC_EXIT);
	}
}

// __UNIX__ (not windows)
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
#if __APPLE__ && !__POWERPC__
	if (!runprofile) {
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
		posix_spawn_file_actions_t fileActions;
		ut32 ps_flags = POSIX_SPAWN_SETSIGDEF |
				POSIX_SPAWN_SETSIGMASK;
   		sigset_t no_signals;
    		sigset_t all_signals;
    		sigemptyset (&no_signals);
    		sigfillset (&all_signals);
		posix_spawnattr_t attr = {0};
		size_t copied = 1;
		cpu_type_t cpu;
		pid_t p = -1;
		int ret, useASLR = io->aslr;
		char *_cmd = io->args ?
				r_str_concatf (strdup (cmd), " %s", io->args) :
				strdup (cmd);
		argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return -1;
		}
		if (!*argv) {
			r_str_argv_free (argv);
			free (_cmd);
			eprintf ("Invalid execvp\n");
			return -1;
		}
		posix_spawnattr_init (&attr);
		if (useASLR != -1) {
			if (!useASLR) ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
		}

		posix_spawn_file_actions_init (&fileActions);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);
		ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
		ps_flags |= POSIX_SPAWN_START_SUSPENDED;

   		posix_spawnattr_setsigmask(&attr, &no_signals);
    		posix_spawnattr_setsigdefault(&attr, &all_signals);

		(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __i386__ || __x86_64__
		cpu = CPU_TYPE_I386;
		if (bits == 64) cpu |= CPU_ARCH_ABI64;
#else
		cpu = CPU_TYPE_ANY;
#endif
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		{
			char *dst = r_file_readlink (argv[0]);
			if (dst) {
				argv[0] = dst;
			}
		}
		ret = posix_spawnp (&p, argv[0], &fileActions, &attr, argv, NULL);
		switch (ret) {
		case 0:
			// eprintf ("Success\n");
			break;
		case 22:
			eprintf ("posix_spawnp: Invalid argument\n");
			break;
		case 86:
			eprintf ("Unsupported architecture\n");
			break;
		default:
			eprintf ("posix_spawnp: unknown error %d\n", ret);
			perror ("posix_spawnp");
			break;
		}
		posix_spawn_file_actions_destroy (&fileActions);
		r_str_argv_free (argv);
		free (_cmd);
		return p;
	}
#endif
	int ret, status, child_pid;

	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			char *expr = NULL;
			int i;
			RRunProfile *rp = r_run_new (NULL);
			argv = r_str_argv (cmd, NULL);
			for (i = 0; argv[i]; i++) {
				rp->_args[i] = argv[i];
			}
			rp->_args[i] = NULL;
			rp->_program = argv[0];
			rp->_dodebug = true;
			if (io->runprofile && *io->runprofile) {
				if (!r_run_parsefile (rp, io->runprofile)) {
					eprintf ("Can't find profile '%s'\n",
						io->runprofile);
					exit (MAGIC_EXIT);
				}
			}
			if (bits == 64)
				r_run_parseline (rp, expr=strdup ("bits=64"));
			else if (bits == 32)
				r_run_parseline (rp, expr=strdup ("bits=32"));
			free (expr);
			if (r_run_config_env (rp)) {
				eprintf ("Can't config the environment.\n");
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_concatf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++)
					(void)close (i);
				execvp (argv[0], argv);
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status))
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		if (WEXITSTATUS (status) == MAGIC_EXIT)
			child_pid = -1;
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
}
Exemplo n.º 15
0
Arquivo: sys.c Projeto: agatti/radare2
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
	char *mysterr = NULL;
	if (!sterr) {
		sterr = &mysterr;
	}
	char buffer[1024], *outputptr = NULL;
	char *inputptr = (char *)input;
	int pid, bytes = 0, status;
	int sh_in[2], sh_out[2], sh_err[2];

	if (len) {
		*len = 0;
	}
	if (pipe (sh_in)) {
		return false;
	}
	if (output) {
		if (pipe (sh_out)) {
			close (sh_in[0]);
			close (sh_in[1]);
			close (sh_out[0]);
			close (sh_out[1]);
			return false;
		}
	}
	if (pipe (sh_err)) {
		close (sh_in[0]);
		close (sh_in[1]);
		return false;
	}

	switch ((pid = r_sys_fork ())) {
	case -1:
		return false;
	case 0:
		dup2 (sh_in[0], 0);
		close (sh_in[0]);
		close (sh_in[1]);
		if (output) {
			dup2 (sh_out[1], 1);
			close (sh_out[0]);
			close (sh_out[1]);
		}
		if (sterr) {
			dup2 (sh_err[1], 2); 
		} else {
			close (2);
		}
		close (sh_err[0]);
		close (sh_err[1]);
		exit (r_sandbox_system (cmd, 0));
	default:
		outputptr = strdup ("");
		if (!outputptr) {
			return false;
		}
		if (sterr) {
			*sterr = strdup ("");
			if (!*sterr) {
				free (outputptr);
				return false;
			}
		}
		if (output) {
			close (sh_out[1]);
		}
		close (sh_err[1]);
		close (sh_in[0]);
		if (!inputptr || !*inputptr) {
			close (sh_in[1]);
		}
		// we should handle broken pipes somehow better
		signal (SIGPIPE, SIG_IGN);
		for (;;) {
			fd_set rfds, wfds;
			int nfd;
			FD_ZERO (&rfds);
			FD_ZERO (&wfds);
			if (output) {
				FD_SET (sh_out[0], &rfds);
			}
			if (sterr) {
				FD_SET (sh_err[0], &rfds);
			}
			if (inputptr && *inputptr) {
				FD_SET (sh_in[1], &wfds);
			}
			memset (buffer, 0, sizeof (buffer));
			nfd = select (sh_err[0] + 1, &rfds, &wfds, NULL, NULL);
			if (nfd < 0) {
				break;
			}
			if (output && FD_ISSET (sh_out[0], &rfds)) {
				if (!(bytes = read (sh_out[0], buffer, sizeof (buffer)-1))) {
					break;
				}
				buffer[sizeof (buffer) - 1] = '\0';
				if (len) {
					*len += bytes;
				}
				outputptr = r_str_append (outputptr, buffer);
			} else if (FD_ISSET (sh_err[0], &rfds) && sterr) {
				if (!read (sh_err[0], buffer, sizeof (buffer)-1)) {
					break;
				}
				buffer[sizeof (buffer) - 1] = '\0';
				*sterr = r_str_append (*sterr, buffer);
			} else if (FD_ISSET (sh_in[1], &wfds) && inputptr && *inputptr) {
				int inputptr_len = strlen (inputptr);
				bytes = write (sh_in[1], inputptr, inputptr_len);
				if (bytes != inputptr_len) {
					break;
				}
				inputptr += bytes;
				if (!*inputptr) {
					close (sh_in[1]);
					/* If neither stdout nor stderr should be captured,
					 * abort now - nothing more to do for select(). */
					if (!output && !sterr) {
						break;
					}
				}
			}
		}
		if (output) {
			close (sh_out[0]);
		}
		close (sh_err[0]);
		close (sh_in[1]);
		waitpid (pid, &status, 0);
		bool ret = true;
		if (status) {
			// char *escmd = r_str_escape (cmd);
			// eprintf ("error code %d (%s): %s\n", WEXITSTATUS (status), escmd, *sterr);
			// eprintf ("(%s)\n", output);
			// eprintf ("%s: failed command '%s'\n", __func__, escmd);
			// free (escmd);
			ret = false;
		}

		if (output) {
			*output = outputptr;
		} else {
			free (outputptr);
		}
		return ret;
	}
	return false;
}
Exemplo n.º 16
0
static int lang_pipe_run(RLang *lang, const char *code, int len) {
#if __UNIX__
	int safe_in = dup (0);
	int child, ret;
	int input[2];
	int output[2];

	pipe (input);
	pipe (output);

	env ("R2PIPE_IN", input[0]);
	env ("R2PIPE_OUT", output[1]);

	child = r_sys_fork ();
	if (child == -1) {
		/* error */
	} else if (child == 0) {
		/* children */
		r_sandbox_system (code, 1);
		write (input[1], "", 1);
		close (input[0]);
		close (input[1]);
		close (output[0]);
		close (output[1]);
		exit (0);
		return false;
	} else {
		/* parent */
		char *res, buf[1024];

		/* Close pipe ends not required in the parent */
		close (output[1]);
		close (input[0]);

		r_cons_break (NULL, NULL);
		for (;;) {
			if (r_cons_singleton ()->breaked) {
				break;
			}
			memset (buf, 0, sizeof (buf));
			ret = read (output[0], buf, sizeof (buf)-1);
			if (ret <1 || !buf[0]) {
				break;
			}
			buf[sizeof (buf)-1] = 0;
			res = lang->cmd_str ((RCore*)lang->user, buf);
			//eprintf ("%d %s\n", ret, buf);
			if (res) {
				write (input[1], res, strlen (res)+1);
				free (res);
			} else {
				eprintf ("r_lang_pipe: NULL reply for (%s)\n", buf);
				write (input[1], "", 1); // NULL byte
			}
		}
		/* workaround to avoid stdin closed */
		if (safe_in != -1)
			close (safe_in);
		safe_in = open (ttyname(0), O_RDONLY);
		if (safe_in != -1) {
			dup2 (safe_in, 0);
		} else eprintf ("Cannot open ttyname(0) %s\n", ttyname(0));
		r_cons_break_end ();
	}

	close (input[0]);
	close (input[1]);
	close (output[0]);
	close (output[1]);
	if (safe_in != -1)
		close (safe_in);
	waitpid (child, NULL, 0);
	return true;
#else
#if __WINDOWS__
	HANDLE hThread = 0;
	char buf[512];
	sprintf(buf,"R2PIPE_IN%x",_getpid());
	SetEnvironmentVariable("R2PIPE_PATH",buf);
	sprintf(buf,"\\\\.\\pipe\\R2PIPE_IN%x",_getpid());
	hPipeInOut = CreateNamedPipe(buf,
			PIPE_ACCESS_DUPLEX,
			PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
			PIPE_BUF_SIZE,
			PIPE_BUF_SIZE,
			0,
			NULL);
	hproc = myCreateChildProcess (code);
	if (!hproc) {
		return false;
	}
	bStopThread=FALSE;
	hThread = CreateThread (NULL, 0,ThreadFunction,lang, 0,0);
	WaitForSingleObject (hproc, INFINITE );
	bStopThread = TRUE;
	DeleteFile (buf);
	WaitForSingleObject (hThread, INFINITE);
	CloseHandle (hPipeInOut);
	return true;
#endif
#endif
}
Exemplo n.º 17
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
#if __APPLE__ && !__POWERPC__
	return fork_and_ptraceme_for_mac(io, bits, cmd);
#else
	int ret, status, child_pid;
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			argv = r_str_argv (cmd, NULL);
			if (!argv) {
				exit(1);
			}
			RRunProfile *rp = _get_run_profile (io, bits, argv);
			if (!rp) {
				r_str_argv_free (argv);
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_appendf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++) {
					(void)close (i);
				}
				if (execvp (argv[0], argv) == -1) {
					eprintf ("Could not execvp: %s\n", strerror (errno));
					exit (MAGIC_EXIT);
				}
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status)) {
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		}
		if (WEXITSTATUS (status) == MAGIC_EXIT) {
			child_pid = -1;
		}
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
#endif
}