[PATCH 0/2] selinux: Don't ignore ENOENT in Permissive mode

See 2/2 for explanation. Michal Prívozník (2): selinux: Swap two blocks handling setfilecon_raw() failure selinux: Don't ignore ENOENT in Permissive mode src/security/security_selinux.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) -- 2.32.0

In virSecuritySELinuxSetFileconImpl() we have code that handles setfilecon_raw() failure. The code consists of two blocks: one for dealing with shared filesystem like NFS (errno is ENOTSUP or EROFS) and the other block that's dealing with EPERM for privileged daemon. Well, the order of these two blocks is a bit confusing because the comment above them mentions the NFS case but EPERM block follows. Swap these two blocks to make it less confusing. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/security/security_selinux.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 0e5ea0366d..050acee2b0 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1264,22 +1264,9 @@ virSecuritySELinuxSetFileconImpl(const char *path, * boolean tunables to allow it ... */ VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR - if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP && - setfilecon_errno != EROFS) { + if (setfilecon_errno == EOPNOTSUPP || setfilecon_errno == ENOTSUP || + setfilecon_errno == EROFS) { VIR_WARNINGS_RESET - /* However, don't claim error if SELinux is in Enforcing mode and - * we are running as unprivileged user and we really did see EPERM. - * Otherwise we want to return error if SELinux is Enforcing. */ - if (security_getenforce() == 1 && - (setfilecon_errno != EPERM || privileged)) { - virReportSystemError(setfilecon_errno, - _("unable to set security context '%s' on '%s'"), - tcon, path); - return -1; - } - VIR_WARN("unable to set security context '%s' on '%s' (errno %d)", - tcon, path, setfilecon_errno); - } else { const char *msg; if (virFileIsSharedFSType(path, VIR_FILE_SHFS_NFS) == 1 && security_get_boolean_active("virt_use_nfs") != 1) { @@ -1293,6 +1280,19 @@ virSecuritySELinuxSetFileconImpl(const char *path, VIR_INFO("Setting security context '%s' on '%s' not supported", tcon, path); } + } else { + /* However, don't claim error if SELinux is in Enforcing mode and + * we are running as unprivileged user and we really did see EPERM. + * Otherwise we want to return error if SELinux is Enforcing. */ + if (security_getenforce() == 1 && + (setfilecon_errno != EPERM || privileged)) { + virReportSystemError(setfilecon_errno, + _("unable to set security context '%s' on '%s'"), + tcon, path); + return -1; + } + VIR_WARN("unable to set security context '%s' on '%s' (errno %d)", + tcon, path, setfilecon_errno); } return 1; -- 2.32.0

In selinux driver there's virSecuritySELinuxSetFileconImpl() which is responsible for actual setting of SELinux label on given file and handling possible failures. In fhe failure handling code we decide whether failure is fatal or not. But there is a bug: depending on SELinux mode (Permissive vs. Enforcing) the ENOENT is either ignored or considered fatal. This not correct - ENOENT must always be fatal - QEMU will fail opening it anyways. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004850 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/security/security_selinux.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 050acee2b0..7e8c4fb4f2 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1283,9 +1283,11 @@ virSecuritySELinuxSetFileconImpl(const char *path, } else { /* However, don't claim error if SELinux is in Enforcing mode and * we are running as unprivileged user and we really did see EPERM. - * Otherwise we want to return error if SELinux is Enforcing. */ - if (security_getenforce() == 1 && - (setfilecon_errno != EPERM || privileged)) { + * Otherwise we want to return error if SELinux is Enforcing, or we + * saw EPERM regardless of SELinux mode. */ + if (setfilecon_errno == ENOENT || + (security_getenforce() == 1 && + (setfilecon_errno != EPERM || privileged))) { virReportSystemError(setfilecon_errno, _("unable to set security context '%s' on '%s'"), tcon, path); -- 2.32.0

On a Monday in 2021, Michal Privoznik wrote:
In selinux driver there's virSecuritySELinuxSetFileconImpl() which is responsible for actual setting of SELinux label on given file and handling possible failures. In fhe failure handling code we decide whether failure is fatal or not. But there is a bug: depending on SELinux mode (Permissive vs. Enforcing) the ENOENT is either ignored or considered fatal.
This not correct - ENOENT must always be fatal - QEMU will fail opening it anyways.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004850
It won't get as far as trying to start QEMU. The error message in the linked bug: error: unable to stat: /var/lib/libvirt/images/slic.dat: No such file or directory comes from the DAC driver. IIUC in virSecurityStackTransactionCommit we happily commit the SELinux changes, fail to commit the DAC changes, but the rollback calling virSecurityManagerTransactionAbort does nothing. And since qemuSecuritySetAllLabel does not complete successfully, qemuProcessLaunch does not ask its callers to restore the labels. Jano
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/security/security_selinux.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)

On 9/20/21 5:57 PM, Ján Tomko wrote:
On a Monday in 2021, Michal Privoznik wrote:
In selinux driver there's virSecuritySELinuxSetFileconImpl() which is responsible for actual setting of SELinux label on given file and handling possible failures. In fhe failure handling code we decide whether failure is fatal or not. But there is a bug: depending on SELinux mode (Permissive vs. Enforcing) the ENOENT is either ignored or considered fatal.
This not correct - ENOENT must always be fatal - QEMU will fail opening it anyways.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004850
It won't get as far as trying to start QEMU. The error message in the linked bug: error: unable to stat: /var/lib/libvirt/images/slic.dat: No such file or directory comes from the DAC driver.
Correct. I should have rephrased that.
IIUC in virSecurityStackTransactionCommit we happily commit the SELinux changes, fail to commit the DAC changes, but the rollback calling virSecurityManagerTransactionAbort does nothing.
Indeed.
And since qemuSecuritySetAllLabel does not complete successfully, qemuProcessLaunch does not ask its callers to restore the labels.
Yes. Michal
participants (3)
-
Ján Tomko
-
Michal Privoznik
-
Michal Prívozník