Bug 750284

Summary: sVirt allows PROT_EXEC mappings
Product: Red Hat Enterprise Linux 6 Reporter: Avi Kivity <avi>
Component: libvirtAssignee: Jiri Denemark <jdenemar>
Status: CLOSED WORKSFORME QA Contact: Virtualization Bugs <virt-bugs>
Severity: high Docs Contact:
Priority: high    
Version: 6.3CC: acathrow, ajia, dallan, dwalsh, dyuan, gsun, juzhang, knoel, mzhan, rwu
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 760473 (view as bug list) Environment:
Last Closed: 2012-02-01 20:32:29 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On: 760473    
Bug Blocks:    

Description Avi Kivity 2011-10-31 15:09:40 UTC
Description of problem:

sVirt now allows mprotect(..., PROT_EXEC) and mmap(..., PROT_EXEC, ..., -1, ...) (that is, executable anonymous memory).  This allows a vulnerable qemu to be compromised by stuffing the stack with a call to mprotect(), making some guest-controlled memory executable, and then returning to that memory.


Version-Release number of selected component (if applicable):
libvirt-0.9.4-20.el6

How reproducible:
always (if you're incredibly clever)

Steps to Reproduce:
1. Find a vulnerability within qemu
2. Fill some guest memory with stage 2 exploit code
3. Exploit the vulnerability
4. Circumvent PIE/PIC and cause the qemu to return to mprotect(), marking your stage 2 exploit code executable
5. Return to stage 2 exploit code
6. Find another vulnerability in the kernel
7. Get your stage 2 exploit code to exploit this vulnerability
8. Responsible disclosure
9. Submit a paper to Black Hat
  
Actual results:

p0wned

Expected results:

segfault

Additional info:

Please also verify that no file mappings can be made executable, either at mmap() time or via mprotect(); especially for guest controlled files like images, or qcow2 snapshot files.

Comment 6 Jiri Denemark 2011-12-02 14:48:07 UTC
Avi, I don't claim to completely understand this issue, but it seems like there's anything that libvirt could do except for running qemu process with the right SELinux context, which libvirt already does. So IMHO this needs to be handled in SELinux policy. Am I right or did I miss anything?

Comment 7 Avi Kivity 2011-12-05 10:32:42 UTC
Maybe it can be handled fully in the policy; I'm not familiar with it.  But note at least one snag - if you run qemu without kvm, then qemu needs to be able to PROT_EXEC some memory for its translated code.  So libvirt does need to make some differentiation between the two cases.

Comment 8 Jiri Denemark 2011-12-05 14:01:45 UTC
Hmm, this is getting complicated. Daniel, any idea how to solve this without the need to have two SELinux types, one that allows PROT_EXEC and one that denies it? Which would be quite a mess. Something like a per-process boolean (which I doubt it exists) would be great :-)

Comment 9 Daniel Walsh 2011-12-05 20:54:19 UTC
No the way to fix this is to have two different types.

svirt_t and svirt_prot_exec_t or something like that.  They can have the exact same policy except one gets prot_exec and the other does not.  The only problem is how to we tell libvirt which to launch.

Comment 10 Daniel Walsh 2011-12-05 20:55:30 UTC
When I originally designed the policy we had planned on there being multiple types BTW, I had thought at one time we might want to design a type that had no network access or limited network ports.  For example.  But a lot of that responsibility can be better handled by iptables.

Comment 11 Jiri Denemark 2011-12-06 09:41:12 UTC
OK, so it seems it won't be such a big mess then :-) Libvirt will need to decide which of the contexts to use according to domain type qemu/kvm.

Anyway, I'm cloning this BZ to selinux-policy so that an appropriate svirt_* type is created.

Comment 12 Jiri Denemark 2012-01-17 08:58:34 UTC
Avi, did you actually try to reproduce the reported issue? According to Daniel's comment https://bugzilla.redhat.com/show_bug.cgi?id=760473#c6 this seems to be already blocked by current policy for svirt_t.

Comment 13 Jiri Denemark 2012-01-31 22:12:00 UTC
And Fedora bug 785635 confirms that this is indeed blocked (at least in Fedora) since qemu doesn't work because of that. So it seems we should be fine in RHEL as long as we have that policy as we have no qemu. We may need the extra virt type for Fedora/upstream though.

Comment 14 Avi Kivity 2012-02-01 10:58:37 UTC
(In reply to comment #12)
> Avi, did you actually try to reproduce the reported issue? According to
> Daniel's comment https://bugzilla.redhat.com/show_bug.cgi?id=760473#c6 this
> seems to be already blocked by current policy for svirt_t.

I did not, and agree we appear to be protected now.

Comment 15 Jiri Denemark 2012-02-01 20:32:29 UTC
Great, I think we can just close this bug then. More work still needs to be done, but that only affects upstream and it is already tracked by bug 785635.

Comment 16 Dave Allan 2012-02-01 20:54:14 UTC
WORKSFORME I think, but agreed.