Bug 1814052

Summary: user_u and staff_u users cannot read memfds from cockpit-session
Product: [Fedora] Fedora Reporter: Martin Pitt <mpitt>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: 31CC: dwalsh, grepl.miroslav, lvrabec, plautrba, vmojzis, zpytela
Target Milestone: ---Keywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-07-17 13:39:06 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Martin Pitt 2020-03-16 21:18:36 UTC
Description of problem: We are currently trying [1] to implement some functionality to cockpit for passing failed login (btmp) data in a sealed memfd (cockpit_tmpfs_t) from cockpit-session (suid root helper, doing PAM, cockpit_session_t) through cockpit's web server (running as unprivileged system user, cockpit_ws_t) to the target user session in cockpit-bridge (running as part of the user session).

This works fine for unconfined_u and sysadm_u users, but not for the more restricted user_u and staff_u. In that case, cockpit-bridge just gets a bogus fd that is essentially /dev/null and complains.

I think that /dev/null thing comes from the kernel's flush_unauthorized_files(), which replaces any open fd with a forbidden type with a /dev/null fd. But even though cockpit.te [3] has zero "dontaudit" rules, there is absolutely no kernel/audit/other journal message about this, which makes this frustratingly hard (even getting to this point has sunken several work days).

I take it we somehow need to extend the policy to allow user_t/staff_t to read (and possibly getattr) cockpit_tmp_t files. I tried to create a local policy that has just about any possible combination of domains that I can imagine:

--------- 8< /tmp/local.e -----------
module local 1.0;
require {
    type user_t;
    type cockpit_tmpfs_t;
    class file { open read map getattr execute_no_trans };
}

allow user_t cockpit_tmpfs_t:file { open read map getattr execute_no_trans };
type_transition cockpit_tmpfs_t cockpit_tmpfs_t:file user_t;
type_transition cockpit_tmpfs_t user_t:file user_t;
type_transition user_t cockpit_tmpfs_t:file cockpit_tmpfs_t;
type_transition user_t user_t:file cockpit_tmpfs_t;
--------- 8< ---------------

and stuffing it into the running system with

checkmodule -M -m -o /tmp/local.mod /tmp/local.te && semodule_package -o /tmp/local.pp -m /tmp/local.mod && semodule -i /tmp/local.pp

but with zero net change. Of course that policy above is mostly wrong -- I was trying to get *something* working and then minimizing it to the bits that are actually necessary.

So I'm afraid I need some help with this.

 - Am I even on the right track here? I. e. can/should we define some policy bits to allow this operation, or is this defined somewhere else?

 - Is there any way to get SELinux/the kernel to log about these violations, and exactly which objects with which type names it complains about?

 - Any suggestions how I can write a working policy?

Thank you in advance!


Version-Release number of selected component (if applicable):

selinux-policy-3.14.4-49.fc31.noarch

[1] https://github.com/cockpit-project/cockpit/pull/13473#issuecomment-599568203
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/security/selinux/hooks.c#n2398
[3] https://github.com/martinpitt/selinux-policy-contrib/blob/rawhide/cockpit.te

Comment 1 Martin Pitt 2020-07-17 13:39:06 UTC
Allison is rearchitecting how cockpit-session spawns the bridge. Now it only passes a memfd which is open for reading, not for writing any more. This avoids this error entirely. See https://github.com/cockpit-project/cockpit/pull/14312