Skip to content

Commit

Permalink
Checkpoint working version.
Browse files Browse the repository at this point in the history
  • Loading branch information
nelhage committed Jan 18, 2011
1 parent f260382 commit 9e91662
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 11 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CFLAGS=-Wall -Werror
CFLAGS=-Wall -Werror -D_GNU_SOURCE -g
STUB_CFLAGS=$(CFLAGS) -nostdlib -Wl,-r -fomit-frame-pointer

all: reptyr stub.o
all: reptyr

reptyr: reptyr.o ptrace.o attach.o

Expand Down
91 changes: 89 additions & 2 deletions attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <limits.h>

#include "ptrace.h"

Expand Down Expand Up @@ -48,10 +50,11 @@ int *get_child_tty_fds(struct ptrace_child *child, int *count) {
if (len < 0)
continue;
buf[len] = 0;
if (strcmp(buf, child_tty) == 0) {
if (strcmp(buf, child_tty) == 0
|| strcmp(buf, "/dev/tty") == 0) {
if (n == allocated) {
allocated = allocated ? 2 * allocated : 2;
fds = realloc(fds, allocated);
fds = realloc(fds, sizeof(int) * allocated);
if (!fds)
goto out;
}
Expand All @@ -65,12 +68,40 @@ int *get_child_tty_fds(struct ptrace_child *child, int *count) {
return fds;
}

void move_process_group(struct ptrace_child *from, pid_t to) {
DIR *dir;
struct dirent *d;
pid_t pid;
char *p;
int err;

if ((dir = opendir("/proc/")) == NULL)
return;

while ((d = readdir(dir)) != NULL) {
if(d->d_name[0] == '.') continue;
pid = strtol(d->d_name, &p, 10);
if (*p) continue;
if (getpgid(pid) == from->pid) {
debug("Change pgid for pid %d", pid);
err = ptrace_remote_syscall(from, __NR_setpgid,
pid, to,
0, 0, 0, 0);
if (err < 0)
debug(" failed: %s", strerror(-err));
}
}
closedir(dir);
}

int attach_child(pid_t pid, const char *pty) {
struct ptrace_child child;
unsigned long scratch_page = -1;
int *child_tty_fds = NULL, n_fds, child_fd;
int i;
int err = 0;
struct ptrace_child dummy;


if (ptrace_attach_child(&child, pid))
return errno;
Expand Down Expand Up @@ -131,13 +162,66 @@ int attach_child(pid_t pid, const char *pty) {

debug("Copied terminal settings");

err = ptrace_remote_syscall(&child, __NR_fork,
0, 0, 0, 0, 0, 0);
if (err < 0)
goto out_close;

debug("Forked a child: %d", child.forked_pid);

err = ptrace_finish_attach(&dummy, child.forked_pid);
if (err < 0)
goto out_kill;

if (ptrace_save_regs(&dummy)) {
err = errno;
goto out_kill;
}

err = ptrace_remote_syscall(&dummy, __NR_setpgid,
0, 0, 0, 0, 0, 0);
if (err < 0) {
debug("Failed to setpgid: %s", strerror(-err));
goto out_kill;
}

move_process_group(&child, dummy.pid);

err = ptrace_remote_syscall(&child, __NR_setsid,
0, 0, 0, 0, 0, 0);
if (err < 0) {
debug("Failed to setsid: %s", strerror(-err));
goto out_kill;
}

debug("Did setsid()");

err = ptrace_remote_syscall(&child, __NR_ioctl,
child_fd, TIOCSCTTY,
0, 0, 0, 0);
if (err < 0)
goto out_kill;

debug("Set the controlling tty");

for (i = 0; i < n_fds; i++)
ptrace_remote_syscall(&child, __NR_dup2,
child_fd, child_tty_fds[i],
0, 0, 0, 0);

ptrace_remote_syscall(&child, __NR_signal,
SIGHUP, (unsigned long)SIG_IGN,
0, 0, 0, 0);

err = 0;

out_kill:
kill(dummy.pid, SIGKILL);
ptrace_wait(&dummy);
ptrace_remote_syscall(&child, __NR_waitpid,
dummy.pid, 0, WNOHANG,
0, 0, 0);

out_close:
ptrace_remote_syscall(&child, __NR_close, child_fd,
0, 0, 0, 0, 0);
Expand All @@ -151,5 +235,8 @@ int attach_child(pid_t pid, const char *pty) {
out_detach:
ptrace_detach_child(&child);

if (err == 0)
kill(child.pid, SIGWINCH);

return err;
}
22 changes: 16 additions & 6 deletions ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,22 @@ int ptrace_wait(struct ptrace_child *child);

int ptrace_attach_child(struct ptrace_child *child, pid_t pid) {
int err = 0;
if ((err = ptrace(PTRACE_ATTACH, pid)) < 0)
return err;

return ptrace_finish_attach(child, pid);
}

int ptrace_finish_attach(struct ptrace_child *child, pid_t pid) {
int err;

memset(child, 0, sizeof child);
child->pid = pid;

if ((err = ptrace(PTRACE_ATTACH, pid)) < 0)
return err;

ptrace_wait(child);

if ((err = ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD)) < 0)
if ((err = ptrace(PTRACE_SETOPTIONS, pid, 0,
PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACEFORK)) < 0)
goto detach;

return err;
Expand All @@ -59,11 +65,15 @@ int ptrace_wait(struct ptrace_child *child) {
if (WIFEXITED(child->status) || WIFSIGNALED(child->status)) {
child->state = ptrace_exited;
} else if(WIFSTOPPED(child->status)) {
if (WSTOPSIG(child->status) & 0x80) {
int sig = WSTOPSIG(child->status);
if (sig & 0x80) {
child->state = (child->state == ptrace_at_syscall) ?
ptrace_after_syscall : ptrace_at_syscall;
} else {
child->state = ptrace_stopped;
if (sig == SIGTRAP && (((child->status >> 8) & PTRACE_EVENT_FORK) == PTRACE_EVENT_FORK))
ptrace(PTRACE_GETEVENTMSG, child->pid, 0, &child->forked_pid);
if (child->state != ptrace_at_syscall)
child->state = ptrace_stopped;
}
} else {
errno = EINVAL;
Expand Down
2 changes: 2 additions & 0 deletions ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ struct ptrace_child {
struct user user;
enum child_state state;
int status;
unsigned long forked_pid;
};

typedef unsigned long child_addr_t;

int ptrace_wait(struct ptrace_child *child);
int ptrace_attach_child(struct ptrace_child *child, pid_t pid);
int ptrace_finish_attach(struct ptrace_child *child, pid_t pid);
int ptrace_detach_child(struct ptrace_child *child);
int ptrace_wait(struct ptrace_child *child);
int ptrace_advance_to_state(struct ptrace_child *child,
Expand Down
3 changes: 2 additions & 1 deletion reptyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ int main(int argc, char **argv) {
die("Unable to unlockpt: %m");

if (argc > 1) {
if (attach_child(atoi(argv[1]),
pid_t child = atoi(argv[1]);
if (attach_child(child,
ptsname(pty))) {
perror("Attaching to child");
return 1;
Expand Down

0 comments on commit 9e91662

Please sign in to comment.