-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 This is an updated patch with Steven's suggestions on making sure we audit bad data. This patch looks good to me. acked. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlJuvlYACgkQrlYvE4MpobMm8QCgqk5v5fp8VWkf1US0iWGCVa81 F+wAoKpueblWU0BMkNPGsU+EFhAbmUjR =nR1C -----END PGP SIGNATURE-----
>From d45e4c1d15dd597c3403846b837f2eb7307c3561 Mon Sep 17 00:00:00 2001 From: Dan Walsh <dwalsh@xxxxxxxxxx> Date: Fri, 25 Oct 2013 14:45:15 -0400 Subject: [PATCH 01/17] Do not return error if system is in permissive mode. Move avc_enforcing check inside avc_has_perm_noaudit This way avc_has_perm and avc_has_perm_noaudit work the same. Also suggested changes from Stephen Smalley to make sure we get an audit message if this failure happens. Make sure to init av_decision buffer so we get audit message on certain failures The source or target security context could no longer be valid, e.g. due to a policy reload since the time the SIDs were allocated, or that the security class is invalid, e.g. a userspace security class unknown to the loaded policy. (Or it could just represent random memory corruption in the application, of course). Returning 0 from avc_has_perm_noaudit() could be a source of subtle bugs without ensuring that the avd has been initialized sanely. avc_has_perm() initializes it before calling avc_has_perm_noaudit(), but maybe that should be moved inside of avc_has_perm_noaudit() if avd is set? Then the subsequent avc_audit() call by avc_has_perm() should set denied to 0 (as avd->allowed will be initialized to 0), but audited will be set to 0 because avd->auditdeny will be initialized to 0 too. So we'll audit nothing and get no indication of the error at that point. We could instead initialize avd in a similar way as the kernel does: static void avd_init(struct av_decision *avd) { avd->allowed = 0; avd->auditallow = 0; avd->auditdeny = 0xffffffff; avd->seqno = avc_cache.latest_notif; avd->flags = 0; } And call that on entry to avc_has_perm_noaudit() if avd is non-NULL. Then we'll get an audit message as well, although the security contexts may be invalid (but will be shown as their string form) or the class may be invalid (in which case we'll get a null string). --- libselinux/src/avc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c index 802a07f..76cc367 100644 --- a/libselinux/src/avc.c +++ b/libselinux/src/avc.c @@ -739,6 +739,15 @@ void avc_audit(security_id_t ssid, security_id_t tsid, hidden_def(avc_audit) +static void avd_init(struct av_decision *avd) +{ + avd->allowed = 0; + avd->auditallow = 0; + avd->auditdeny = 0xffffffff; + avd->seqno = avc_cache.latest_notif; + avd->flags = 0; +} + int avc_has_perm_noaudit(security_id_t ssid, security_id_t tsid, security_class_t tclass, @@ -751,6 +760,9 @@ int avc_has_perm_noaudit(security_id_t ssid, access_vector_t denied; struct avc_entry_ref ref; + if (avd) + avd_init(avd); + if (!avc_using_threads && !avc_app_main_loop) { (void)avc_netlink_check_nb(); } @@ -809,6 +821,7 @@ int avc_has_perm_noaudit(security_id_t ssid, out: avc_release_lock(avc_lock); + if (!avc_enforcing && (errno == EINVAL)) return 0; return rc; } @@ -821,8 +834,6 @@ int avc_has_perm(security_id_t ssid, security_id_t tsid, struct av_decision avd; int errsave, rc; - memset(&avd, 0, sizeof(avd)); - rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd); errsave = errno; avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); -- 1.8.3.1