Module: SeccompTools::Ptrace

Defined in:
ext/ptrace/ptrace.c

Constant Summary collapse

EVENT_CLONE =

consts

UINT2NUM(PTRACE_EVENT_CLONE)
EVENT_FORK =
UINT2NUM(PTRACE_EVENT_FORK)
EVENT_VFORK =
UINT2NUM(PTRACE_EVENT_VFORK)
O_TRACECLONE =
UINT2NUM(PTRACE_O_TRACECLONE)
O_TRACEFORK =
UINT2NUM(PTRACE_O_TRACEFORK)
O_TRACESYSGOOD =
UINT2NUM(PTRACE_O_TRACESYSGOOD)
O_TRACEVFORK =
UINT2NUM(PTRACE_O_TRACEVFORK)

Class Method Summary collapse

Class Method Details

.attach_and_wait(pid) ⇒ Object

attach to an existing process



107
108
109
110
111
112
113
114
# File 'ext/ptrace/ptrace.c', line 107

static VALUE
ptrace_attach_and_wait(VALUE _mod, VALUE pid) {
  long val = ptrace(PTRACE_ATTACH, NUM2LONG(pid), 0, 0);
  if(val < 0)
    rb_sys_fail("ptrace attach failed");
  waitpid(NUM2LONG(pid), NULL, 0);
  return Qnil;
}

.detach(pid) ⇒ Object

detach from an existing process



133
134
135
136
137
138
139
# File 'ext/ptrace/ptrace.c', line 133

static VALUE
ptrace_detach(VALUE _mod, VALUE pid) {
  long val = ptrace(PTRACE_DETACH, NUM2LONG(pid), 0, 0);
  if(val < 0)
    rb_sys_fail(0);
  return Qnil;
}

.geteventmsg(pid) ⇒ Object

geteventmsg



17
18
19
20
21
22
# File 'ext/ptrace/ptrace.c', line 17

static VALUE
ptrace_geteventmsg(VALUE _mod, VALUE pid) {
  unsigned long val;
  ptrace(PTRACE_GETEVENTMSG, NUM2LONG(pid), NULL, &val);
  return ULONG2NUM(val);  
}

.peekdata(pid, addr, _data) ⇒ Object

get data



24
25
26
27
28
# File 'ext/ptrace/ptrace.c', line 24

static VALUE
ptrace_peekdata(VALUE _mod, VALUE pid, VALUE addr, VALUE _data) {
  long val = ptrace(PTRACE_PEEKDATA, NUM2LONG(pid), NUM2LONG(addr), NULL);
  return LONG2NUM(val);  
}

.peekuser(pid, off, _data, bits) ⇒ Object

we care about.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'ext/ptrace/ptrace.c', line 34

static VALUE
ptrace_peekuser(VALUE _mod, VALUE pid, VALUE off, VALUE _data, VALUE bits) {
  size_t offset = NUM2LONG(off);
  // Unless your registers fill an entire page, an offset greater than this is
  // probably wrong.
  if (offset >= 4096) {
    return LONG2NUM(-1);
  }
  size_t width = NUM2LONG(bits);
  if (width != 32 && width != 64) {
    return LONG2NUM(-1);
  }
  width /= 8;
  union {
    uint32_t val32;
    uint64_t val64;
  } val;
  // Dynamically allocate a buffer to store registers-well, at least enough
  // registers to reach the offset we want. Normally we'd want to use
  // user_pt_regs or similar, but it's difficult to find it available in the
  // the same header across different versions of Linux or libcs, or even with
  // the same *name*, so this is the compromise.
  size_t size = offset + width;
  char *regs = malloc(size);
  if (!regs) {
    return LONG2NUM(-1);
  }
  struct iovec vec = { regs, size };
  if (ptrace(PTRACE_GETREGSET, NUM2LONG(pid), NT_PRSTATUS, &vec) != -1 && vec.iov_len >= size) {
    memcpy(&val, regs + offset, width);
  } else {
    free(regs);
    return LONG2NUM(-1);
  }
  free(regs);
  if (width == sizeof(val.val32)) {
    return LONG2NUM(val.val32);
  } else if (width == sizeof(val.val64)) {
    return LONG2NUM(val.val64);
  } else {
    assert(!"Unreachable");
    return LONG2NUM(-1);
  }
}

.seccomp_get_filter(pid, index) ⇒ Object

retrieve seccomp filter



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'ext/ptrace/ptrace.c', line 116

static VALUE
ptrace_seccomp_get_filter(VALUE _mod, VALUE pid, VALUE index) {
  long count = ptrace(PTRACE_SECCOMP_GET_FILTER, NUM2LONG(pid), NUM2LONG(index), NULL);
  struct sock_filter *filter;
  VALUE result;
  if(count < 0)
    rb_sys_fail("ptrace seccomp_get_filter failed");
  filter = ALLOC_N(struct sock_filter, count);
  if(ptrace(PTRACE_SECCOMP_GET_FILTER, NUM2LONG(pid), NUM2LONG(index), filter) != count) {
    xfree(filter);
    rb_sys_fail("ptrace seccomp_get_filter failed");
  }
  result = rb_str_new((const char *)filter, sizeof(struct sock_filter) * count);
  xfree(filter);
  return result;
}

.setoptions(pid, _addr, option) ⇒ Object

set ptrace options



79
80
81
82
83
84
# File 'ext/ptrace/ptrace.c', line 79

static VALUE
ptrace_setoptions(VALUE _mod, VALUE pid, VALUE _addr, VALUE option) {
  if(ptrace(PTRACE_SETOPTIONS, NUM2LONG(pid), NULL, NUM2LONG(option)) != 0)
    perror("ptrace setoptions");
  return Qnil;
}

.syscall(pid, _addr, sig) ⇒ Object

wait for syscall



86
87
88
89
90
91
# File 'ext/ptrace/ptrace.c', line 86

static VALUE
ptrace_syscall(VALUE _mod, VALUE pid, VALUE _addr, VALUE sig) {
  if(ptrace(PTRACE_SYSCALL, NUM2LONG(pid), NULL, NUM2LONG(sig)) != 0)
    perror("ptrace syscall");
  return Qnil;
}

.tracemeObject

wait for its parent to attach



93
94
95
96
97
98
# File 'ext/ptrace/ptrace.c', line 93

static VALUE
ptrace_traceme(VALUE _mod) {
  if(ptrace(PTRACE_TRACEME, 0, 0, 0) != 0)
    perror("ptrace traceme");
  return Qnil;
}

.traceme_and_stopObject

stop itself before parent attaching



100
101
102
103
104
105
# File 'ext/ptrace/ptrace.c', line 100

static VALUE
ptrace_traceme_and_stop(VALUE mod) {
  ptrace_traceme(mod);
  kill(getpid(), SIGSTOP);
  return Qnil;
}