Bug 888502 - libvirt doesn't label console, serial sockets
libvirt doesn't label console, serial sockets
Status: CLOSED CURRENTRELEASE
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: selinux-policy (Show other bugs)
7.0
Unspecified Linux
unspecified Severity unspecified
: rc
: ---
Assigned To: Miroslav Grepl
BaseOS QE Security Team
: Reopened
Depends On: 853393
Blocks: 857453
  Show dependency treegraph
 
Reported: 2012-12-18 14:31 EST by Richard W.M. Jones
Modified: 2013-07-30 17:00 EDT (History)
9 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: 853393
Environment:
Last Closed: 2013-07-30 17:00:34 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Richard W.M. Jones 2012-12-18 14:31:17 EST
Somehow this bug is not fixed in RHEL 7, even though I
am using the package:

selinux-policy-3.11.1-63.el7.noarch

and libguestfs is labelling the socket.  Would there be
a reason why svirt_socket_t would not work in RHEL 7?

+++ This bug was initially created as a clone of Bug #853393 +++

Description of problem:

In libguestfs with the libvirt backend we create sockets
to talk to the daemon and console like this:

    <serial type="unix">
      <source mode="connect" path="/tmp/libguestfs3vK8dN/console.sock"/>
      <target port="0"/>
    </serial>
    <channel type="unix">
      <source mode="connect" path="/tmp/libguestfs3vK8dN/guestfsd.sock"/>
      <target type="virtio" name="org.libguestfs.channel.0"/>
    </channel>

where "/tmp/libguestfs3vK8dN" is a temporary directory created
by libguestfs.

Note that these socket files are created by libguestfs.  Qemu has
to connect to them.

libvirt labels most things -- disks, kernel etc -- but it doesn't
label the console socket (and possibly not the virtio socket either,
but see below).  Therefore when SELinux is Enforcing, qemu
cannot connect to the console socket.

If SELinux is Permissive then we get the following AVC:

type=AVC msg=audit(1346412361.391:3414): avc:  denied  { connectto } for  pid=24102 comm="qemu-kvm" path="/tmp/libguestfs3vK8dN/console.sock" scontext=unconfined_u:unconfined_r:svirt_t:s0:c471,c928 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket

[...]

--- Additional comment from Daniel Walsh on 2012-12-07 12:38:37 EST ---

One potential fix for this would be create a new type guestfs_socket_t for the socket and then allow svirt_t to connect to it.

guestfs could do something like the following pseudo code.

getcon(&scon)
con=context_new(scon)
context_set_type(con,"guestfs_socket_t")
setsockcreatecon(context_str(con))
sock = socket()
context_free(con)
freecon(scon)

# cat mypol.te
policy_module(mypol,1.0)
gen_require(`
type svirt_t;
role unconfined_r;
')
type guestfs_socket_t;
role unconfined_r types guestfs_socket_t;

allow svirt_t guestfs_socket_t:unix_stream_socket connectto;

# make -f /usr/share/selinux/devel/Makefile
# semodule -i mypol.pp

--- Additional comment from Daniel Walsh on 2012-12-07 12:39:17 EST ---

Of course we would have to formalize how guestfs gets the name of its socket, if this works...

--- Additional comment from Richard W.M. Jones on 2012-12-11 06:03:44 EST ---

(In reply to comment #16)
> One potential fix for this would be create a new type guestfs_socket_t for
> the socket and then allow svirt_t to connect to it.
> 
> guestfs could do something like the following pseudo code.
> 
> getcon(&scon)
> con=context_new(scon)
> context_set_type(con,"guestfs_socket_t")
> setsockcreatecon(context_str(con))
> sock = socket()
> context_free(con)
> freecon(scon)
> 
> # cat mypol.te
> policy_module(mypol,1.0)
> gen_require(`
> type svirt_t;
> role unconfined_r;
> ')
> type guestfs_socket_t;
> role unconfined_r types guestfs_socket_t;
> 
> allow svirt_t guestfs_socket_t:unix_stream_socket connectto;
> 
> # make -f /usr/share/selinux/devel/Makefile
> # semodule -i mypol.pp

I added all of this to libguestfs.  The setsockcreatecon
call is fine, but the subsequent socket call fails with -EPERM:

libguestfs: error: socket: Permission denied

and this AVC:

type=SYSCALL msg=audit(11/12/12 10:43:55.237:2060) : arch=x86_64 syscall=socket success=no exit=-13(Permission denied) a0=local a1=SOCK_STREAM|SOCK_CLOEXEC a2=ip a3=0x7fff6702d380 items=0 ppid=26899 pid=26957 auid=rjones uid=rjones gid=rjones euid=rjones suid=rjones fsuid=rjones egid=rjones sgid=rjones fsgid=rjones tty=pts3 ses=2 comm=lt-libguestfs-t exe=/home/rjones/d/libguestfs/test-tool/.libs/lt-libguestfs-test-tool subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) 
type=AVC msg=audit(11/12/12 10:43:55.237:2060) : avc:  denied  { create } for  pid=26957 comm=lt-libguestfs-t scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:guestfs_socket_t:s0-s0:c0.c1023 tclass=unix_stream_socket 

To cut a long story short, I updated the policy until I finally
got everything working.  Here is my updated policy:

---------------------------------------------
policy_module(mypol,1.0)
gen_require(`
type svirt_t;
type unconfined_t;
type svirt_image_t;
role unconfined_r;
')
type guestfs_socket_t;
role unconfined_r types guestfs_socket_t;

allow svirt_t guestfs_socket_t:unix_stream_socket connectto;

# necessary, but why??? - maybe a bug in libvirt labelling code?
allow svirt_t svirt_image_t:sock_file write;

allow unconfined_t guestfs_socket_t:unix_stream_socket { create bind listen accept write read };
---------------------------------------------

(In reply to comment #17)
> Of course we would have to formalize how guestfs gets the name of its
> socket, if this works...

Why can't we just create sockets in our tmpdir and label them?  I'm quite
happy to add this setsockcreatecon call to libguestfs, and continuing
to use /tmp means (a) we don't have to make invasive changes to the
code to create a third temporary location, (b) we don't have to worry
about naming issues, and (c) the sockets will get cleaned up automatically
(if we fail to) by the tmp cleaner.  This seems a much better solution
all round.

--- Additional comment from Richard W.M. Jones on 2012-12-11 06:04:47 EST ---

Created attachment 661371 [details]
0001-launch-libvirt-Label-sockets-with-guestfs_socket_t-R.patch

Proposed labelling patch for libguestfs.

--- Additional comment from Daniel Walsh on 2012-12-11 14:42:10 EST ---

I changed to use svirt_socket_t rather then guestfs_socket_t so this solution could be generalized.  selinux-policy-3.11.1-63.fc18 will include this policy.

Way back when we created svirt we created virtual_domain_context without using named value pairs.

cat /etc/selinux/targeted/contexts/virtual_domain_context 
system_u:system_r:svirt_t:s0

for lxc we have fixed this.

cat /etc/selinux/targeted/contexts/lxc_contexts 
process = "system_u:system_r:svirt_lxc_net_t:s0"
file = "system_u:object_r:svirt_lxc_file_t:s0"
content = "system_u:object_r:virt_var_lib_t:s0"


So currently we have no good way of allowing the polciy writer to establish the svirt_socket_t so that libguest could discover it. I am not thrilled with hard coding it, although it will probably always be there.

[...]

Note You need to log in before you can comment on or make changes to this bug.