* RE: ptrace bug
2001-10-16 0:12 ptrace bug Gian-Yan Xu
@ 2001-10-15 17:04 ` Monty Vanderbilt
2001-10-16 9:52 ` Gian-Yan Xu
0 siblings, 1 reply; 4+ messages in thread
From: Monty Vanderbilt @ 2001-10-15 17:04 UTC (permalink / raw)
To: Gian-Yan Xu, linux-kernel
I don't think the problem is what you identified.
arch/i386/kernel/ptrace.c:getreg() takes the extra FS,GS offsets into
account and performs special handling for them. I suspect this is because
they are not stable per-thread registers and not saved into the register
structure on an interrupt or system call.
ptrace.c:getreg() ...
switch (regno >> 2) {
case FS:
retval = child->thread.fs;
break;
case GS:
retval = child->thread.gs;
break;
case DS:
case ES:
case SS:
case CS:
retval = 0xffff;
/* fall through */
default:
if (regno > GS*4) // *** Adusts for missing FS,GS fields *** //
regno -= 2*4;
regno = regno - sizeof(struct pt_regs);
retval &= get_stack_long(child, regno);
}
-----Original Message-----
From: linux-kernel-owner@vger.kernel.org
[mailto:linux-kernel-owner@vger.kernel.org]On Behalf Of Gian-Yan Xu
Sent: Monday, October 15, 2001 5:12 PM
To: linux-kernel@vger.kernel.org
Subject: ptrace bug
Today I try to get register's value via ptrace(PTRACE_GETREGS, ...),
but only EBX, ECX, EDX, ESI, EDI, EBP, EAX registers are correct.
I notice that file /usr/src/linux/include/asm/ptrace.h:
#define FS 9
#define GS 10
but in the declare of struct pt_regs:
struct pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
There is no xfs/xgs member in that struct, and the #define FRAME_SIZE 17
is not match the number of member in the pt_regs struct.
In addition, in the ptrace.c:
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, (unsigned *)data,
FRAME_SIZE*sizeo(long))) {
ret = -EIO;
break;
}
for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
__put_user(getreg(child, i),(unsigned long *) data);
data += sizeof(long);
}
ret = 0;
FRAME_SIZE*sizeof(long) is larger than sizeof(struct pt_regs),
the ptrace() will overwrite the data of parent process!
To fix the bug, try this patch:
--- ptrace.h.orig Mon Oct 15 21:00:48 2001
+++ ptrace.h Mon Oct 15 21:05:56 2001
@@ -33,6 +33,8 @@
long eax;
int xds;
int xes;
+ int xfs;
+ int xgs;
long orig_eax;
long eip;
int xcs;
--
Best regards,
Gian-Yain Xu. (kids@linux.ee.tku.edu.tw)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 4+ messages in thread
* ptrace bug
@ 2001-10-16 0:12 Gian-Yan Xu
2001-10-15 17:04 ` Monty Vanderbilt
0 siblings, 1 reply; 4+ messages in thread
From: Gian-Yan Xu @ 2001-10-16 0:12 UTC (permalink / raw)
To: linux-kernel
Today I try to get register's value via ptrace(PTRACE_GETREGS, ...),
but only EBX, ECX, EDX, ESI, EDI, EBP, EAX registers are correct.
I notice that file /usr/src/linux/include/asm/ptrace.h:
#define FS 9
#define GS 10
but in the declare of struct pt_regs:
struct pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
There is no xfs/xgs member in that struct, and the #define FRAME_SIZE 17
is not match the number of member in the pt_regs struct.
In addition, in the ptrace.c:
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
if (!access_ok(VERIFY_WRITE, (unsigned *)data,
FRAME_SIZE*sizeo(long))) {
ret = -EIO;
break;
}
for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
__put_user(getreg(child, i),(unsigned long *) data);
data += sizeof(long);
}
ret = 0;
FRAME_SIZE*sizeof(long) is larger than sizeof(struct pt_regs),
the ptrace() will overwrite the data of parent process!
To fix the bug, try this patch:
--- ptrace.h.orig Mon Oct 15 21:00:48 2001
+++ ptrace.h Mon Oct 15 21:05:56 2001
@@ -33,6 +33,8 @@
long eax;
int xds;
int xes;
+ int xfs;
+ int xgs;
long orig_eax;
long eip;
int xcs;
--
Best regards,
Gian-Yain Xu. (kids@linux.ee.tku.edu.tw)
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: ptrace bug
2001-10-15 17:04 ` Monty Vanderbilt
@ 2001-10-16 9:52 ` Gian-Yan Xu
0 siblings, 0 replies; 4+ messages in thread
From: Gian-Yan Xu @ 2001-10-16 9:52 UTC (permalink / raw)
To: Monty Vanderbilt; +Cc: linux-kernel
On Mon, 15 Oct 2001, Monty Vanderbilt wrote:
> I don't think the problem is what you identified.
> arch/i386/kernel/ptrace.c:getreg() takes the extra FS,GS offsets into
> account and performs special handling for them. I suspect this is because
> they are not stable per-thread registers and not saved into the register
> structure on an interrupt or system call.
Before the reply, I dont examin getreg() carefully. But now, I still
believe the bug is exist. see the blow (ptrace.c case PTRACE_GETREGS):
for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
__put_user(getreg(child, i),(unsigned long *) data);
data += sizeof(long);
}
when i = FS*sizeof(long), the getreg() return child->thread.fs,
and the value will be copy into *data of user-space, but
*data is point to orig_eax of struct pt_regs.
So, when i = ORIG_EAX*sizeof(long), even getreg() adjust his regno,
that let us get accurate registers, but it copy value into wrong member of
struct pt_regs ( the *data is point to xcs member, not orig_eax member,
because the line: data += sizeof(long); never be adjust)
If we dont modify struct pt_regs, maybe we should fix the ptrace.c?
>
> ptrace.c:getreg() ...
> switch (regno >> 2) {
> case FS:
> retval = child->thread.fs;
> break;
> case GS:
> retval = child->thread.gs;
> break;
> case DS:
> case ES:
> case SS:
> case CS:
> retval = 0xffff;
> /* fall through */
> default:
> if (regno > GS*4) // *** Adusts for missing FS,GS fields *** //
> regno -= 2*4;
> regno = regno - sizeof(struct pt_regs);
> retval &= get_stack_long(child, regno);
> }
>
--
Best regards,
Gian-Yan Xu.
^ permalink raw reply [flat|nested] 4+ messages in thread
* ptrace() bug
@ 2002-02-17 14:56 Juan Cespedes
0 siblings, 0 replies; 4+ messages in thread
From: Juan Cespedes @ 2002-02-17 14:56 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 888 bytes --]
Hi,
I am the author of "ltrace" and unfortunatelly it does not work in 2.4
kernels, due to a bug in the kernel. Unfortunately, I don't know when
did this behaviour started and what could have caused it...
Summary: if I use ptrace() witth a process that does fork(), and after
the fork I modify with PTRACE_POKETEXT some of the code in the parent,
the same modification is observed in the child.
I need to modify the .text in order to introduce breakpoints, but with
this bug ltrace does not work with any process which forks.
The attached little program shows the bug: the child should not see the
content of "sync" modified after it is alive.
Thanks for your help,
--
.+'''+. .+'''+. .+'''+. .+'''+. .+''
Juan Cespedes / \ / \ cespedes@debian.org
.+' `+...+' `+...+' `+...+' `+...+'
[-- Attachment #2: test.c --]
[-- Type: text/x-csrc, Size: 789 bytes --]
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <signal.h>
void
traced_process(void) {
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
exit(1);
kill(getpid(), SIGCONT);
if (fork()) {
sleep(2);
/* printf("parent: *sync=%d\n", *(unsigned char*)sync); */
} else {
printf("child is alive (*sync=%d)\n", *(unsigned char*)sync);
sleep(1);
printf("child: *sync=%d\n", *(unsigned char*)sync);
}
exit(0);
}
int
main(void) {
pid_t pid;
int status;
int i=0;
pid = fork();
if (!pid) traced_process();
while(1) {
if (wait(&status)==-1) {
break;
}
printf("ptrace(PTRACE_POKETEXT, %d, sync, %d)...\n", pid, ++i);
ptrace(PTRACE_POKETEXT, pid, sync, i);
ptrace(PTRACE_SYSCALL, pid, 0, 0);
}
exit(0);
}
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2002-02-17 14:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-10-16 0:12 ptrace bug Gian-Yan Xu
2001-10-15 17:04 ` Monty Vanderbilt
2001-10-16 9:52 ` Gian-Yan Xu
-- strict thread matches above, loose matches on Subject: below --
2002-02-17 14:56 ptrace() bug Juan Cespedes
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.