Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 16 Mar 2013 01:25:04 +0100 (CET)
From: Pavel Kankovsky <peak@...o.troja.mff.cuni.cz>
To: owl-dev@...ts.openwall.com
Subject: Re: strace

On Fri, 15 Mar 2013, Pavel Kankovsky wrote:

> On Fri, 15 Mar 2013, Dmitry V. Levin wrote:
>
>>  The change of orig_eax offset means that there was a change in the ptrace
>>  ABI between 2.6.18 and 2.6.32, and all its users (e.g. strace and gdb)
>>  should be rebuilt.
>
> Things appear to be a little more complicated.
>
> As far as I can tell, PTRACE_GETREGS returns data in struct pt_regs 
> layout on 2.6.18 and in struct user_regs_struct layout on 2.6.32. Those 
> two structs are compatible on 2.6.32 but they are different on 2.6.18 
> (i386 arch; x86-64 is probably unaffected).

Uhh... I am sorry. Let me retract this statement, please. I was not 
thinking clearly (note to myself: do not write & send any important emails 
after 2am) and I misinterpreted the code in 2.6.18 (I quote vanilla 
here, RH added some irrelevant stuff):

static unsigned long getreg(struct task_struct *child,
 	unsigned long regno)
{
 	unsigned long retval = ~0UL;

 	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)
 				regno -= 2*4;
 			regno = regno - sizeof(struct pt_regs);
 			retval &= get_stack_long(child, regno);
 	}
 	return retval;
}

I did not pay enough attention to "if (regno > GS*4) regno -= 2*4".
That command skips two elements that are present in user_regs_struct
but are missing in pt_regs:

pt_regs (2.6.18):         user_regs_struct (2.6.32):
   long ebx;                 unsigned long   bx;
   long ecx;                 unsigned long   cx;
   long edx;                 unsigned long   dx;
   long esi;                 unsigned long   si;
   long edi;                 unsigned long   di;
   long ebp;                 unsigned long   bp;
   long eax;                 unsigned long   ax;
   int  xds;                 unsigned long   ds;
   int  xes;                 unsigned long   es;
                             unsigned long   fs;
                             unsigned long   gs;
   long orig_eax;            unsigned long   orig_ax;
   long eip;                 unsigned long   ip;
   int  xcs;                 unsigned long   cs;
   long eflags;              unsigned long   flags;
   long esp;                 unsigned long   sp;
   int  xss;                 unsigned long   ss;

(For some unfathomable reasons, register names in user_regs_struct differ
between kernel headers and Glibc but the layout stays the same.)

There were some changes: GS was migrated to struct pt_regs in 2.6.20
and the code was reengineered completely in 2.6.25. But it appears to me
(now) that its interface has been stable.

I made a small test program PTRACE_GETREGS and I get the expected results 
(namely orig_eax == 0x25 == SYS_kill) on RHEL 2.6.18 and on 2.6.32.

  0: ebx      0x0000372a
  1: ecx      0x00000002
  2: edx      0x009c4ff4
  3: esi      0x00867ca0
  4: edi      0x00000000
  5: ebp      0xbffa1b08
  6: eax      0x00000000
  7: ds       0x0000007b
  8: es       0x0000007b
  9: fs       0x00000000
10: gs       0x00000033
11: orig_eax 0x00000025  <---- SYS_kill
12: eip      0x006bb402
13: cs       0x00000073
14: eflags   0x00000246
15: esp      0xbffa1a88
16: ss       0x0000007b
17: xxx      0xdeafbeef


-- 
Pavel Kankovsky aka Peak                          / Jeremiah 9:21        \
"For death is come up into our MS Windows(tm)..." \ 21st century edition /
View attachment "ptrace_getregs.c" of type "TEXT/PLAIN" (1184 bytes)

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ