Any update in the recent two weeks (I assume the recent update to cockpit-297-1.fc38) has made cockpit unusable on Fedora installations where SELinux is enforcing within user accounts ("confined user") and not only around them. This means that many use cases no longer work with cockpit (in short, cockpit is in the new version no longer compatible with and compliant to SELinux), which likely also affects other systems: I assume on RHEL it would be the same [1]. The issue relates to the confinement of the user accounts in which cockpit is logging into, not to the user accounts the user is using to open the cockpit web interface. For example, if I open Firefox and go to the web interface of cockpit in order to login, and if I then log in with the user "virtual-user" whereas "virtual-user" is confined (e.g., user_u), cockpit does no longer work. The issue looks at first glance like wrong credentials, since the web interface always outputs that the username or the password is wrong. However, I have tested many times and also in testing environments with copy-paste-passwords: the credentials seem wrong when the user account in which I want to log into with cockpit is confined, but it works if it is unconfined. The root log documents the problem: first, the new cockpit version seems to provoke an avc denial, which is followed by an error in cockpit (the error type indicates a bug, even if the avc denial is provoking it). A little later, cockpit starts to provoke another series of SELinux denials. It seems that SELinux becomes active because cockpit does not handle issues with regards to /tmp/ properly. This can be a misconfiguration of policy files but also a bug. Given the overall behavior and logs (especially the Python error type), I tend to assume that this is a bug. This issue could also have security implications depending on how and where cockpit is used. This is the full output of "journalctl -r": https://gitlab.com/py0xc31/tmp71/-/raw/main/cockpit-error-log The major part is imho: ``` <see full output for more> ... ... Aug 04 13:35:11 fedora setroubleshoot[8232]: SELinux is preventing cockpit-bridge from execute access on the file /tmp/#135 (deleted). ***** Plugin catchall_boolean (89.3 confidence) suggests ****************** If you want to allow user to exec content Then you must tell SELinux about this by enabling the 'user_exec_content' boolean. Do setsebool -P user_exec_content 1 ***** Plugin catchall (11.6 confidence) suggests ************************** If you believe that cockpit-bridge should be allowed execute access on the #135 (deleted) file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'cockpit-bridge' --raw | audit2allow -M my-cockpitbridge # semodule -X 300 -i my-cockpitbridge.pp Aug 04 13:35:11 fedora setroubleshoot[8232]: SELinux is preventing cockpit-bridge from execute access on the file /tmp/#135 (deleted). For complete SELinux messages run: sealert -l 23e5953f-7c79-4b04-8367-470ec578df3b Aug 04 13:35:11 fedora setroubleshoot[8232]: SELinux is preventing cockpit-bridge from execute access on the file /memfd:libffi (deleted). ***** Plugin catchall_boolean (89.3 confidence) suggests ****************** If you want to allow user to exec content Then you must tell SELinux about this by enabling the 'user_exec_content' boolean. Do setsebool -P user_exec_content 1 ***** Plugin catchall (11.6 confidence) suggests ************************** If you believe that cockpit-bridge should be allowed execute access on the memfd:libffi (deleted) file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'cockpit-bridge' --raw | audit2allow -M my-cockpitbridge # semodule -X 300 -i my-cockpitbridge.pp Aug 04 13:35:11 fedora setroubleshoot[8232]: SELinux is preventing cockpit-bridge from execute access on the file /memfd:libffi (deleted). For complete SELinux messages run: sealert -l 23e5953f-7c79-4b04-8367-470ec578df3b ... ... <see full output for more> ... ... Aug 04 13:35:08 fedora abrt-notification[7924]: Process 4629 (cockpit-bridge) of user 1002 encountered an uncaught MemoryError exception Aug 04 13:35:08 fedora abrt-server[7880]: Deleting problem directory Python3-2023-08-04-13:35:08-7846 (dup of Python3-2023-08-03-23:05:29-4629) Aug 04 13:35:08 fedora systemd-logind[1732]: Removed session 12. Aug 04 13:35:08 fedora systemd-logind[1732]: Session 12 logged out. Waiting for processes to exit. Aug 04 13:35:08 fedora systemd[1]: session-12.scope: Deactivated successfully. Aug 04 13:35:08 fedora audit[7785]: USER_END pid=7785 uid=0 auid=1002 ses=12 subj=system_u:system_r:cockpit_session_t:s0 msg='op=PAM:session_close grantors=pam_selinux,pam_loginuid,pam_selinux,pam_keyinit,pam_ssh_add,pam_keyinit,pam_limits,pam_systemd,pam_unix,pam_umask,pam_lastlog acct="virtual" exe="/usr/libexec/cockpit-session" hostname=fe80::278f:3155:4884:44e3%enp1s0f0 addr=fe80::278f:3155:4884:44e3 terminal=? res=success' Aug 04 13:35:08 fedora cockpit-session[7785]: pam_unix(cockpit:session): session closed for user virtual Aug 04 13:35:08 fedora audit[7785]: CRED_DISP pid=7785 uid=0 auid=1002 ses=12 subj=system_u:system_r:cockpit_session_t:s0 msg='op=PAM:setcred grantors=pam_localuser,pam_unix,pam_listfile acct="virtual" exe="/usr/libexec/cockpit-session" hostname=fe80::278f:3155:4884:44e3%enp1s0f0 addr=fe80::278f:3155:4884:44e3 terminal=? res=success' Aug 04 13:35:08 fedora cockpit-ws[7846]: MemoryError Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: self.callback = sd.bus_message_handler_t(handler) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/_vendor/systemd_ctypes/bus.py", line 226, in __init__ Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: slot = Slot(obj.message_received) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/_vendor/systemd_ctypes/bus.py", line 345, in add_object Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: self.exportees = [self.server.add_object(path, cls()) for path, cls in exports] Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/bridge.py", line 54, in <listcomp> Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: self.exportees = [self.server.add_object(path, cls()) for path, cls in exports] Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/bridge.py", line 54, in __init__ Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: self.internal_bus = InternalBus(EXPORTS) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/bridge.py", line 67, in __init__ Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: router = Bridge(args) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/bridge.py", line 168, in run Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: return future.result() Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib64/python3.11/asyncio/base_events.py", line 653, in run_until_complete Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: return self._loop.run_until_complete(task) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib64/python3.11/asyncio/runners.py", line 118, in run Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^^^^^^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: return runner.run(main) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib64/python3.11/asyncio/runners.py", line 190, in run Aug 04 13:35:08 fedora cockpit-ws[7846]: asyncio.run(main, debug=debug) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/_vendor/systemd_ctypes/event.py", line 109, in run_async Aug 04 13:35:08 fedora cockpit-ws[7846]: run_async(run(args), debug=args.debug) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/lib/python3.11/site-packages/cockpit/bridge.py", line 283, in main Aug 04 13:35:08 fedora cockpit-ws[7846]: ^^^^^^ Aug 04 13:35:08 fedora cockpit-ws[7846]: sys.exit(main()) Aug 04 13:35:08 fedora cockpit-ws[7846]: File "/usr/bin/cockpit-bridge", line 8, in <module> Aug 04 13:35:08 fedora cockpit-ws[7846]: Traceback (most recent call last): Aug 04 13:35:08 fedora python3[7846]: detected unhandled Python exception in '/usr/bin/cockpit-bridge' Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F72756E2F757365722F313030322F233437202864656C6574656429 dev="tmpfs" ino=47 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F746D702F23313337202864656C6574656429 dev="tmpfs" ino=137 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F6465762F73686D2F2334202864656C6574656429 dev="tmpfs" ino=4 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F72756E2F757365722F313030322F233436202864656C6574656429 dev="tmpfs" ino=46 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F746D702F23313336202864656C6574656429 dev="tmpfs" ino=136 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F6465762F73686D2F2333202864656C6574656429 dev="tmpfs" ino=3 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { map } for pid=7846 comm="cockpit-bridge" path=2F686F6D652F7669727475616C2F233230373338363736202864656C6574656429 dev="dm-0" ino=20738676 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_home_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F6465762F73686D2F2332202864656C6574656429 dev="tmpfs" ino=2 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F7661722F746D702F2331343739363939202864656C6574656429 dev="dm-0" ino=1479699 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F746D702F23313335202864656C6574656429 dev="tmpfs" ino=135 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:08 fedora audit[7846]: AVC avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F6D656D66643A6C6962666669202864656C6574656429 dev="tmpfs" ino=9259 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass=file permissive=0 Aug 04 13:35:07 fedora audit[7785]: CRED_REFR pid=7785 uid=0 auid=1002 ses=12 subj=system_u:system_r:cockpit_session_t:s0 msg='op=PAM:setcred grantors=pam_localuser,pam_unix,pam_listfile acct="virtual" exe="/usr/libexec/cockpit-session" hostname=fe80::278f:3155:4884:44e3%enp1s0f0 addr=fe80::278f:3155:4884:44e3 terminal=? res=success' Aug 04 13:35:07 fedora audit[7785]: USER_START pid=7785 uid=0 auid=1002 ses=12 subj=system_u:system_r:cockpit_session_t:s0 msg='op=PAM:session_open grantors=pam_selinux,pam_loginuid,pam_selinux,pam_keyinit,pam_ssh_add,pam_keyinit,pam_limits,pam_systemd,pam_unix,pam_umask,pam_lastlog acct="virtual" exe="/usr/libexec/cockpit-session" hostname=fe80::278f:3155:4884:44e3%enp1s0f0 addr=fe80::278f:3155:4884:44e3 terminal=? res=success' Aug 04 13:35:07 fedora cockpit-session[7785]: pam_unix(cockpit:session): session opened for user virtual(uid=1002) by (uid=0) Aug 04 13:35:07 fedora systemd[1]: Started session-12.scope - Session 12 of User virtual. ... ... <see full output for more> ``` If you need more information, let me know. [1] https://access.redhat.com/documentation/de-de/red_hat_enterprise_linux/8/html/using_selinux/managing-confined-and-unconfined-users_using-selinux Reproducible: Always Steps to Reproduce: 1. create a user account with password and then confine the user account (I did this by making __default__ to "user_u", which makes any login "user_u" except those that are determined explicitly in a different way) -> e.g., "semanage login -a -s user_u __default__" 2. Go to cockpit web interface (I used Firefox) and try to login into cockpit with the confined user 3. The web interface will tell that credentials are wrong 4. Check the journalctl of root 5. Remove the confinement, log out and then log in again, or simply reboot (changed confinements needs a re-login to become active). 6. Test again without confinement: it will work. Actual Results: The new version of cockpit cannot be used when SELinux is active within and among user accounts that are used by cockpit, which limits use cases and environments/infrastructures that can use cockpit. Expected Results: The new version of cockpit should work with confined user accounts just like previous versions. F38 KDE Spin. All up to date as of today. Only stable branches on the test system. cat /proc/sys/kernel/tainted = 0. No third party repositories.
https://bodhi.fedoraproject.org/updates/FEDORA-2023-34f212e4ae
Thanks for your report! We already cover a restricted `user_u` login in our tests: https://github.com/cockpit-project/cockpit/blob/fabdc84b/test/verify/check-static-login#L457 However, that uses "semanage login -a -s user_u username", not the __default__ appraoch. perhaps this is slightly different. This also creates a brand new user, whereas possibly your user has existed for a while? Can you reproduce this with a newly created user as well?
I have just retested with __default__ being unconfined_u and the user I want to log into with cockpit being user_u. First, I tested with changing the existing user. Then, I kept __default__ at unconfined_u and created a completely new user (virtual2) and did "semanage login -a -s user_u virtual2". The problem remains the same in all cases. When setting __default__ to unconfined_u, I have always restarted both cockpit.service and cockpit.socket with systemctl to ensure that the accounts cockpit-ws* get the new confinement condition (is there maybe a consideration I have missed?). > not the __default__ approach This should not make a difference: if I log into an account with cockpit, only the confinement of this account should be relevant. SELinux behavior is equal if the "abc" account is user_u through mapping from __default__ or through mapping from "abc". If cockpit is itself working with an account, this should be likewise confined. If cockpit would need an account for itself that has to be unconfined (while being used by non-confined accounts), this would partly break the security concept. However, having tested successfully with __default__ being user_u when only the log-in-account was unconfined_u, this seems to be not the origin. So it seems that cockpit does not need any unconfined_u account for its processes. It would be interesting to know if your tests behave different if you change in the tests "semanage login -a -s user_u username" to "semanage login -a -s user_u __default__"? My expectation is that "semanage login -a -s user_u username" and "semanage login -a -s user_u __default__" should behave the same because we know circumstances where __default__=user_u works (so, if the user account that is used to log in with cockpit is explicitly determined unconfined_u to be not mapped to __default__). The account I am using to work (and from which I opened Firefox) is sysadm_u. But this works properly if the account in cockpit is unconfined_u, so I assume this is not related. Can maybe the python error give us some hint? Concerning the configuration of cockpit, the only modification in its configs that I have made is to add some accounts on the disallow list in /etc/cockpit (I just rechecked: none of the tested accounts are contained on the disallow list). I will also play a bit and see if I can get more. If you need me to provide more information or test something, let me know.
I forgot: I have made my original tests also with an earlier kernel where I know for sure that I have used it already successfully with cockpit: 6.3.6 (now I am on 6.3.7). So the kernel is not the issue. The last time I know for sure that cockpit worked properly was on 28st July according to my logs (I was using virtual machines in cockpit). Theoretically, any update in between could be the origin. It seems that the new cockpit was updated the same day, and the dnf updates started two minutes before the last log entry of my cockpit machines. So I guess the new cockpit has not been active back then since I did definitely no systemctl restart or so. It might be noted that there are two other updates that are not cockpit-specific but that could be related: selinux-policy noarch 38.22-1.fc38 updates 50 k selinux-policy-targeted noarch 38.22-1.fc38 updates 6.7 M All updates that have been applied after I used cockpit the last time successfully can be seen below (I don't think that I did any other change to my system since then): cockpit x86_64 297-1.fc38 updates 41 k cockpit-bridge x86_64 297-1.fc38 updates 545 k cockpit-networkmanager noarch 297-1.fc38 updates 949 k cockpit-packagekit noarch 297-1.fc38 updates 1.0 M cockpit-selinux noarch 297-1.fc38 updates 482 k cockpit-storaged noarch 297-1.fc38 updates 954 k cockpit-system noarch 297-1.fc38 updates 3.7 M cockpit-ws x86_64 297-1.fc38 updates 927 k swtpm x86_64 0.8.0-5.fc38 updates 29 k swtpm-libs x86_64 0.8.0-5.fc38 updates 50 k swtpm-tools x86_64 0.8.0-5.fc38 updates 115 k vim-data noarch 2:9.0.1677-2.fc38 updates 23 k vim-minimal x86_64 2:9.0.1677-2.fc38 updates 796 k Installing dependencies: swtpm-selinux noarch 0.8.0-5.fc38 updates 20 k ------------------- kernel-* x86_64 6.4.7-200.fc38 updates-testing <kernel packages> ------------------- cmake-filesystem x86_64 3.27.1-1.fc38 updates 18 k dnf noarch 4.16.2-1.fc38 updates 475 k dnf-automatic noarch 4.16.2-1.fc38 updates 44 k dnf-data noarch 4.16.2-1.fc38 updates 38 k dnf-plugins-core noarch 4.4.2-1.fc38 updates 38 k libdnf x86_64 0.70.2-1.fc38 updates 670 k libgexiv2 x86_64 0.14.2-1.fc38 updates 98 k libqalculate x86_64 4.7.0-1.fc38 updates 2.2 M m17n-db noarch 1.8.3-1.fc38 updates 688 k m17n-lib x86_64 1.8.3-1.fc38 updates 197 k mariadb x86_64 3:10.5.21-1.fc38 updates 1.6 M mariadb-backup x86_64 3:10.5.21-1.fc38 updates 6.5 M mariadb-common x86_64 3:10.5.21-1.fc38 updates 33 k mariadb-cracklib-password-check x86_64 3:10.5.21-1.fc38 updates 13 k mariadb-embedded x86_64 3:10.5.21-1.fc38 updates 5.4 M mariadb-errmsg x86_64 3:10.5.21-1.fc38 updates 217 k mariadb-gssapi-server x86_64 3:10.5.21-1.fc38 updates 16 k mariadb-server x86_64 3:10.5.21-1.fc38 updates 11 M mariadb-server-utils x86_64 3:10.5.21-1.fc38 updates 216 k openssh x86_64 9.0p1-17.fc38 updates 435 k openssh-clients x86_64 9.0p1-17.fc38 updates 698 k openssh-server x86_64 9.0p1-17.fc38 updates 450 k openssl x86_64 1:3.0.9-2.fc38 updates 1.0 M openssl-libs x86_64 1:3.0.9-2.fc38 updates 2.1 M pipewire x86_64 0.3.76-1.fc38 updates 108 k pipewire-alsa x86_64 0.3.76-1.fc38 updates 63 k pipewire-gstreamer x86_64 0.3.76-1.fc38 updates 64 k pipewire-jack-audio-connection-kit x86_64 0.3.76-1.fc38 updates 16 k pipewire-jack-audio-connection-kit-libs x86_64 0.3.76-1.fc38 updates 139 k pipewire-libs x86_64 0.3.76-1.fc38 updates 1.8 M pipewire-pulseaudio x86_64 0.3.76-1.fc38 updates 171 k pipewire-utils x86_64 0.3.76-1.fc38 updates 344 k python3-dnf noarch 4.16.2-1.fc38 updates 604 k python3-dnf-plugins-core noarch 4.4.2-1.fc38 updates 299 k python3-hawkey x86_64 0.70.2-1.fc38 updates 106 k python3-libdnf x86_64 0.70.2-1.fc38 updates 826 k qpdf-libs x86_64 11.5.0-1.fc38 updates 928 k smartmontools x86_64 1:7.3-9.fc38 updates 600 k smartmontools-selinux noarch 1:7.3-9.fc38 updates 31 k xapian-core-libs x86_64 1.4.23-1.fc38 updates 771 k yum noarch 4.16.2-1.fc38 updates 36 k ------------------- cpp x86_64 13.2.1-1.fc38 updates 11 M libatomic x86_64 13.2.1-1.fc38 updates 34 k libgcc x86_64 13.2.1-1.fc38 updates 109 k libgomp x86_64 13.2.1-1.fc38 updates 319 k libobjc x86_64 13.2.1-1.fc38 updates 59 k libstdc++ x86_64 13.2.1-1.fc38 updates 863 k ------------------- podman x86_64 5:4.6.0-1.fc38 updates 14 M podman-gvproxy x86_64 5:4.6.0-1.fc38 updates 5.0 M selinux-policy noarch 38.22-1.fc38 updates 50 k selinux-policy-targeted noarch 38.22-1.fc38 updates 6.7 M ------------------- firefox x86_64 116.0-2.fc38 updates 61 M firefox-langpacks x86_64 116.0-2.fc38 updates 42 M firefox-wayland x86_64 116.0-2.fc38 updates 23 k mkpasswd x86_64 5.5.18-1.fc38 updates 26 k whois x86_64 5.5.18-1.fc38 updates 76 k whois-nls noarch 5.5.18-1.fc38 updates 38 k ------------------- clevis-pin-tpm2 x86_64 0.5.3-1.fc38 updates 885 k gupnp x86_64 1.6.5-1.fc38 updates 105 k ------------------- autocorr-de noarch 1:7.5.5.2-1.fc38 updates 77 k autocorr-en noarch 1:7.5.5.2-1.fc38 updates 110 k cockpit-machines noarch 295-1.fc38 updates 1.2 M ibus-typing-booster noarch 2.23.2-1.fc38 updates 1.2 M libreoffice-calc x86_64 1:7.5.5.2-1.fc38 updates 8.4 M libreoffice-core x86_64 1:7.5.5.2-1.fc38 updates 121 M libreoffice-data x86_64 1:7.5.5.2-1.fc38 updates 559 k libreoffice-draw x86_64 1:7.5.5.2-1.fc38 updates 22 k libreoffice-graphicfilter x86_64 1:7.5.5.2-1.fc38 updates 271 k libreoffice-gtk3 x86_64 1:7.5.5.2-1.fc38 updates 571 k libreoffice-gtk4 x86_64 1:7.5.5.2-1.fc38 updates 503 k libreoffice-help-de x86_64 1:7.5.5.2-1.fc38 updates 3.7 M libreoffice-help-en x86_64 1:7.5.5.2-1.fc38 updates 3.0 M libreoffice-impress x86_64 1:7.5.5.2-1.fc38 updates 479 k libreoffice-kf5 x86_64 1:7.5.5.2-1.fc38 updates 283 k libreoffice-langpack-de x86_64 1:7.5.5.2-1.fc38 updates 915 k libreoffice-langpack-en x86_64 1:7.5.5.2-1.fc38 updates 99 k libreoffice-ogltrans x86_64 1:7.5.5.2-1.fc38 updates 169 k libreoffice-opensymbol-fonts noarch 1:7.5.5.2-1.fc38 updates 150 k libreoffice-pdfimport x86_64 1:7.5.5.2-1.fc38 updates 243 k libreoffice-pyuno x86_64 1:7.5.5.2-1.fc38 updates 457 k libreoffice-ure x86_64 1:7.5.5.2-1.fc38 updates 2.3 M libreoffice-ure-common x86_64 1:7.5.5.2-1.fc38 updates 1.6 M libreoffice-writer x86_64 1:7.5.5.2-1.fc38 updates 3.8 M libreoffice-x11 x86_64 1:7.5.5.2-1.fc38 updates 240 k librepo x86_64 1.15.2-1.fc38 updates 95 k nspr x86_64 4.35.0-9.fc38 updates 136 k nss x86_64 3.92.0-1.fc38 updates 695 k nss-softokn x86_64 3.92.0-1.fc38 updates 1.0 M nss-softokn-freebl x86_64 3.92.0-1.fc38 updates 326 k nss-sysinit x86_64 3.92.0-1.fc38 updates 18 k nss-tools x86_64 3.92.0-1.fc38 updates 537 k nss-util x86_64 3.92.0-1.fc38 updates 86 k python-pip-wheel noarch 22.3.1-3.fc38 updates 1.4 M python3-productmd noarch 1.36-1.fc38 updates 101 k python3-regex x86_64 2023.6.3-1.fc38 updates 414 k xdg-desktop-portal-gnome x86_64 44.2-1.fc38 updates 197 k -------------------
I'm testing this with a pristine Fedora 38 cloud image, with cockpit-{bridge,system,ws}-297-1.fc38.x86_64 -- i.e. not a build in our CI, but *the* Fedora packages. Testing changing the default restriction mapping as you said: # semanage login -a -s user_u __default__ ValueError: Login mapping for __default__ is already defined # semanage login -m -s user_u __default__ libsemanage.validate_handler: MLS range s0-s0:c0.c1023 for Unix user __default__ exceeds allowed range s0 for SELinux user user_u (No such file or directory). libsemanage.validate_handler: seuser mapping [__default__ -> (user_u, s0-s0:c0.c1023)] is invalid (No such file or directory). libsemanage.dbase_llist_iterate: could not iterate over records (No such file or directory). FileNotFoundError: No such file or directory # semanage login -d -s user_u __default__ ValueError: Login mapping for __default__ is defined in policy, cannot be deleted Meh, I'm too stupid to drive SELinux... How *exactly* did you change the default? So in the meantime, going back to creating a new user with user_u. You already confirmed that the issue happens for you with that as well: # useradd unpriv; echo 'unpriv:foobar' | chpasswd; semanage login -a -s user_u unpriv # semanage login --list __default__ unconfined_u s0-s0:c0.c1023 * root unconfined_u s0-s0:c0.c1023 * unpriv user_u s0 * This causes a lot of noise in the journal, as a lot of operations are restricted. For example: (tmpfiles)[1244]: systemd-tmpfiles-setup.service: Failed to locate executable systemd-tmpfiles: No such file or directory (tmpfiles)[1244]: systemd-tmpfiles-setup.service: Failed at step EXEC spawning systemd-tmpfiles: No such file or directory systemd[1231]: systemd-tmpfiles-setup.service: Main process exited, code=exited, status=203/EXEC and also various SELinux denials: systemd[1231]: selinux: avc: denied { status } for auid=1003 uid=1003 gid=1003 cmdline="/usr/bin/dbus-broker-launch --scope user" function="method_subscribe" scontext=user_u:user_r:user_dbusd_t:s0 tcontext=user_u:user_r:user_t:s0 tclass=system permissive=0 audit[1246]: AVC avc: denied { watch } for pid=1246 comm="cockpit-bridge" path="/run/systemd" dev="tmpfs" ino=2 scontext=user_u:user_r:user_t:s0 tcontext=system_u:object_r:init_var_run_t:s0 tclass=dir permissive=0 audit[1246]: AVC avc: denied { watch } for pid=1246 comm="cockpit-bridge" path="/var" dev="vda5" ino=269 scontext=user_u:user_r:user_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=dir permissive=0 audit[1246]: AVC avc: denied { watch } for pid=1246 comm="cockpit-bridge" path="/var" dev="vda5" ino=269 scontext=user_u:user_r:user_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=dir permissive=0 but that's fine -- I still get a working cockpit session and no bridge crash. The current kernel is 6.4.6, quite a bit newer than your 6.3.7, but it's not very probable that this is the cause. `id -Z` in cockpit's terminal confirms "user_u:user_r:user_t:s0". The denials that I *don't* get, but appear in your log, are things like these: avc: denied { execute } for pid=7846 comm="cockpit-bridge" path=2F72756E2F757365722F313030322F233437202864656C6574656429 dev="tmpfs" ino=47 scontext=user_u:user_r:user_t:s0 tcontext=user_u:object_r:user_tmp_t:s0 tclass that's something that may have changed with the Python bridge. That "path=" looks like hex ASCII code for "/run/user/1002/#47 (deleted)". My "unpriv" user's runtime directory is mounted like this: tmpfs on /run/user/1003 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=109752k,nr_inodes=27438,mode=700,uid=1003,gid=1003,inode64) perhaps you can compare? Is that mounted "noexec" for you by any chance? But perhaps it is an SELinux policy instead of a mount option -- the "user_exec_content boolean option" in your log hints to this. The default policy is "on": # semanage boolean --list | grep user_exec_content container_user_exec_content (on , on) Allow container to user exec content user_exec_content (on , on) Allow user to exec content And indeed I get your error after "semanage boolean --modify --off user_exec_content". An unrestricted user account still works, just the user_u one fails. So I'm fairly sure that the relevant change on your system is just that. I'll now check how to properly handle that MemoryError exception in the bridge. Thanks!
I started with the patch below, but this isn't an isolated thing -- *every* D-Bus operation fails with user_exec_content being off. It also doesn't help that SELinux responds with ENOMEM to all such denied calls, which is very misleading (what about good old EPERM?). It feels to me that this is either due to how sd_bus itself works, or how Python's ctypes wraps C calls -- one of these seems to require user_exec_content in the user's $XDG_RUNTIME_DIR. diff --git src/cockpit/bridge.py src/cockpit/bridge.py index 806bf64eb..9cec94823 100644 --- src/cockpit/bridge.py +++ src/cockpit/bridge.py @@ -51,10 +51,17 @@ class InternalBus: client_socket, server_socket = socket.socketpair() self.client = bus.Bus.new(fd=client_socket.detach()) self.server = bus.Bus.new(fd=server_socket.detach(), server=True) - self.exportees = [self.server.add_object(path, cls()) for path, cls in exports] + self.exportees = [] + for path, cls in exports: + self.export(path, cls()) def export(self, path: str, obj: bus.BaseObject) -> None: - self.exportees.append(self.server.add_object(path, obj)) + try: + slot = self.server.add_object(path, obj) + except (OSError, MemoryError) as e: + logger.warning("Failed to export internal bus path %s: %s", path, str(e)) + return + self.exportees.append(slot) class Bridge(Router, PackagesListener): diff --git src/cockpit/internal_endpoints.py src/cockpit/internal_endpoints.py index 6bc27d503..c92eb2647 100644 --- src/cockpit/internal_endpoints.py +++ src/cockpit/internal_endpoints.py @@ -128,7 +128,10 @@ class cockpit_Machines(bus.Object): # ignore the first callback self.pending_notify = ... - self.watch = pathwatch.PathWatch(str(self.path), self) + try: + self.watch = pathwatch.PathWatch(str(self.path), self) + except (OSError, MemoryError) as e: + logger.warning("Failed to set up watch for %s: %s", self.path, e) self.pending_notify = None
I'm currently much on the way and cannot test much. But concerning your question: > How *exactly* did you change the default? Check "semanage login -l" to see what accounts / mappings are regulated (which includes user accounts like "username", "virtual" and such, but also including the mapping "__default__" to which user accounts that are not explicitly regulated are mapped to). If you change the setting of an account that is already listed (=regulated), you use "-m", and if it is not yet listed/regulated, you use "-a". E.g., if it is already listed with "-l": semanage login -m -s user_u username E.g., if it is not yet listed with "-l": semanage login -a -s user_u username However, you cannot delete __default__ because this is the condition for any account that is not explicitly regulated (otherwise, SELinux would not know what to do if an account logs in that is not explicitly regulated in the "-l" list). The default condition of __default__ is unconfined_u, which means there is no confinement at all. This means, if you want to disable confinement by default (which is also the default for Fedora), you do not delete __default__ but you change it to unconfined_u. So if I understand what you want to achieve, you have to REPLACE "semanage login -d -s user_u __default__" with "semanage login -m -s unconfined_u username" -> if you delete all explicitly regulated accounts while you set __default__ to unconfined_u, you have disabled confined user accounts at all. I think Fedora keeps by default root separated from __default__ (this means, by default you have both __default__ and root listed with "semanage login -l") so that root does not get accidentally confined (this can create a situation where people lock themselves out of the system). Let me know if I misunderstood your goal or if something is unclear. Also let me know I shall test something on my side (I can dedicate some time to test by the end of the week).
> perhaps you can compare? Is that mounted "noexec" for you by any chance? But perhaps it is an SELinux policy instead of a mount option -- the "user_exec_content boolean option" in your log hints to this. The default policy is "on": ``` [username@fedora ~]$ cat /etc/mtab | grep tmpfs ... ... ... tmpfs /tmp tmpfs rw,seclabel,nosuid,nodev,nr_inodes=1048576,inode64 0 0 tmpfs /run/user/1000 tmpfs rw,seclabel,nosuid,nodev,relatime,size=3157620k,nr_inodes=789405,mode=700,uid=1000,gid=1000,inode64 0 0 tmpfs /run/user/1001 tmpfs rw,seclabel,nosuid,nodev,relatime,size=3157620k,nr_inodes=789405,mode=700,uid=1001,gid=1001,inode64 0 0 ``` I have not changed the defaults here (so, default of F38 KDE Spin). So there's no noexec in the tmpfs. I can currently not check the condition of user_exec_content on the system, but I will check later and then let you know how this is set currently on my system. It is possible that I have changed the default of user_exec_content since I have modified some of the booleans there. I will check later also what F38 Workstation and F38 KDE have by default to check if I changed that.
(In reply to Christopher Klooz from comment #7) > > How *exactly* did you change the default? > > Check "semanage login -l" to see what accounts [...] For the record: This and the "noexec mount option" bits are not relevant any more, this was mostly me thinking aloud. > I can currently not check the condition of user_exec_content on the system This must be the cause. If it's not, then I'll throw away my hat and open a bar or something, because then what am I even doing here :-)
> For the record: This and the "noexec mount option" bits are not relevant any more, this was mostly me thinking aloud. I am currently working much out of my email account, and I didn't see the mail of your second post when writing the first answer ;) > This must be the cause. If it's not, then I'll throw away my hat and open a bar or something, because then what am I even doing here :-) I am happy to tell you that you do not need to open a bar (although I would appreciate a good drink ;) -> user_exec_content seems to be indeed the origin. The condition I have set on my system is: ``` [username@fedora ~]$ semanage boolean --list | grep user_exec_content ... user_exec_content (off , off) Allow user to exec content ``` I have just had a minute at home to test: I changed user_exec_content from "off" to "on" and after that, I was able to log into cockpit and also to use my virtual machines. It seems that I have changed this value myself since the live images of KDE and Workstation have the value set to "on" by default. So we found the SELinux boolean that causes the trouble... However, the question is: Why did this work in the previous cockpit versions? And can we adjust the current version to work again with user_exec_content=="off" ? This is not a serious security issue or so, but it reduces the use cases for the current version of cockpit because user_exec_content can be a powerful means to increase security or to satisfy corporate IT/security policies in several environments (and some environments with untrusted users might even depend on it). ------ If you choose to not consider user_exec_content=="off" in future versions, you might check if the documentation of RHEL needs to be adjusted (I don't know what the default value is in RHEL, and thus if it can cause trouble if RHEL 8 users update without adjusting the boolean if it is "off" by default). In any case, thank you for taking care of this!
> Why did this work in the previous cockpit versions? And can we adjust the current version to work again with user_exec_content=="off" ? The bridge implementation changed from gdbus to sdbus, wrapped in Python's ctypes. Either of these seems to require exec permissions on the user's runtime directory. Indeed we should check if this can be salvaged -- but that will take a few weeks (holiday season and all). That's why I keep this bugzilla open, but it's not a "stop the line" urgency.
It would be cool if user_exec_content=="off" would work again future. But this is indeed not urgent. Let me know if I can help with testing or so. Have a nice holiday ;)
The issue seems to be solved: The cockpit login does now work again when I use credentials from a user account that is set to user_u while __default__ is also user_u. I have just worked again with virtual machines (cockpit-machines) in this condition: looks good. Only the account I am working in is still sysadm_u (as it was in the tests above). Solved. My system is at the moment F39 KDE, up to date as of today with stable updates. Unfortunately, I have not tested this for some time, so I cannot say which stable update solved the issue. Thanks for taking care :)
... of course the new test was with user_exec_content=="off"