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
-
.attach_and_wait(pid) ⇒ Object
attach to an existing process.
-
.detach(pid) ⇒ Object
detach from an existing process.
-
.geteventmsg(pid) ⇒ Object
geteventmsg.
-
.peekdata(pid, addr, _data) ⇒ Object
get data.
-
.peekuser(pid, off, _data, bits) ⇒ Object
we care about.
-
.seccomp_get_filter(pid, index) ⇒ Object
retrieve seccomp filter.
-
.setoptions(pid, _addr, option) ⇒ Object
set ptrace options.
-
.syscall(pid, _addr, sig) ⇒ Object
wait for syscall.
-
.traceme ⇒ Object
wait for its parent to attach.
-
.traceme_and_stop ⇒ Object
stop itself before parent attaching.
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;
}
|
.traceme ⇒ Object
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_stop ⇒ Object
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; } |