(~amd64 packages, development reference policy) LVM does not quite function out of the box in an enforcing environment. Some work needs to be done. NOTE: I don't have a Gentoo clustered filesystem testing environment to test this with. Ten to one says it will be broken in a different, more interesting, way (along with a bunch of other things). But that's life. 1) /run/lvmetad.pid doesn't have a default context. Not major, but I'm in a fixing mood. It now gets the proper lvm_var_run_t context it deserves. 2) /run/lvm/lvmetad.socket needs to be usable. In enforcing mode, you will see something like this: # run_init service lvm restart Authenticating root. * Shutting down the Logical Volume Manager * Shutting Down LVs & VGs ... /run/lvm/lvmetad.socket: connect failed: Permission denied WARNING: Failed to connect to lvmetad. Falling back to internal scanning. With the requisite avc denials. This is because the lvm userspace tools interact via the lvm UNIX socket. This is very, very important in environments where you are clustering LVM. A bit less so on a local machine, but it still needs to be done right. 3) /sbin/lvmetad is not labeled correctly It is getting bin_t which is preventing it from running under lvm_t and setting up the correct socket permissions. 4) etc, I lost track while fixing denials. Reproducible: Always
So this patch is a bit big and disruptive to the existing selinux LVM ecosystem. The tl;dr is that LVM now runs under its' own domain (before it was running under "whatever"), which has an interface designed for access to it. The interface is attached to the sysadm role as an optional policy. What is tested to be working under full enforce: LVM userspace programs: lvcreate / lvremote / vgchange / vgscan / vgchange / pvscan / pvs / lvs / vgs This includes lvmetad caching everything. LVM init scripts: lvm / lvmetad / lvm-monitoring What I have no ability to test is a doozie: Clustering. LVM locking across a shared volume (eg, an iscsi / san mount) is super important however I can't test this. However my expectation is that it would not function in an enforcing environment *anyway* and this iteration is in a better position to make such a solution work. For a clustering environment I think an interface would have to be setup such that the cman (or whatever) clustering tools can access lvm_t stuff, however I can't test that and it might good enough to just use lvm_admin(). Not sure. But the solution can be extended as needed.
Created attachment 389474 [details, diff] works for me
One more small one, as it turns out cryptsetup runs under the lvm_t domain (why?). I use dmcrypt to mount LUKS encrypted partitions, and this policy needed a few more adjustments in order to make that work. diff --git a/policy/modules/system/lvm.te b/policy/modules/system/lvm.te index d29a22a..88bba35 100644 --- a/policy/modules/system/lvm.te +++ b/policy/modules/system/lvm.te @@ -55,6 +55,9 @@ files_tmp_file(lvm_tmp_t) type lvm_socket_t; files_type(lvm_socket_t) + +allow lvm_t lvm_socket_t:sock_file manage_sock_file_perms; +allow lvm_t self:socket create_socket_perms; stream_connect_pattern(lvm_t, lvm_socket_t, lvm_socket_t, lvm_socket_t) ######################################## Hopefully there won't be any more "...and just one more thing" for a bit.
This policy functions happily under 2.3 userspace.
I'm first going to focus on supporting general constructs that are easy to upstream, and I'll pick around when we get to the more disruptive stuff.
# vgcreate vgtest /dev/mapper/test /etc/lvm/archive: mkdir failed: Permission denied time->Thu Nov 27 21:07:26 2014 type=UNKNOWN[1327] msg=audit(1417122446.005:102): proctitle=766763726561746500766774657374002F6465762F6D61707065722F74657374 type=PATH msg=audit(1417122446.005:102): item=1 name="/etc/lvm/archive" nametype=CREATE type=PATH msg=audit(1417122446.005:102): item=0 name="/etc/lvm/" inode=1966543 dev=fc:03 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:lvm_etc_t:s0 nametype=PARENT type=CWD msg=audit(1417122446.005:102): cwd="/root" type=SYSCALL msg=audit(1417122446.005:102): arch=c000003e syscall=83 success=no exit=-13 a0=2e527afd30 a1=1ff a2=0 a3=2f7eb56f070 items=2 ppid=1238 pid=22863 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=2 comm="vgcreate" exe="/sbin/lvm" subj=root:sysadm_r:lvm_t:s0 key=(null) type=AVC msg=audit(1417122446.005:102): avc: denied { create } for pid=22863 comm="vgcreate" name="archive" scontext=root:sysadm_r:lvm_t:s0 tcontext=root:object_r:lvm_etc_t:s0 tclass=dir permissive=0 create_dirs_pattern(lvm_t, lvm_etc_t, lvm_etc_t)
lvmetad indeed not starting as lvm_t, so ok for file context change. lvmetad wants to create a socket, but fails: time->Thu Nov 27 21:24:47 2014 type=UNKNOWN[1327] msg=audit(1417123487.005:105): proctitle=2F7362696E2F6C766D65746164002D70002F72756E2F6C766D657461642E706964 type=PATH msg=audit(1417123487.005:105): item=2 name=(null) nametype=CREATE type=PATH msg=audit(1417123487.005:105): item=1 name=(null) inode=2347 dev=00:11 mode=040700 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:var_run_t:s0 nametype=PARENT type=PATH msg=audit(1417123487.005:105): item=0 name=(null) inode=2347 dev=00:11 mode=040700 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:var_run_t:s0 nametype=PARENT type=SOCKADDR msg=audit(1417123487.005:105): saddr=01002F72756E2F6C766D2F6C766D657461642E736F636B657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 type=SYSCALL msg=audit(1417123487.005:105): arch=c000003e syscall=49 success=no exit=-13 a0=4 a1=3c33ba330c0 a2=6e a3=292121eb7a items=3 ppid=1456 pid=1457 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=1 comm="lvmetad" exe="/sbin/lvmetad" subj=system_u:system_r:lvm_t:s0 key=(null) type=AVC msg=audit(1417123487.005:105): avc: denied { create } for pid=1457 comm="lvmetad" name="lvmetad.socket" scontext=system_u:system_r:lvm_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0 The policy however already has a file transition in place for lvm_t creating a sock_file in var_run_t to become lvm_var_run_t. The reason that it fails: lvm is SELinux-aware, and forced the context based on the context definitions. Solution: /var/run/lvm(/.*)? is to be marked as lvm_var_run_t. PS It is commonly best practice to use the _var_run_t for sockets (unless there is a clear reason to separate them beyond the fact that they already have different class notations). So no reason to create an lvm_socket_t type.
# run_init rc-service lvm-monitoring start Authenticating root. * Starting dmeventd ... Child exited with code 6 * start-stop-daemon: failed to start `/sbin/dmeventd' [ !! ] * ERROR: dmeventd failed to start * ERROR: cannot start lvm-monitoring as dmeventd would not start In AVC, we see that dmeventd is running in initrc_t domain: time->Thu Nov 27 21:46:56 2014 type=AVC msg=audit(1417124816.885:201): avc: denied { read } for pid=6247 comm="dmeventd" name="file_contexts.subs_dist" dev="vda3" ino=3043391 scontext=system_u:system_r:initrc_t:s0 tcontext=system_u:object_r:file_context_t:s0 tclass=file permissive=0 Marking dmeventd as lvm_exec_t... # run_init rc-service lvm-monitoring start Authenticating root. * Starting dmeventd ... Child exited with code 6 * start-stop-daemon: failed to start `/sbin/dmeventd' [ !! ] * ERROR: dmeventd failed to start * ERROR: cannot start lvm-monitoring as dmeventd would not start time->Thu Nov 27 21:49:02 2014 type=UNKNOWN[1327] msg=audit(1417124942.210:209): proctitle="/sbin/dmeventd" type=PATH msg=audit(1417124942.210:209): item=1 name="/run/dmeventd-client" nametype=CREATE type=PATH msg=audit(1417124942.210:209): item=0 name="/run/" inode=262 dev=00:11 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:var_run_t:s0 nametype=PARENT type=CWD msg=audit(1417124942.210:209): cwd="/" type=SYSCALL msg=audit(1417124942.210:209): arch=c000003e syscall=133 success=no exit=-13 a0=75f5333a02 a1=1180 a2=0 a3=3a745f6e75725f72 items=2 ppid=6277 pid=6278 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=1 comm="dmeventd" exe="/sbin/dmeventd" subj=system_u:system_r:lvm_t:s0 key=(null) type=AVC msg=audit(1417124942.210:209): avc: denied { create } for pid=6278 comm="dmeventd" name="dmeventd-client" scontext=system_u:system_r:lvm_t:s0 tcontext=system_u:object_r:lvm_var_run_t:s0 tclass=fifo_file permissive=0 Granting: manage_fifo_files_pattern(lvm_t, lvm_var_run_t, lvm_var_run_t) # run_init rc-service lvm-monitoring start Authenticating root. * Starting dmeventd ... [ ok ] * Starting LVM monitoring for VGs vgtest: ... 1 logical volume(s) in volume group "vgtest" monitored [ ok ]
Okay, all seems to work with those changes in. Thanks! Is in repo, will be part of r8
r1 is now stable