Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Mon, Jun 20, 2016 at 9:14 AM, Oleg Nesterov  wrote:
> On 06/20, Andy Lutomirski wrote:
>>
>> On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
>> >
>> > How about the simple change below for now? IIRC 32-bit task can't use
>> > "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
>> > not that bad, even if it "leaks" to user-mode.
>>
>> Hmm.  That should fix the minor security issue, but it will even
>> further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
>> task that does int $0x80 will malfunction even more than it would
>> have.
>
> This is broken in any case. I mean, a 32-bit debugger can't really
> debug a 64-bit task.
>
> I don't think this change makes the things really worse.
>
>> Also, it relies on bizarre arch details IMO.
>
> Heh,  it looks as if your patch do not ;)
>
>> I think I prefer my version, coming momentarily.
>
> I disagree... I don't really understand why do we need the additional
> complications for the minimal fix which doesn't look very nice anyway.
>
> But I won't argue, and your patch looks correct to me.

Part of the reason is that I actually want to fix this in two parts.
After my TS_REGS_POKED_I386 patch, I have a follow-up patch that I
want to polish and test a bit more that's intended to get the
64-bit-tracer/32-bit-tracee case right, but it probably needs extra
testing, is less likely to make 4.8, and is definitely not for
4.7/stab.e.  That patch deletes TS_REGS_POKED_I386 again.  So by
having the minimal fix be more mindless, I'm more comfortable with the
backport.  I'll send out the second patch soon.


--Andy


-- 
Andy Lutomirski
AMA Capital Management, LLC


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Mon, Jun 20, 2016 at 9:14 AM, Oleg Nesterov  wrote:
> On 06/20, Andy Lutomirski wrote:
>>
>> On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
>> >
>> > How about the simple change below for now? IIRC 32-bit task can't use
>> > "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
>> > not that bad, even if it "leaks" to user-mode.
>>
>> Hmm.  That should fix the minor security issue, but it will even
>> further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
>> task that does int $0x80 will malfunction even more than it would
>> have.
>
> This is broken in any case. I mean, a 32-bit debugger can't really
> debug a 64-bit task.
>
> I don't think this change makes the things really worse.
>
>> Also, it relies on bizarre arch details IMO.
>
> Heh,  it looks as if your patch do not ;)
>
>> I think I prefer my version, coming momentarily.
>
> I disagree... I don't really understand why do we need the additional
> complications for the minimal fix which doesn't look very nice anyway.
>
> But I won't argue, and your patch looks correct to me.

Part of the reason is that I actually want to fix this in two parts.
After my TS_REGS_POKED_I386 patch, I have a follow-up patch that I
want to polish and test a bit more that's intended to get the
64-bit-tracer/32-bit-tracee case right, but it probably needs extra
testing, is less likely to make 4.8, and is definitely not for
4.7/stab.e.  That patch deletes TS_REGS_POKED_I386 again.  So by
having the minimal fix be more mindless, I'm more comfortable with the
backport.  I'll send out the second patch soon.


--Andy


-- 
Andy Lutomirski
AMA Capital Management, LLC


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/20, Andy Lutomirski wrote:
>
> On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
> >
> > How about the simple change below for now? IIRC 32-bit task can't use
> > "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
> > not that bad, even if it "leaks" to user-mode.
>
> Hmm.  That should fix the minor security issue, but it will even
> further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
> task that does int $0x80 will malfunction even more than it would
> have.

This is broken in any case. I mean, a 32-bit debugger can't really
debug a 64-bit task.

I don't think this change makes the things really worse.

> Also, it relies on bizarre arch details IMO.

Heh,  it looks as if your patch do not ;)

> I think I prefer my version, coming momentarily.

I disagree... I don't really understand why do we need the additional
complications for the minimal fix which doesn't look very nice anyway.

But I won't argue, and your patch looks correct to me.

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/20, Andy Lutomirski wrote:
>
> On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
> >
> > How about the simple change below for now? IIRC 32-bit task can't use
> > "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
> > not that bad, even if it "leaks" to user-mode.
>
> Hmm.  That should fix the minor security issue, but it will even
> further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
> task that does int $0x80 will malfunction even more than it would
> have.

This is broken in any case. I mean, a 32-bit debugger can't really
debug a 64-bit task.

I don't think this change makes the things really worse.

> Also, it relies on bizarre arch details IMO.

Heh,  it looks as if your patch do not ;)

> I think I prefer my version, coming momentarily.

I disagree... I don't really understand why do we need the additional
complications for the minimal fix which doesn't look very nice anyway.

But I won't argue, and your patch looks correct to me.

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
> On 06/19, Andy Lutomirski wrote:
>>
>> On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  
>> wrote:
>> Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
>> in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
>> etc.  Clear it in do_signal.
>
> do_signal() won't be necessarily called...

True.  But I should have said "clear it in prepare_exit_to_usermode",
and the patch I'm just about to send does that.
>
>> I wonder if we could actually get away with doing syscall restart
>> processing before ptrace invocation.
>
> How? this doesn't look possible or I misunderstood.
>
> How about the simple change below for now? IIRC 32-bit task can't use
> "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
> not that bad, even if it "leaks" to user-mode.

Hmm.  That should fix the minor security issue, but it will even
further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
task that does int $0x80 will malfunction even more than it would
have.  Also, it relies on bizarre arch details IMO.

I think I prefer my version, coming momentarily.

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Mon, Jun 20, 2016 at 8:24 AM, Oleg Nesterov  wrote:
> On 06/19, Andy Lutomirski wrote:
>>
>> On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  
>> wrote:
>> Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
>> in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
>> etc.  Clear it in do_signal.
>
> do_signal() won't be necessarily called...

True.  But I should have said "clear it in prepare_exit_to_usermode",
and the patch I'm just about to send does that.
>
>> I wonder if we could actually get away with doing syscall restart
>> processing before ptrace invocation.
>
> How? this doesn't look possible or I misunderstood.
>
> How about the simple change below for now? IIRC 32-bit task can't use
> "syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
> not that bad, even if it "leaks" to user-mode.

Hmm.  That should fix the minor security issue, but it will even
further break cross-arch tracing: now a 32-bit tracer tracing a 64-bit
task that does int $0x80 will malfunction even more than it would
have.  Also, it relies on bizarre arch details IMO.

I think I prefer my version, coming momentarily.

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/19, Andy Lutomirski wrote:
>
> On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  wrote:
> Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
> in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
> etc.  Clear it in do_signal.

do_signal() won't be necessarily called...

> I wonder if we could actually get away with doing syscall restart
> processing before ptrace invocation.

How? this doesn't look possible or I misunderstood.

How about the simple change below for now? IIRC 32-bit task can't use
"syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
not that bad, even if it "leaks" to user-mode.

nobody should use, say, in_ia32_syscall() unless we know that "in syscall"
is actually true. Hmm, arch/x86/kernel/uprobes.c does and this is wrong
regardless, I'll send the fix.

Oleg.

--- x/arch/x86/kernel/ptrace.c
+++ x/arch/x86/kernel/ptrace.c
@@ -930,7 +930,7 @@ static int putreg32(struct task_struct *
 * exit from a 32-bit syscall with TS_COMPAT still set.
 */
regs->orig_ax = value;
-   if (syscall_get_nr(child, regs) >= 0)
+   if (syscall_get_nr(child, regs) >= 0 && !user_64bit_mode(regs))
task_thread_info(child)->status |= TS_COMPAT;
break;
 



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/19, Andy Lutomirski wrote:
>
> On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  wrote:
> Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
> in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
> etc.  Clear it in do_signal.

do_signal() won't be necessarily called...

> I wonder if we could actually get away with doing syscall restart
> processing before ptrace invocation.

How? this doesn't look possible or I misunderstood.

How about the simple change below for now? IIRC 32-bit task can't use
"syscall" so if syscall_get_nr() >= 0 then even the wrong TS_COMPAT is
not that bad, even if it "leaks" to user-mode.

nobody should use, say, in_ia32_syscall() unless we know that "in syscall"
is actually true. Hmm, arch/x86/kernel/uprobes.c does and this is wrong
regardless, I'll send the fix.

Oleg.

--- x/arch/x86/kernel/ptrace.c
+++ x/arch/x86/kernel/ptrace.c
@@ -930,7 +930,7 @@ static int putreg32(struct task_struct *
 * exit from a 32-bit syscall with TS_COMPAT still set.
 */
regs->orig_ax = value;
-   if (syscall_get_nr(child, regs) >= 0)
+   if (syscall_get_nr(child, regs) >= 0 && !user_64bit_mode(regs))
task_thread_info(child)->status |= TS_COMPAT;
break;
 



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/19, Andy Lutomirski wrote:
>
> On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> >
> > And this leads to another question, why do we actually need to set/clear
> > TS_COMPAT in set_personality_ia32() ??
>
> Something's clearly buggy there, considering that
> set_personality_64bit() does *not* clear it.

Yes, yes, I too noticed this, and this doesn't match the "if (x32)"
branch in set_personality_ia32().

But I think we do not really need to clear this bit. And probably
set_personality_ia32() doesn't need to play with TS_COMPAT.

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Oleg Nesterov
On 06/19, Andy Lutomirski wrote:
>
> On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> >
> > And this leads to another question, why do we actually need to set/clear
> > TS_COMPAT in set_personality_ia32() ??
>
> Something's clearly buggy there, considering that
> set_personality_64bit() does *not* clear it.

Yes, yes, I too noticed this, and this doesn't match the "if (x32)"
branch in set_personality_ia32().

But I think we do not really need to clear this bit. And probably
set_personality_ia32() doesn't need to play with TS_COMPAT.

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Jan Kratochvil
On Mon, 20 Jun 2016 12:07:56 +0200, Pedro Alves wrote:
> On 06/18/2016 06:02 PM, Andy Lutomirski wrote:
> > Yuck.  I should have dug in to the history.  Why not just
> > unconditionally sign-extend eax when set by a 32-bit tracer?
> 
> No idea.

Roland McGrath knows why he wrote it that way, Cced.

What if eax contains an address in 2GB..4GB range?  I guess currently the
orig_eax check tries to verify %eax cannot contain an address.


Jan


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Jan Kratochvil
On Mon, 20 Jun 2016 12:07:56 +0200, Pedro Alves wrote:
> On 06/18/2016 06:02 PM, Andy Lutomirski wrote:
> > Yuck.  I should have dug in to the history.  Why not just
> > unconditionally sign-extend eax when set by a 32-bit tracer?
> 
> No idea.

Roland McGrath knows why he wrote it that way, Cced.

What if eax contains an address in 2GB..4GB range?  I guess currently the
orig_eax check tries to verify %eax cannot contain an address.


Jan


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Pedro Alves
On 06/19/2016 11:09 PM, Andy Lutomirski wrote:
> 
> The latter bit is a mess and is probably broken on current kernels for
> 64-bit gdb attached to a 32-bit process.  (Is it?  All of this stuff
> is a bit of a pain to test.)

The testcase at:

 https://sourceware.org/ml/gdb/2014-05/msg4.html

still fails for me on Fedora 23 with git master gdb.

Nevermind the misleading URL, that's a kernel patch.

 $ gcc -g -m32 interrupt.c -o interrupt.32
 ...
 (gdb) r
 Starting program: /home/pedro/tmp/interrupt.32 
 talk to me baby
 ^C
 Program received signal SIGINT, Interrupt.
 0xf7fd9d49 in __kernel_vsyscall ()
 (gdb) p func1()
 $1 = 4
 (gdb) c
 Continuing.
 Unknown error 512
 [Inferior 1 (process 20252) exited with code 01]
 (gdb) 

That was a 64-bit gdb.

Note it doesn't fail with fedora 23's gdb, because of a 
fedora-local workaround.

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Pedro Alves
On 06/19/2016 11:09 PM, Andy Lutomirski wrote:
> 
> The latter bit is a mess and is probably broken on current kernels for
> 64-bit gdb attached to a 32-bit process.  (Is it?  All of this stuff
> is a bit of a pain to test.)

The testcase at:

 https://sourceware.org/ml/gdb/2014-05/msg4.html

still fails for me on Fedora 23 with git master gdb.

Nevermind the misleading URL, that's a kernel patch.

 $ gcc -g -m32 interrupt.c -o interrupt.32
 ...
 (gdb) r
 Starting program: /home/pedro/tmp/interrupt.32 
 talk to me baby
 ^C
 Program received signal SIGINT, Interrupt.
 0xf7fd9d49 in __kernel_vsyscall ()
 (gdb) p func1()
 $1 = 4
 (gdb) c
 Continuing.
 Unknown error 512
 [Inferior 1 (process 20252) exited with code 01]
 (gdb) 

That was a 64-bit gdb.

Note it doesn't fail with fedora 23's gdb, because of a 
fedora-local workaround.

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Pedro Alves
On 06/18/2016 06:02 PM, Andy Lutomirski wrote:

> Yuck.  I should have dug in to the history.  Why not just
> unconditionally sign-extend eax when set by a 32-bit tracer?

No idea.

> 
> Do you know how to acquire a copy of erestartsys-trap.c?  The old
> links appear to be broken.

That's part of the ptrace testsuite project, still in cvs, though the url 
changed:

 $ https://sourceware.org/systemtap/wiki/utrace/tests

 $ cvs -d :pserver:anoncvs:anon...@sourceware.org:/cvs/systemtap co ptrace-tests

Can't seem to find a cvsweb interface for that.

I think it'd be great to move these to the selftests infrastructure
directly in the kernel tree.  However, nobody's has ever managed to
find energy for that.

> 
> Also, while I have your attention: when gdb restores old state like
> this, does it do it with individual calls to PTRACE_POKEUSER or does
> it use SETREGSET or similar to do it all at once?  I'm asking because
> I have some other code (fsgsbase) that's on hold until I can figure
> out how to keep it from breaking gdb if and when gdb writes to fs and
> fs_base.
> 

It depends on which register you're accessing, and on kernel version.
But on a recent kernel, it should be using PTRACE_SETREGS / PTRACE_SETREGSET,
thus storing a whole register set in one go.  (And it's likely we could
get rid of PTRACE_POKE fallback paths by now.)
To write to the debug registers (dr0-dr7), PTRACE_POKEUSER is always used.

There's code that coordinates with glibc's libthread_db.so that ends
up _reading_ fs_base/gs_base, and gdb uses PTRACE_PEEKUSER for that,
though there's a pending series that changes it, exposing fs_base/gs_base
as just another register in gdb's register cache:

 https://www.sourceware.org/ml/gdb-patches/2015-11/msg00076.html
 https://www.sourceware.org/ml/gdb-patches/2015-11/msg00077.html

Guess that makes fs_base/gs_base user-writable, if the kernel allows it.

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Pedro Alves
On 06/18/2016 06:02 PM, Andy Lutomirski wrote:

> Yuck.  I should have dug in to the history.  Why not just
> unconditionally sign-extend eax when set by a 32-bit tracer?

No idea.

> 
> Do you know how to acquire a copy of erestartsys-trap.c?  The old
> links appear to be broken.

That's part of the ptrace testsuite project, still in cvs, though the url 
changed:

 $ https://sourceware.org/systemtap/wiki/utrace/tests

 $ cvs -d :pserver:anoncvs:anon...@sourceware.org:/cvs/systemtap co ptrace-tests

Can't seem to find a cvsweb interface for that.

I think it'd be great to move these to the selftests infrastructure
directly in the kernel tree.  However, nobody's has ever managed to
find energy for that.

> 
> Also, while I have your attention: when gdb restores old state like
> this, does it do it with individual calls to PTRACE_POKEUSER or does
> it use SETREGSET or similar to do it all at once?  I'm asking because
> I have some other code (fsgsbase) that's on hold until I can figure
> out how to keep it from breaking gdb if and when gdb writes to fs and
> fs_base.
> 

It depends on which register you're accessing, and on kernel version.
But on a recent kernel, it should be using PTRACE_SETREGS / PTRACE_SETREGSET,
thus storing a whole register set in one go.  (And it's likely we could
get rid of PTRACE_POKE fallback paths by now.)
To write to the debug registers (dr0-dr7), PTRACE_POKEUSER is always used.

There's code that coordinates with glibc's libthread_db.so that ends
up _reading_ fs_base/gs_base, and gdb uses PTRACE_PEEKUSER for that,
though there's a pending series that changes it, exposing fs_base/gs_base
as just another register in gdb's register cache:

 https://www.sourceware.org/ml/gdb-patches/2015-11/msg00076.html
 https://www.sourceware.org/ml/gdb-patches/2015-11/msg00077.html

Guess that makes fs_base/gs_base user-writable, if the kernel allows it.

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> Let me first thank Pedro who has already replied!
>
> And I have to admit I will need to re-read his explanations after
> sleep to (try to) convince myself I fully understans the problems ;)
> Too late for me.
>
> Right now I have nothing to add, but
>
> On 06/18, Andy Lutomirski wrote:
>>
>> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
>> regno, u32 value)
>>   R32(esp, sp);
>>
>>   case offsetof(struct user32, regs.orig_eax):
>> - /*
>> -  * A 32-bit debugger setting orig_eax means to restore
>> -  * the state of the task restarting a 32-bit syscall.
>> -  * Make sure we interpret the -ERESTART* codes correctly
>> -  * in case the task is not actually still sitting at the
>> -  * exit from a 32-bit syscall with TS_COMPAT still set.
>> -  */
>>   regs->orig_ax = value;
>> - if (syscall_get_nr(child, regs) >= 0)
>> - task_thread_info(child)->status |= TS_COMPAT;
>
> I agree it would be nice to remove this code, but then it is not clear
> how/when we should sign-extend regs->ax..
>
> And this leads to another question, why do we actually need to set/clear
> TS_COMPAT in set_personality_ia32() ??

Something's clearly buggy there, considering that
set_personality_64bit() does *not* clear it.

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-20 Thread Andy Lutomirski
On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> Let me first thank Pedro who has already replied!
>
> And I have to admit I will need to re-read his explanations after
> sleep to (try to) convince myself I fully understans the problems ;)
> Too late for me.
>
> Right now I have nothing to add, but
>
> On 06/18, Andy Lutomirski wrote:
>>
>> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
>> regno, u32 value)
>>   R32(esp, sp);
>>
>>   case offsetof(struct user32, regs.orig_eax):
>> - /*
>> -  * A 32-bit debugger setting orig_eax means to restore
>> -  * the state of the task restarting a 32-bit syscall.
>> -  * Make sure we interpret the -ERESTART* codes correctly
>> -  * in case the task is not actually still sitting at the
>> -  * exit from a 32-bit syscall with TS_COMPAT still set.
>> -  */
>>   regs->orig_ax = value;
>> - if (syscall_get_nr(child, regs) >= 0)
>> - task_thread_info(child)->status |= TS_COMPAT;
>
> I agree it would be nice to remove this code, but then it is not clear
> how/when we should sign-extend regs->ax..
>
> And this leads to another question, why do we actually need to set/clear
> TS_COMPAT in set_personality_ia32() ??

Something's clearly buggy there, considering that
set_personality_64bit() does *not* clear it.

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Andy Lutomirski
On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> Let me first thank Pedro who has already replied!
>
> And I have to admit I will need to re-read his explanations after
> sleep to (try to) convince myself I fully understans the problems ;)
> Too late for me.
>
> Right now I have nothing to add, but
>
> On 06/18, Andy Lutomirski wrote:
>>
>> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
>> regno, u32 value)
>>   R32(esp, sp);
>>
>>   case offsetof(struct user32, regs.orig_eax):
>> - /*
>> -  * A 32-bit debugger setting orig_eax means to restore
>> -  * the state of the task restarting a 32-bit syscall.
>> -  * Make sure we interpret the -ERESTART* codes correctly
>> -  * in case the task is not actually still sitting at the
>> -  * exit from a 32-bit syscall with TS_COMPAT still set.
>> -  */
>>   regs->orig_ax = value;
>> - if (syscall_get_nr(child, regs) >= 0)
>> - task_thread_info(child)->status |= TS_COMPAT;
>
> I agree it would be nice to remove this code, but then it is not clear
> how/when we should sign-extend regs->ax..
>
> And this leads to another question, why do we actually need to set/clear
> TS_COMPAT in set_personality_ia32() ??

I have no idea.  Legacy junk?  Maybe so audit sees execution of a
64-bit task as a 64-bit sys_execve return even if the task was 32-bit
before execve?

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Andy Lutomirski
On Sun, Jun 19, 2016 at 2:19 PM, Oleg Nesterov  wrote:
> Let me first thank Pedro who has already replied!
>
> And I have to admit I will need to re-read his explanations after
> sleep to (try to) convince myself I fully understans the problems ;)
> Too late for me.
>
> Right now I have nothing to add, but
>
> On 06/18, Andy Lutomirski wrote:
>>
>> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
>> regno, u32 value)
>>   R32(esp, sp);
>>
>>   case offsetof(struct user32, regs.orig_eax):
>> - /*
>> -  * A 32-bit debugger setting orig_eax means to restore
>> -  * the state of the task restarting a 32-bit syscall.
>> -  * Make sure we interpret the -ERESTART* codes correctly
>> -  * in case the task is not actually still sitting at the
>> -  * exit from a 32-bit syscall with TS_COMPAT still set.
>> -  */
>>   regs->orig_ax = value;
>> - if (syscall_get_nr(child, regs) >= 0)
>> - task_thread_info(child)->status |= TS_COMPAT;
>
> I agree it would be nice to remove this code, but then it is not clear
> how/when we should sign-extend regs->ax..
>
> And this leads to another question, why do we actually need to set/clear
> TS_COMPAT in set_personality_ia32() ??

I have no idea.  Legacy junk?  Maybe so audit sees execution of a
64-bit task as a 64-bit sys_execve return even if the task was 32-bit
before execve?

--Andy


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Oleg Nesterov
Let me first thank Pedro who has already replied!

And I have to admit I will need to re-read his explanations after
sleep to (try to) convince myself I fully understans the problems ;)
Too late for me.

Right now I have nothing to add, but

On 06/18, Andy Lutomirski wrote:
>
> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
> regno, u32 value)
>   R32(esp, sp);
>  
>   case offsetof(struct user32, regs.orig_eax):
> - /*
> -  * A 32-bit debugger setting orig_eax means to restore
> -  * the state of the task restarting a 32-bit syscall.
> -  * Make sure we interpret the -ERESTART* codes correctly
> -  * in case the task is not actually still sitting at the
> -  * exit from a 32-bit syscall with TS_COMPAT still set.
> -  */
>   regs->orig_ax = value;
> - if (syscall_get_nr(child, regs) >= 0)
> - task_thread_info(child)->status |= TS_COMPAT;

I agree it would be nice to remove this code, but then it is not clear
how/when we should sign-extend regs->ax..

And this leads to another question, why do we actually need to set/clear
TS_COMPAT in set_personality_ia32() ??

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Oleg Nesterov
Let me first thank Pedro who has already replied!

And I have to admit I will need to re-read his explanations after
sleep to (try to) convince myself I fully understans the problems ;)
Too late for me.

Right now I have nothing to add, but

On 06/18, Andy Lutomirski wrote:
>
> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
> regno, u32 value)
>   R32(esp, sp);
>  
>   case offsetof(struct user32, regs.orig_eax):
> - /*
> -  * A 32-bit debugger setting orig_eax means to restore
> -  * the state of the task restarting a 32-bit syscall.
> -  * Make sure we interpret the -ERESTART* codes correctly
> -  * in case the task is not actually still sitting at the
> -  * exit from a 32-bit syscall with TS_COMPAT still set.
> -  */
>   regs->orig_ax = value;
> - if (syscall_get_nr(child, regs) >= 0)
> - task_thread_info(child)->status |= TS_COMPAT;

I agree it would be nice to remove this code, but then it is not clear
how/when we should sign-extend regs->ax..

And this leads to another question, why do we actually need to set/clear
TS_COMPAT in set_personality_ia32() ??

Oleg.



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Andy Lutomirski
On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  wrote:
> On Jun 18, 2016 6:56 AM, "Pedro Alves"  wrote:
>>
>> On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
>> > A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
>> >
>> > - If the tracee is stopped in a 32-bit syscall, this has no effect
>> >   as TS_COMPAT will already be set.
>> >
>> > - If the tracee is stopped on entry to a 64-bit syscall, this could
>> >   cause problems: in_compat_syscall() etc will be out of sync with
>> >   the actual syscall table in use.  I can imagine this bre aking
>> >   audit.  (It can't meaningfully break seccomp, as a malicious
>> >   tracer can already fully bypass seccomp.)  I could also imagine it
>> >   subtly confusing the implementations of a few syscalls.
>> >
>> >  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>> >will end up set in user mode, which isn't supposed to happen.  The 
>> > results
>> >are likely to be similar to the 64-bit syscall entry case.
>> >
>> > Fix it by deleting the code.
>> >
>> > Here's my understanding of the previous intent.  Suppose a
>> > 32-bit tracee makes a syscall that returns one of the -ERESTART
>> > codes.  A 32-bit tracer saves away its register state.  The tracee
>> > resumes, returns from the system call, and gets stopped again for a
>> > non-syscall reason (e.g. a signal).  Then the tracer tries to roll
>> > back the tracee's state by writing all of the saved registers back.
>> >
>> > The result of this sequence of events will be that the tracee's
>> > registers' low bits match what they were at the end of the syscall
>> > but TS_COMPAT will be clear.  This will cause syscall_get_error() to
>> > return a *positive* number, because we zero-extend registers poked
>> > by 32-bit tracers instead of sign-extending them.  As a result, with
>> > this change, syscall restart won't happen, whereas, historically, it
>> > would have happened.
>> >
>> > As far as I can tell, this corner case isn't very important, and I
>>
>> I believe it's actually very much very important for gdb, for restoring
>> the inferior state when the user calls a function in the inferior, with:
>>
>>  (gdb) print foo()
>>
>> Some background here:
>>
>>  
>> http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0
>
> Yuck.  I should have dug in to the history.  Why not just
> unconditionally sign-extend eax when set by a 32-bit tracer?
>
> Do you know how to acquire a copy of erestartsys-trap.c?  The old
> links appear to be broken.
>
> Also, while I have your attention: when gdb restores old state like
> this, does it do it with individual calls to PTRACE_POKEUSER or does
> it use SETREGSET or similar to do it all at once?  I'm asking because
> I have some other code (fsgsbase) that's on hold until I can figure
> out how to keep it from breaking gdb if and when gdb writes to fs and
> fs_base.

OK, I studied this a bit.  What a mess!  Here's what's going on AFAICT:

1. For reasons that probably made sense, the kernel delivers signals
and triggers ptrace before handling syscall restart.  This means that
-ERESTART_RESTARTBLOCK, etc is visible to userspace.  We could
plausibly get away with changing that, but it seems quite risky.

2. As a result of (1), gdb (quite reasonably) expects that it can
snapshot user state on signal delivery, adjust regs to call a
function, and then restore user state.

3. Presumably as a result of (2), we do syscall restart if indicated
by the register state on ptrace resume even if we're *not* resuming a
syscall.

4. Also as a result of (1), gdb expects that writing -1 to orig_eax
via POKEUSER or similar will *disable* syscall restart, which is
necessary to get function calling on syscall exit to work.

The combination of (1) and (4) means that we need to skip syscall
restart if orig_eax == -1 (in a 32-bit signed sense).  The combination
of (1) and (2) means that we need to enable syscall restart if
orig_eax > 0 (in a 32-bit signed sense) and eax contains a
-ERESTARTxyz code (again in a signed sense).  And, for extra fun, we
need to make sure that, if we set __NR_restart_syscall, we set the
correct value based on the syscall that we're restarting.

The latter bit is a mess and is probably broken on current kernels for
64-bit gdb attached to a 32-bit process.  (Is it?  All of this stuff
is a bit of a pain to test.)

Here's my proposal:

Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
etc.  Clear it in do_signal.  This gets rid of the arch confusion
while (hopefully) preserving current behavior.

Step 2: Optionally, for 4.8, consider cleaning up the whole mess.
First, change putreg32 to sign-extend orig_eax and eax and just get
rid of the TS_COMPAT checks in syscall_get_nr and syscall_get_error.
Then we either change the 64-bit -ERESTART_BLOCK to a different number
or 

Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-19 Thread Andy Lutomirski
On Sat, Jun 18, 2016 at 10:02 AM, Andy Lutomirski  wrote:
> On Jun 18, 2016 6:56 AM, "Pedro Alves"  wrote:
>>
>> On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
>> > A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
>> >
>> > - If the tracee is stopped in a 32-bit syscall, this has no effect
>> >   as TS_COMPAT will already be set.
>> >
>> > - If the tracee is stopped on entry to a 64-bit syscall, this could
>> >   cause problems: in_compat_syscall() etc will be out of sync with
>> >   the actual syscall table in use.  I can imagine this bre aking
>> >   audit.  (It can't meaningfully break seccomp, as a malicious
>> >   tracer can already fully bypass seccomp.)  I could also imagine it
>> >   subtly confusing the implementations of a few syscalls.
>> >
>> >  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>> >will end up set in user mode, which isn't supposed to happen.  The 
>> > results
>> >are likely to be similar to the 64-bit syscall entry case.
>> >
>> > Fix it by deleting the code.
>> >
>> > Here's my understanding of the previous intent.  Suppose a
>> > 32-bit tracee makes a syscall that returns one of the -ERESTART
>> > codes.  A 32-bit tracer saves away its register state.  The tracee
>> > resumes, returns from the system call, and gets stopped again for a
>> > non-syscall reason (e.g. a signal).  Then the tracer tries to roll
>> > back the tracee's state by writing all of the saved registers back.
>> >
>> > The result of this sequence of events will be that the tracee's
>> > registers' low bits match what they were at the end of the syscall
>> > but TS_COMPAT will be clear.  This will cause syscall_get_error() to
>> > return a *positive* number, because we zero-extend registers poked
>> > by 32-bit tracers instead of sign-extending them.  As a result, with
>> > this change, syscall restart won't happen, whereas, historically, it
>> > would have happened.
>> >
>> > As far as I can tell, this corner case isn't very important, and I
>>
>> I believe it's actually very much very important for gdb, for restoring
>> the inferior state when the user calls a function in the inferior, with:
>>
>>  (gdb) print foo()
>>
>> Some background here:
>>
>>  
>> http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0
>
> Yuck.  I should have dug in to the history.  Why not just
> unconditionally sign-extend eax when set by a 32-bit tracer?
>
> Do you know how to acquire a copy of erestartsys-trap.c?  The old
> links appear to be broken.
>
> Also, while I have your attention: when gdb restores old state like
> this, does it do it with individual calls to PTRACE_POKEUSER or does
> it use SETREGSET or similar to do it all at once?  I'm asking because
> I have some other code (fsgsbase) that's on hold until I can figure
> out how to keep it from breaking gdb if and when gdb writes to fs and
> fs_base.

OK, I studied this a bit.  What a mess!  Here's what's going on AFAICT:

1. For reasons that probably made sense, the kernel delivers signals
and triggers ptrace before handling syscall restart.  This means that
-ERESTART_RESTARTBLOCK, etc is visible to userspace.  We could
plausibly get away with changing that, but it seems quite risky.

2. As a result of (1), gdb (quite reasonably) expects that it can
snapshot user state on signal delivery, adjust regs to call a
function, and then restore user state.

3. Presumably as a result of (2), we do syscall restart if indicated
by the register state on ptrace resume even if we're *not* resuming a
syscall.

4. Also as a result of (1), gdb expects that writing -1 to orig_eax
via POKEUSER or similar will *disable* syscall restart, which is
necessary to get function calling on syscall exit to work.

The combination of (1) and (4) means that we need to skip syscall
restart if orig_eax == -1 (in a 32-bit signed sense).  The combination
of (1) and (2) means that we need to enable syscall restart if
orig_eax > 0 (in a 32-bit signed sense) and eax contains a
-ERESTARTxyz code (again in a signed sense).  And, for extra fun, we
need to make sure that, if we set __NR_restart_syscall, we set the
correct value based on the syscall that we're restarting.

The latter bit is a mess and is probably broken on current kernels for
64-bit gdb attached to a 32-bit process.  (Is it?  All of this stuff
is a bit of a pain to test.)

Here's my proposal:

Step 1: for 4.7 and for -stable, introduce TS_I386_REGS_POKED.  Set it
in putreg32.  Use it in syscall_get_error, get_nr_restart_syscall,
etc.  Clear it in do_signal.  This gets rid of the arch confusion
while (hopefully) preserving current behavior.

Step 2: Optionally, for 4.8, consider cleaning up the whole mess.
First, change putreg32 to sign-extend orig_eax and eax and just get
rid of the TS_COMPAT checks in syscall_get_nr and syscall_get_error.
Then we either change the 64-bit -ERESTART_BLOCK to a different number
or encode the desired restart bitness in 

Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Kees Cook
On Sat, Jun 18, 2016 at 3:21 AM, Andy Lutomirski  wrote:
> A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
>
> - If the tracee is stopped in a 32-bit syscall, this has no effect
>   as TS_COMPAT will already be set.
>
> - If the tracee is stopped on entry to a 64-bit syscall, this could
>   cause problems: in_compat_syscall() etc will be out of sync with
>   the actual syscall table in use.  I can imagine this bre aking
>   audit.  (It can't meaningfully break seccomp, as a malicious
>   tracer can already fully bypass seccomp.)  I could also imagine it
>   subtly confusing the implementations of a few syscalls.
>
>  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>will end up set in user mode, which isn't supposed to happen.  The results
>are likely to be similar to the 64-bit syscall entry case.
>
> Fix it by deleting the code.
>
> Here's my understanding of the previous intent.  Suppose a
> 32-bit tracee makes a syscall that returns one of the -ERESTART
> codes.  A 32-bit tracer saves away its register state.  The tracee
> resumes, returns from the system call, and gets stopped again for a
> non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> back the tracee's state by writing all of the saved registers back.
>
> The result of this sequence of events will be that the tracee's
> registers' low bits match what they were at the end of the syscall
> but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> return a *positive* number, because we zero-extend registers poked
> by 32-bit tracers instead of sign-extending them.  As a result, with
> this change, syscall restart won't happen, whereas, historically, it
> would have happened.
>
> As far as I can tell, this corner case isn't very important, and I
> also don't see how one would reasonably have triggered it in the
> first place.  In particular, syscall restart happens before ptrace
> hooks in the syscall exit path, so a tracer should never see the
> problematic pre-restart syscall state in the first place.
>
> Signed-off-by: Andy Lutomirski 
> ---
>
> Oleg, you often have good insight into ptrace oddities.  Do you think I'm
> correct that this can safely be deleted?
>
> Kees, I think that either this or a similar fix is important to make the
> seccomp reordering series be fully effective.

For good measure, just to repeat what I said in the other thread:
yeah, this TS_COMPAT injection needs to be fixed, though I don't view
it as critical for seccomp since the major bypass situation will be
fixed already. The TS_COMPAT interaction isn't bad (since the arch
state is saved before the seccomp calls), but it can confuse a filter
intentionally trying to hit this bug via RET_SECCOMP_TRACE, but then
it would only be a problem for a filter that was either ignoring arch
tests or doing biarch filtering, which is extremely uncommon.

-Kees

>
> Ingo, this is intended for x86/urgent.  I deliberately didn't cc stable,
> as the bug this fixes seems minor enough that I think we can wait a while
> to backport it.
>
> arch/x86/kernel/ptrace.c | 9 -
>  1 file changed, 9 deletions(-)
>
> diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
> index 600edd225e81..bde57caf9aa9 100644
> --- a/arch/x86/kernel/ptrace.c
> +++ b/arch/x86/kernel/ptrace.c
> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
> regno, u32 value)
> R32(esp, sp);
>
> case offsetof(struct user32, regs.orig_eax):
> -   /*
> -* A 32-bit debugger setting orig_eax means to restore
> -* the state of the task restarting a 32-bit syscall.
> -* Make sure we interpret the -ERESTART* codes correctly
> -* in case the task is not actually still sitting at the
> -* exit from a 32-bit syscall with TS_COMPAT still set.
> -*/
> regs->orig_ax = value;
> -   if (syscall_get_nr(child, regs) >= 0)
> -   task_thread_info(child)->status |= TS_COMPAT;
> break;
>
> case offsetof(struct user32, regs.eflags):
> --
> 2.7.4
>



-- 
Kees Cook
Chrome OS & Brillo Security


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Kees Cook
On Sat, Jun 18, 2016 at 3:21 AM, Andy Lutomirski  wrote:
> A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
>
> - If the tracee is stopped in a 32-bit syscall, this has no effect
>   as TS_COMPAT will already be set.
>
> - If the tracee is stopped on entry to a 64-bit syscall, this could
>   cause problems: in_compat_syscall() etc will be out of sync with
>   the actual syscall table in use.  I can imagine this bre aking
>   audit.  (It can't meaningfully break seccomp, as a malicious
>   tracer can already fully bypass seccomp.)  I could also imagine it
>   subtly confusing the implementations of a few syscalls.
>
>  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>will end up set in user mode, which isn't supposed to happen.  The results
>are likely to be similar to the 64-bit syscall entry case.
>
> Fix it by deleting the code.
>
> Here's my understanding of the previous intent.  Suppose a
> 32-bit tracee makes a syscall that returns one of the -ERESTART
> codes.  A 32-bit tracer saves away its register state.  The tracee
> resumes, returns from the system call, and gets stopped again for a
> non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> back the tracee's state by writing all of the saved registers back.
>
> The result of this sequence of events will be that the tracee's
> registers' low bits match what they were at the end of the syscall
> but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> return a *positive* number, because we zero-extend registers poked
> by 32-bit tracers instead of sign-extending them.  As a result, with
> this change, syscall restart won't happen, whereas, historically, it
> would have happened.
>
> As far as I can tell, this corner case isn't very important, and I
> also don't see how one would reasonably have triggered it in the
> first place.  In particular, syscall restart happens before ptrace
> hooks in the syscall exit path, so a tracer should never see the
> problematic pre-restart syscall state in the first place.
>
> Signed-off-by: Andy Lutomirski 
> ---
>
> Oleg, you often have good insight into ptrace oddities.  Do you think I'm
> correct that this can safely be deleted?
>
> Kees, I think that either this or a similar fix is important to make the
> seccomp reordering series be fully effective.

For good measure, just to repeat what I said in the other thread:
yeah, this TS_COMPAT injection needs to be fixed, though I don't view
it as critical for seccomp since the major bypass situation will be
fixed already. The TS_COMPAT interaction isn't bad (since the arch
state is saved before the seccomp calls), but it can confuse a filter
intentionally trying to hit this bug via RET_SECCOMP_TRACE, but then
it would only be a problem for a filter that was either ignoring arch
tests or doing biarch filtering, which is extremely uncommon.

-Kees

>
> Ingo, this is intended for x86/urgent.  I deliberately didn't cc stable,
> as the bug this fixes seems minor enough that I think we can wait a while
> to backport it.
>
> arch/x86/kernel/ptrace.c | 9 -
>  1 file changed, 9 deletions(-)
>
> diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
> index 600edd225e81..bde57caf9aa9 100644
> --- a/arch/x86/kernel/ptrace.c
> +++ b/arch/x86/kernel/ptrace.c
> @@ -922,16 +922,7 @@ static int putreg32(struct task_struct *child, unsigned 
> regno, u32 value)
> R32(esp, sp);
>
> case offsetof(struct user32, regs.orig_eax):
> -   /*
> -* A 32-bit debugger setting orig_eax means to restore
> -* the state of the task restarting a 32-bit syscall.
> -* Make sure we interpret the -ERESTART* codes correctly
> -* in case the task is not actually still sitting at the
> -* exit from a 32-bit syscall with TS_COMPAT still set.
> -*/
> regs->orig_ax = value;
> -   if (syscall_get_nr(child, regs) >= 0)
> -   task_thread_info(child)->status |= TS_COMPAT;
> break;
>
> case offsetof(struct user32, regs.eflags):
> --
> 2.7.4
>



-- 
Kees Cook
Chrome OS & Brillo Security


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Andy Lutomirski
On Jun 18, 2016 6:56 AM, "Pedro Alves"  wrote:
>
> On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
> > A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
> >
> > - If the tracee is stopped in a 32-bit syscall, this has no effect
> >   as TS_COMPAT will already be set.
> >
> > - If the tracee is stopped on entry to a 64-bit syscall, this could
> >   cause problems: in_compat_syscall() etc will be out of sync with
> >   the actual syscall table in use.  I can imagine this bre aking
> >   audit.  (It can't meaningfully break seccomp, as a malicious
> >   tracer can already fully bypass seccomp.)  I could also imagine it
> >   subtly confusing the implementations of a few syscalls.
> >
> >  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
> >will end up set in user mode, which isn't supposed to happen.  The 
> > results
> >are likely to be similar to the 64-bit syscall entry case.
> >
> > Fix it by deleting the code.
> >
> > Here's my understanding of the previous intent.  Suppose a
> > 32-bit tracee makes a syscall that returns one of the -ERESTART
> > codes.  A 32-bit tracer saves away its register state.  The tracee
> > resumes, returns from the system call, and gets stopped again for a
> > non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> > back the tracee's state by writing all of the saved registers back.
> >
> > The result of this sequence of events will be that the tracee's
> > registers' low bits match what they were at the end of the syscall
> > but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> > return a *positive* number, because we zero-extend registers poked
> > by 32-bit tracers instead of sign-extending them.  As a result, with
> > this change, syscall restart won't happen, whereas, historically, it
> > would have happened.
> >
> > As far as I can tell, this corner case isn't very important, and I
>
> I believe it's actually very much very important for gdb, for restoring
> the inferior state when the user calls a function in the inferior, with:
>
>  (gdb) print foo()
>
> Some background here:
>
>  
> http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0

Yuck.  I should have dug in to the history.  Why not just
unconditionally sign-extend eax when set by a 32-bit tracer?

Do you know how to acquire a copy of erestartsys-trap.c?  The old
links appear to be broken.

Also, while I have your attention: when gdb restores old state like
this, does it do it with individual calls to PTRACE_POKEUSER or does
it use SETREGSET or similar to do it all at once?  I'm asking because
I have some other code (fsgsbase) that's on hold until I can figure
out how to keep it from breaking gdb if and when gdb writes to fs and
fs_base.


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Andy Lutomirski
On Jun 18, 2016 6:56 AM, "Pedro Alves"  wrote:
>
> On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
> > A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
> >
> > - If the tracee is stopped in a 32-bit syscall, this has no effect
> >   as TS_COMPAT will already be set.
> >
> > - If the tracee is stopped on entry to a 64-bit syscall, this could
> >   cause problems: in_compat_syscall() etc will be out of sync with
> >   the actual syscall table in use.  I can imagine this bre aking
> >   audit.  (It can't meaningfully break seccomp, as a malicious
> >   tracer can already fully bypass seccomp.)  I could also imagine it
> >   subtly confusing the implementations of a few syscalls.
> >
> >  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
> >will end up set in user mode, which isn't supposed to happen.  The 
> > results
> >are likely to be similar to the 64-bit syscall entry case.
> >
> > Fix it by deleting the code.
> >
> > Here's my understanding of the previous intent.  Suppose a
> > 32-bit tracee makes a syscall that returns one of the -ERESTART
> > codes.  A 32-bit tracer saves away its register state.  The tracee
> > resumes, returns from the system call, and gets stopped again for a
> > non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> > back the tracee's state by writing all of the saved registers back.
> >
> > The result of this sequence of events will be that the tracee's
> > registers' low bits match what they were at the end of the syscall
> > but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> > return a *positive* number, because we zero-extend registers poked
> > by 32-bit tracers instead of sign-extending them.  As a result, with
> > this change, syscall restart won't happen, whereas, historically, it
> > would have happened.
> >
> > As far as I can tell, this corner case isn't very important, and I
>
> I believe it's actually very much very important for gdb, for restoring
> the inferior state when the user calls a function in the inferior, with:
>
>  (gdb) print foo()
>
> Some background here:
>
>  
> http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0

Yuck.  I should have dug in to the history.  Why not just
unconditionally sign-extend eax when set by a 32-bit tracer?

Do you know how to acquire a copy of erestartsys-trap.c?  The old
links appear to be broken.

Also, while I have your attention: when gdb restores old state like
this, does it do it with individual calls to PTRACE_POKEUSER or does
it use SETREGSET or similar to do it all at once?  I'm asking because
I have some other code (fsgsbase) that's on hold until I can figure
out how to keep it from breaking gdb if and when gdb writes to fs and
fs_base.


Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Pedro Alves
On 06/18/2016 02:55 PM, Pedro Alves wrote:

> This hunk being mentioned in this thread a couple years ago too:
> 
>  https://www.sourceware.org/ml/gdb/2014-04/msg00095.html
> 
> Please don't break this use case ( and fix the one reported in
> that thread :-) ).

BTW, there was a follow up v2 patch to that last url, here:

 [PATCH v2] Fix get ERESTARTSYS with m32 in x86_64 when debug by GDB
 https://sourceware.org/ml/gdb/2014-05/msg4.html

(for some reason, I can only find the ping on the lkml, not the
 original post, though it was apparently CCed.)

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Pedro Alves
On 06/18/2016 02:55 PM, Pedro Alves wrote:

> This hunk being mentioned in this thread a couple years ago too:
> 
>  https://www.sourceware.org/ml/gdb/2014-04/msg00095.html
> 
> Please don't break this use case ( and fix the one reported in
> that thread :-) ).

BTW, there was a follow up v2 patch to that last url, here:

 [PATCH v2] Fix get ERESTARTSYS with m32 in x86_64 when debug by GDB
 https://sourceware.org/ml/gdb/2014-05/msg4.html

(for some reason, I can only find the ping on the lkml, not the
 original post, though it was apparently CCed.)

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Pedro Alves
On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
> A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
> 
> - If the tracee is stopped in a 32-bit syscall, this has no effect
>   as TS_COMPAT will already be set.
> 
> - If the tracee is stopped on entry to a 64-bit syscall, this could
>   cause problems: in_compat_syscall() etc will be out of sync with
>   the actual syscall table in use.  I can imagine this bre aking
>   audit.  (It can't meaningfully break seccomp, as a malicious
>   tracer can already fully bypass seccomp.)  I could also imagine it
>   subtly confusing the implementations of a few syscalls.
> 
>  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>will end up set in user mode, which isn't supposed to happen.  The results
>are likely to be similar to the 64-bit syscall entry case.
> 
> Fix it by deleting the code.
> 
> Here's my understanding of the previous intent.  Suppose a
> 32-bit tracee makes a syscall that returns one of the -ERESTART
> codes.  A 32-bit tracer saves away its register state.  The tracee
> resumes, returns from the system call, and gets stopped again for a
> non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> back the tracee's state by writing all of the saved registers back.
> 
> The result of this sequence of events will be that the tracee's
> registers' low bits match what they were at the end of the syscall
> but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> return a *positive* number, because we zero-extend registers poked
> by 32-bit tracers instead of sign-extending them.  As a result, with
> this change, syscall restart won't happen, whereas, historically, it
> would have happened.
> 
> As far as I can tell, this corner case isn't very important, and I

I believe it's actually very much very important for gdb, for restoring
the inferior state when the user calls a function in the inferior, with:

 (gdb) print foo()

Some background here:

 
http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0

This hunk being mentioned in this thread a couple years ago too:

 https://www.sourceware.org/ml/gdb/2014-04/msg00095.html

Please don't break this use case ( and fix the one reported in
that thread :-) ).

Thanks,
Pedro Alves



Re: [PATCH] x86/ptrace: Remove questionable TS_COMPAT usage in ptrace

2016-06-18 Thread Pedro Alves
On 06/18/2016 11:21 AM, Andy Lutomirski wrote:
> A 32-bit tracer can set a tracee's TS_COMPAT flag by poking orig_ax.
> 
> - If the tracee is stopped in a 32-bit syscall, this has no effect
>   as TS_COMPAT will already be set.
> 
> - If the tracee is stopped on entry to a 64-bit syscall, this could
>   cause problems: in_compat_syscall() etc will be out of sync with
>   the actual syscall table in use.  I can imagine this bre aking
>   audit.  (It can't meaningfully break seccomp, as a malicious
>   tracer can already fully bypass seccomp.)  I could also imagine it
>   subtly confusing the implementations of a few syscalls.
> 
>  - If the tracee is stopped in a non-syscall context, then TS_COMPAT
>will end up set in user mode, which isn't supposed to happen.  The results
>are likely to be similar to the 64-bit syscall entry case.
> 
> Fix it by deleting the code.
> 
> Here's my understanding of the previous intent.  Suppose a
> 32-bit tracee makes a syscall that returns one of the -ERESTART
> codes.  A 32-bit tracer saves away its register state.  The tracee
> resumes, returns from the system call, and gets stopped again for a
> non-syscall reason (e.g. a signal).  Then the tracer tries to roll
> back the tracee's state by writing all of the saved registers back.
> 
> The result of this sequence of events will be that the tracee's
> registers' low bits match what they were at the end of the syscall
> but TS_COMPAT will be clear.  This will cause syscall_get_error() to
> return a *positive* number, because we zero-extend registers poked
> by 32-bit tracers instead of sign-extending them.  As a result, with
> this change, syscall restart won't happen, whereas, historically, it
> would have happened.
> 
> As far as I can tell, this corner case isn't very important, and I

I believe it's actually very much very important for gdb, for restoring
the inferior state when the user calls a function in the inferior, with:

 (gdb) print foo()

Some background here:

 
http://linux-kernel.vger.kernel.narkive.com/fqrh4xKK/patch-x86-ptrace-sign-extend-eax-with-orig-eax-0

This hunk being mentioned in this thread a couple years ago too:

 https://www.sourceware.org/ml/gdb/2014-04/msg00095.html

Please don't break this use case ( and fix the one reported in
that thread :-) ).

Thanks,
Pedro Alves