how does execstack work?

Sebastian Pfaff sebastian.pfaff at gmail.com
Tue Mar 17 16:49:31 UTC 2009


Hello everyone,

1st i'm  relativley new to selinux, so  be patient with me ;). Im  
using Fedora 10. I wrote a small c app:

#include <stdio.h>
/* shellcode calls exit_code(2), see man 2 exit_code */
  void func(int a, int b, int c) {
  int *helper = NULL;
  char buf[] = "\x31\xdb\xb3\x02\x31\xc0\xb0\xfc\xcd\x80";
  helper = (int *)(&helper+2);
  *helper=(int)buf;
}

int main(int c, char **v) {
  func(1, 2, 3);
  return 0;
}

the shellcode executes exit_group(2) with argument 2 (like  
exit_group(2)). Shellcode works as expected. I tested it on several  
systems. The shellcode will run in the stack region of the process.  
helper = (int *)(&helper+2); will overwrite the saved instrucion  
pointer (return address), so the process will continue execution at  
address of local variable buf (which is saved on stack). Program was  
compiled with: gcc -Xlinker -v -Xlinker execstack -o shellcode_str  
shellcode_str.c
Here the commands:
[root at SecLab student]# gcc -Xlinker -z -Xlinker execstack  
shellcode_str.c -o shellcode_str
[root at SecLab student]# chcon -t vul_exec_t shellcode_str
[root at SecLab student]# ls -Z shellcode_str
-rwxrwxr-x  root root unconfined_u:object_r:vul_exec_t:s0 shellcode_str

(i i did a chcon -t vul_exec_t shellcode_str, so excutable  
shellcode_str is labled correctly)
Please note that shellscript will run in domain vul_t.
My te file (vul.te):
## <summary>confines vul</summary>

policy_module(vul,0.0.6)

require { type unconfined_t; }
role unconfined_r types vul_t;

########################################
#
# Declarations
#

type vul_t;
domain_type(vul_t)

# Access to shared libraries
libs_use_ld_so(vul_t)
libs_use_shared_libs(vul_t)

type vul_exec_t;
files_type(vul_exec_t)
domain_entry_file(vul_t, vul_exec_t)

domain_auto_transition_pattern(unconfined_t, vul_exec_t, vul_t);
#auditallow unconfined_t self:process execstack;
#auditallow vul_t self:process execstack;

execstack -q says that the executable has an exectcubale stack:
[root at SecLab student]# execstack -q shellcode_str
X shellcode_str

exucting shellcode_str:
[root at SecLab student]# semodule -R
[root at SecLab student]# ./shellcode_str
[root at SecLab student]# echo $?
2

Return value of 2 indicates that shellcode on the stack has been  
executed successfully.
I expected that SELinux will prevent any execution of code on the  
stack. But audit.log shows me nothing like this. Here the audit.log,  
since last reloead:

type=MAC_POLICY_LOAD msg=audit(1237306463.553:2886): policy loaded  
auid=0 ses=133
type=SYSCALL msg=audit(1237306463.553:2886): arch=40000003 syscall=4  
success=yes exit=3470910 a0=4 a1=b7bce000 a2=34f63e a3=bf9330f8  
items=0 ppid=20508 pid=20509 auid
=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0  
ses=133 comm="load_policy" exe="/usr/sbin/load_policy"  
subj=unconfined_u:unconfined_r:load_policy_
t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1237306470.434:2887): avc:  denied  { read write }  
for  pid=20511 comm="shellcode_str" name="0" dev=devpts ino=2  
scontext=unconfined_u:unconfined_r
:vul_t:s0-s0:c0.c1023  
tcontext=unconfined_u:object_r:unconfined_devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1237306470.434:2887): avc:  denied  { read write }  
for  pid=20511 comm="shellcode_str" path="/dev/pts/0" dev=devpts ino=2  
scontext=unconfined_u:unc
onfined_r:vul_t:s0-s0:c0.c1023  
tcontext=unconfined_u:object_r:unconfined_devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1237306470.434:2887): avc:  denied  { read write }  
for  pid=20511 comm="shellcode_str" path="/dev/pts/0" dev=devpts ino=2  
scontext=unconfined_u:unc
onfined_r:vul_t:s0-s0:c0.c1023  
tcontext=unconfined_u:object_r:unconfined_devpts_t:s0 tclass=chr_file
type=AVC msg=audit(1237306470.434:2887): avc:  denied  { read write }  
for  pid=20511 comm="shellcode_str" path="/dev/pts/0" dev=devpts ino=2  
scontext=unconfined_u:unc
onfined_r:vul_t:s0-s0:c0.c1023  
tcontext=unconfined_u:object_r:unconfined_devpts_t:s0 tclass=chr_file
type=SYSCALL msg=audit(1237306470.434:2887): arch=40000003 syscall=11  
per=400000 success=yes exit=0 a0=811b480 a1=8121ca8 a2=8110bc0 a3=0  
items=0 ppid=6574 pid=20511
auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0  
tty=(none) ses=133 comm="shellcode_str" exe="/home/student/ 
shellcode_str" subj=unconfined_u:unconfined_
r:vul_t:s0-s0:c0.c1023 key=(null)

Does SELinux prevent exectution on the stack? If yes, how can i see  
this. It would also be helpful, when i had an example which shows me a  
denial of execstack (searching the log gave no results here). Or is  
something wrong with my example?
I suppose, i have an wrong understanding adout how SELinux execstack  
works. Please help to clarify this.

hope someone can help. tnx in advance.
--
Sebastian Pfaff






More information about the fedora-selinux-list mailing list