Skip to contentSkip to conversation

x86: prevent binaries from making system calls using the wrong syscall interface

PATCH In review Michael Davidson 7 participants 8 messages Aug 7, 2008 – Aug 8, 2008 x86

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 x86: prevent binaries from making system calls using the wrong syscall interface

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

Since the 32 bit and 64 bit system call numbers are different this means that a binary could attempt to obfuscate which system calls it was actually making by using the "wrong" system call interface. In particular, the call to audit_syscall_entry() relies on checking the TIF_IA32 flag to determine whether it is dealing with a 32 or 64 bit system call without regard to the actual type of system call that was made.While this specific issue could be addressed by checking the TS_COMPAT flag in threadinfo_status it seems preferable to simply disallow this situation altogether.

---

arch/x86/ia32/ia32entry.S +8 -0
Index: linux-2.6.26.2/arch/x86/ia32/ia32entry.S
===================================================================
@@ -123,6 +123,8 @@
  	.quad 1b,ia32_badarg
  	.previous	
 	GET_THREAD_INFO(%r10)
+	testl  $_TIF_IA32,threadinfo_flags(%r10)
+	jz     ia32_bad_abi
 	orl    $TS_COMPAT,threadinfo_status(%r10)
 	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	CFI_REMEMBER_STATE
@@ -230,6 +232,8 @@
 	.quad 1b,ia32_badarg
 	.previous	
 	GET_THREAD_INFO(%r10)
+	testl $_TIF_IA32,threadinfo_flags(%r10)
+	jz    ia32_bad_abi
 	orl   $TS_COMPAT,threadinfo_status(%r10)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	CFI_REMEMBER_STATE
@@ -324,6 +328,8 @@
 	   this could be a problem. */
 	SAVE_ARGS 0,0,1
 	GET_THREAD_INFO(%r10)
+	testl $_TIF_IA32,threadinfo_flags(%r10)
+	jz    ia32_bad_abi
 	orl   $TS_COMPAT,threadinfo_status(%r10)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz ia32_tracesys
@@ -347,6 +353,8 @@
 	jmp ia32_do_syscall
 END(ia32_syscall)
 
+ia32_bad_abi:
+	CFI_REMEMBER_STATE
 ia32_badsys:
 	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
arch/x86/kernel/entry_64.S +3 -1
Index: linux-2.6.26.2/arch/x86/kernel/entry_64.S
===================================================================
@@ -244,7 +244,7 @@
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP|_TIF_IA32),threadinfo_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
 	ja badsys
@@ -318,6 +318,8 @@
 
 	/* Do syscall tracing */
 tracesys:			 
+	testl $_TIF_IA32,threadinfo_flags(%rcx)
+	jnz badsys
 	SAVE_REST
 	movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
 	FIXUP_TOP_OF_STACK %rdi
#1 lore raw
Quoted 6 lines

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

I thought this was a feature?

arch/x86/ia32/ia32entry.S line 130

Quoted 13 lines

Index: linux-2.6.26.2/arch/x86/ia32/ia32entry.S
===================================================================

arch/x86/ia32/ia32entry.S +2 -0
@@ -123,6 +123,8 @@
  	.quad 1b,ia32_badarg
  	.previous	
 	GET_THREAD_INFO(%r10)
+	testl  $_TIF_IA32,threadinfo_flags(%r10)
+	jz     ia32_bad_abi
 	orl    $TS_COMPAT,threadinfo_status(%r10)
 	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	CFI_REMEMBER_STATE

...and slowing down all syscalls for this is certainly bad idea.
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#2 lore raw
In reply to Michael Davidson
Quoted 7 lines · Michael Davidson

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

Quoted 9 lines

Since the 32 bit and 64 bit system call numbers are different this means that a binary could attempt to obfuscate which system calls it was actually making by using the "wrong" system call interface. In particular, the call to audit_syscall_entry() relies on checking the TIF_IA32 flag to determine whether it is dealing with a 32 or 64 bit system call without regard to the actual type of system call that was made.While this specific issue could be addressed by checking the TS_COMPAT flag in threadinfo_status it seems preferable to simply disallow this situation altogether.

I asked Andi whether 64-bit processes are allowed to make 32-bit syscalls on May 4 2007, and he stated that yes it's both allowed and supposed to work. (The thread was cc:d to [email protected].)

Quoted 21 lines
arch/x86/ia32/ia32entry.S +4 -0
@@ -123,6 +123,8 @@
  	.quad 1b,ia32_badarg
  	.previous	
 	GET_THREAD_INFO(%r10)
+	testl  $_TIF_IA32,threadinfo_flags(%r10)
+	jz     ia32_bad_abi
 	orl    $TS_COMPAT,threadinfo_status(%r10)
 	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	CFI_REMEMBER_STATE
@@ -230,6 +232,8 @@
 	.quad 1b,ia32_badarg
 	.previous	
 	GET_THREAD_INFO(%r10)
+	testl $_TIF_IA32,threadinfo_flags(%r10)
+	jz    ia32_bad_abi
 	orl   $TS_COMPAT,threadinfo_status(%r10)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	CFI_REMEMBER_STATE

arch/x86/ia32/ia32entry.S line 335

Quoted 8 lines
arch/x86/ia32/ia32entry.S +2 -0
@@ -324,6 +328,8 @@
 	   this could be a problem. */
 	SAVE_ARGS 0,0,1
 	GET_THREAD_INFO(%r10)
+	testl $_TIF_IA32,threadinfo_flags(%r10)
+	jz    ia32_bad_abi
 	orl   $TS_COMPAT,threadinfo_status(%r10)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz ia32_tracesys

Your patch slows down all compat-mode syscalls.

/Mikael

#3 lore raw
In reply to Michael Davidson
Quoted 3 lines

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

What about applications that choose to do this
- Test tools
- Tools where certain interfaces are only available 32bit ?

Quoted 9 lines

Since the 32 bit and 64 bit system call numbers are different this means that a binary could attempt to obfuscate which system calls it was actually making by using the "wrong" system call interface. In particular, the call to audit_syscall_entry() relies on checking the TIF_IA32 flag to determine whether it is dealing with a 32 or 64 bit system call without regard to the actual type of system call that was made.While this specific issue could be addressed by checking the TS_COMPAT flag in threadinfo_status it seems preferable to simply disallow this situation altogether.

That is a significant change of kernel ABI considering it exists just to wallpaper over crappy audit tools.

I'm definitely against that approach.

Alan

#4 lore raw
In reply to Michael Davidson
Quoted 2 lines · On Wed, 6 Aug 2008 17:34:59 -0700 (PDT) [email protected] (Michael Davidson) wrote:

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

since you can have mixed 32 / 64 binaries just fine I don't think your patch is the right thing to do in general.

Signature · 3 lines
If you want to reach me at my work email, use [email protected]
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org
#5 lore raw
In reply to Michael Davidson
Quoted 7 lines · Michael Davidson

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

No. While I'm not sure it's been used, it would definitely be useful to be able to invoke 32-bit int 0x80 syscalls in 64-bit bit process for something like Valgrind.

Issuing 64-bit syscalls from a 32-bit process would be... interesting.

Quoted 7 lines

Since the 32 bit and 64 bit system call numbers are different this means that a binary could attempt to obfuscate which system calls it was actually making by using the "wrong" system call interface. In particular, the call to audit_syscall_entry() relies on checking the TIF_IA32 flag to determine whether it is dealing with a 32 or 64 bit system call without regard to the actual type of system call that was made.

Or just have separate 32-compat vs 64 bit audit paths which can clearly make the distinction.

J

#6 lore raw
In reply to Michael Davidson
Quoted 6 lines · [email protected] (Michael Davidson) writes:

Prevent binaries from making system calls using other than one of the "normal" system call interfaces for that binary type.

Currently there is nothing to prevent 64 bit binaries from attempting to make system calls using the 32 bit system call interfaces and vice versa.

nack. That was allowed intentionally because there are some use cases for 32bit syscalls from 64bit (e.g. 64bit JIT running 32bit executable). I believe it is used in production in a few cases.

Quoted 10 lines

Since the 32 bit and 64 bit system call numbers are different this means that a binary could attempt to obfuscate which system calls it was actually making by using the "wrong" system call interface. In particular, the call to audit_syscall_entry() relies on checking the TIF_IA32 flag to determine whether it is dealing with a 32 or 64 bit system call without regard to the actual type of system call that was made.While this specific issue could be addressed by checking the TS_COMPAT flag in threadinfo_status it seems preferable to simply disallow this situation altogether.

audit is wrong to assume this and should be just fixed

-Andi

#7 lore raw

OK - I did not realize that this was a "feature".

I have already submitted a one line patch to fix the audit path.