Skip to content

Commit fc431e0

Browse files
committed
728* driver/systrace.c: Bug fix for /proc/dtrace/syscall - SIGSEGV
and confusion on 32b kernel.
1 parent e9e7992 commit fc431e0

File tree

10 files changed

+721
-15
lines changed

10 files changed

+721
-15
lines changed

.release

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
date=Thu Jul 26 21:47:57 BST 2012
2-
release=dtrace-20120726d
3-
build=402
1+
date=Fri Jul 27 22:57:26 BST 2012
2+
release=dtrace-20120727
3+
build=403

Changes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
Fri Jul 27 13:27:25 2012 fox
2+
3+
728* driver/systrace.c: Bug fix for /proc/dtrace/syscall - SIGSEGV
4+
and confusion on 32b kernel.
5+
6+
727* libproc/common/Pcontrol.c: Use the /dev/dtrace_ctl driver instead
7+
of ptrace(). We can now use PID provider on stopped jobs or even
8+
procs being debugged in a debugger.
9+
110
Thu Jul 26 08:33:03 2012 fox
211

312
726* archive: 1.0140

driver/ctl.c

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ present.
8181
#define PCSZONE 30L /* set zoneid from zoneid_t argument */
8282
#define PCSCREDX 31L /* as PCSCRED but with supplemental groups */
8383

84-
void *(*fn_get_pid_task)(void *, int);
84+
static void (*__put_task_struct_ptr)(struct task_struct *);
8585
static int (*access_process_vm_ptr)(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
8686

8787
#if 0
@@ -215,31 +215,63 @@ ctl_linux_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsign
215215

216216
if (copyin((void *) arg, &mem, sizeof mem))
217217
return -EFAULT;
218+
if (mem.c_len <= 0)
219+
return -EINVAL;
218220

219-
#if 0
221+
/***********************************************/
222+
/* Convert PID to a process structure, but */
223+
/* special locking required in case process */
224+
/* tries to die. The */
225+
/* get_task_struct/put_task_struct modifies */
226+
/* a lock counter. */
227+
/***********************************************/
220228
rcu_read_lock();
221-
// child = find_task_by_vpid(mem.c_pid);
229+
child = find_task_by_vpid(mem.c_pid);
222230
if (child)
223231
get_task_struct(child);
224232
rcu_read_unlock();
225233
if (child == NULL)
226234
return -ESRCH;
227-
#endif
228235

229236
src = mem.c_src;
230237
dst = mem.c_dst;
231238
for (len = mem.c_len; len > 0; ) {
232239
int sz = len > sizeof buf ? sizeof buf : len;
233240
int sz1;
234241

235-
sz1 = access_process_vm_ptr(child, (unsigned long) src, buf, sz,
236-
cmd == CTLIOC_RDMEM ? 0 : 1);
237-
if (sz1 <= 0)
238-
break;
239-
if (copyout(buf, dst, sz1))
240-
return -EFAULT;
242+
if (cmd == CTLIOC_RDMEM) {
243+
sz1 = access_process_vm_ptr(child,
244+
(unsigned long) src, buf, sz, 0);
245+
printk("sz1=%d sz=%d\n", sz1, sz);
246+
if (sz1 <= 0)
247+
break;
248+
printk("access_process_vm_ptr %p %p returns %d\n", src, dst, sz1);
249+
if (copy_to_user(dst, buf, sz1)) {
250+
n = -EFAULT;
251+
break;
252+
}
253+
} else {
254+
if (copy_from_user(buf, src, sz)) {
255+
n = -EFAULT;
256+
break;
257+
}
258+
sz1 = access_process_vm_ptr(child, (unsigned long) dst, buf, sz, 1);
259+
if (sz1 <= 0)
260+
break;
261+
}
262+
src += sz1;
263+
dst += sz1;
241264
len -= sz1;
265+
n += sz1;
242266
}
267+
268+
/***********************************************/
269+
/* Unlock the target now we are done. */
270+
/***********************************************/
271+
// put_task_struct(child); GPL
272+
if (atomic_dec_and_test(&child->usage))
273+
__put_task_struct_ptr(child);
274+
243275
return n;
244276
}
245277

@@ -286,6 +318,8 @@ static struct miscdevice ctl_dev = {
286318
int ctl_init(void)
287319
{ int ret;
288320

321+
__put_task_struct_ptr = get_proc_addr("__put_task_struct");
322+
289323
ret = misc_register(&ctl_dev);
290324
if (ret) {
291325
printk(KERN_WARNING "ctl: Unable to register misc device\n");

driver/systrace.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static char *syscallnames32[] = {
131131
};
132132
# define NSYSCALL32 (sizeof syscallnames32 / sizeof syscallnames32[0])
133133

134+
int xx = NSYSCALL;
135+
int xx32 = NSYSCALL32;
134136
struct sysent {
135137
asmlinkage int64_t (*sy_callc)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); /* C-style call hander or wrapper */
136138
};
@@ -2176,7 +2178,10 @@ static int sys_seq_show(struct seq_file *seq, void *v)
21762178
n -= 2;
21772179
if (n >= NSYSCALL + NSYSCALL32)
21782180
return 0;
2179-
2181+
# if defined(__i386)
2182+
if (n >= NSYSCALL)
2183+
return 0;
2184+
# endif
21802185
if (n >= NSYSCALL) {
21812186
sysp = &systrace_sysent32[n - NSYSCALL];
21822187
syp = &sysent32[n - NSYSCALL];
@@ -2186,7 +2191,11 @@ static int sys_seq_show(struct seq_file *seq, void *v)
21862191
}
21872192

21882193
seq_printf(seq, "%s%s %p %p %3d %8llu %s\n",
2194+
# if defined(__i386)
2195+
"x32",
2196+
# else
21892197
n >= NSYSCALL ? "x32" : "x64",
2198+
# endif
21902199
syp->sy_callc == sysp->stsy_underlying ? " " : "*",
21912200
syp->sy_callc, sysp->stsy_underlying,
21922201
(int) (n >= NSYSCALL ? n - NSYSCALL : n),

include/ctl.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**********************************************************************/
2+
/* Driver for allowing direct access to process memory - similar */
3+
/* to /proc/pid/mem, but bypassing various restrictions which mean */
4+
/* that dtrace can have trouble ptrace() attaching to a process */
5+
/* which is being debugged. */
6+
/**********************************************************************/
7+
8+
#if !defined(_CTL_H_INCLUDE)
9+
# define _CTL_H_INCLUDE
10+
11+
/**********************************************************************/
12+
/* ioctl values and structures for /dev/dtrace_ctl */
13+
/**********************************************************************/
14+
#define CTLIOC (('c' << 24) | ('t' << 16) | ('l' << 8))
15+
#define CTLIOC_RDMEM (CTLIOC | 1)
16+
#define CTLIOC_WRMEM (CTLIOC | 2)
17+
typedef struct ctl_mem_t {
18+
int c_pid;
19+
void *c_src;
20+
void *c_dst;
21+
int c_len;
22+
} ctl_mem_t;
23+
24+
#endif /* _CTL_H_INCLUDE */

libdtrace/dt_proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
737737
* an external debugger and we were waiting in dt_proc_waitrun().
738738
* Leave the process in this condition using PRELEASE_HANG.
739739
*/
740-
printf("dt_proc_destroy flags=%d\n", Pstatus(dpr->dpr_proc)->pr_flags);
740+
/*printf("dt_proc_destroy flags=%d\n", Pstatus(dpr->dpr_proc)->pr_flags);*/
741741
if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) {
742742
dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid);
743743
rflag = PRELEASE_HANG;

libproc/common/Pcontrol.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <sys/sysmacros.h>
5353
# if linux
5454
#include <sys/ptrace.h>
55+
#include "../../include/ctl.h"
5556
# endif
5657

5758

@@ -93,6 +94,23 @@ static ssize_t
9394
Pread_live(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
9495
{
9596
# if linux
97+
static int fd = -1;
98+
ctl_mem_t ctl;
99+
100+
if (fd < 0) {
101+
if ((fd = open("/dev/dtrace_ctl", O_RDWR)) < 0) {
102+
perror("/dev/dtrace_ctl");
103+
printf("Either dtrace kernel module is not loaded or you are not root.\n");
104+
return -1;
105+
}
106+
}
107+
108+
ctl.c_pid = P->pid;
109+
ctl.c_src = addr;
110+
ctl.c_dst = buf;
111+
ctl.c_len = n;
112+
return ioctl(fd, CTLIOC_RDMEM, &ctl);
113+
96114
// HACK: this is horrible from a performance perspective,
97115
// and we need to be root to attach, but pread() wont
98116
// work unless we own the proc. We need to move this to

libproc/common/Psymtab.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ get_saddrs(struct ps_prochandle *P, uintptr_t ehdr_start, uint_t *n)
103103
uintptr_t a, addr, *addrs, last = 0;
104104
uint_t i, naddrs = 0, unordered = 0;
105105

106+
printf("model=%lx\n", P->status.pr_dmodel);
106107
if (P->status.pr_dmodel == PR_MODEL_ILP32) {
107108
Elf32_Ehdr ehdr;
108109
Elf32_Phdr phdr;
@@ -159,6 +160,10 @@ get_saddrs(struct ps_prochandle *P, uintptr_t ehdr_start, uint_t *n)
159160
addrs[naddrs++] = last = addr + phdr.p_memsz - 1;
160161
}
161162
#endif
163+
} else {
164+
printf("Internal error: %s:%s pr_dmodel is incorrect\n",
165+
__FILE__, __func__);
166+
abort();
162167
}
163168

164169
if (unordered)

tests/ctl.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include <stdio.h>
2+
#include <fcntl.h>
3+
#include <stdlib.h>
4+
#include "../include/ctl.h"
5+
6+
char buf[2 * 1024 * 1024];
7+
8+
static void
9+
dump_mem(char *start, char *mem, char *memend)
10+
{ char *cp;
11+
int i;
12+
13+
for (cp = mem; cp < memend; cp += 16) {
14+
printf("%04lx: ", cp - start);
15+
for (i = 0; i < 16 && cp + i < memend; i++) {
16+
printf("%02x ", cp[i] & 0xff);
17+
}
18+
printf("\n");
19+
}
20+
}
21+
22+
int main(int argc, char **argv)
23+
{ int arg_index = 1;
24+
int ret, cmd;
25+
int fd;
26+
ctl_mem_t ctl;
27+
28+
if (argc < 5) {
29+
printf("usage: ctl [rd | wr] pid addr len\n");
30+
exit(1);
31+
}
32+
33+
fd = open("/dev/dtrace_ctl", O_RDWR);
34+
if (fd < 0) {
35+
perror("/dev/dtrace_ctl");
36+
exit(1);
37+
}
38+
39+
if (strcmp(argv[arg_index++], "rd") == 0) {
40+
ctl.c_pid = atoi(argv[arg_index++]);
41+
cmd = CTLIOC_RDMEM;
42+
ctl.c_dst = buf;
43+
ctl.c_src = strtoul(argv[arg_index++], NULL, 0);
44+
} else {
45+
ctl.c_pid = atoi(argv[arg_index++]);
46+
cmd = CTLIOC_WRMEM;
47+
ctl.c_src = buf;
48+
ctl.c_dst = strtoul(argv[arg_index++], NULL, 0);
49+
}
50+
ctl.c_len = atoi(argv[arg_index++]);
51+
52+
printf("pid=%d src=%p dst=%p len=%d\n",
53+
ctl.c_pid, ctl.c_src, ctl.c_dst, ctl.c_len);
54+
if ((ret = ioctl(fd, cmd, &ctl)) < 0) {
55+
perror("ioctl");
56+
exit(1);
57+
}
58+
printf("ret=%d\n", ret);
59+
dump_mem(buf, buf, buf + ret);
60+
}

0 commit comments

Comments
 (0)