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@SecLab student]# gcc -Xlinker -z -Xlinker execstack shellcode_str.c -o shellcode_str [root@SecLab student]# chcon -t vul_exec_t shellcode_str [root@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@SecLab student]# execstack -q shellcode_str X shellcode_str
exucting shellcode_str: [root@SecLab student]# semodule -R [root@SecLab student]# ./shellcode_str [root@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
On Tue, 2009-03-17 at 17:49 +0100, Sebastian Pfaff wrote:
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.
The SELinux execstack check only comes into play if the process calls mprotect(...PROT_EXEC...) on the stack. It is just a policy control over the ability of the process to mark its stack executable. If the program was marked as requiring an executable stack, then that won't ever happen - the kernel will set it up accordingly from the beginning.
http://people.redhat.com/drepper/selinux-mem.html
selinux@lists.fedoraproject.org