-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 This patch looks good to me. acked. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk6wTM8ACgkQrlYvE4MpobNwkwCgsux7l4CAeCl7ouYCaXHji7Ln kTMAoNLn+5DNaAuNqCjgwZYvl0emCuZR =AnoI -----END PGP SIGNATURE-----
>From a3937807d751496b4a374c56429ba70b11fbfd5e Mon Sep 17 00:00:00 2001 From: Dan Walsh <dwalsh@xxxxxxxxxx> Date: Thu, 20 Oct 2011 15:14:08 -0400 Subject: [PATCH 54/63] libselinux: simple interface for access checks Some programs, like passwd, need to do simeple one time access checks. Rather than set up a full avc cache and use that infrastructure they were directly using security_compute_av. A problem with this approach is the lack of audit on denials. This patch creates a new interface that is simple to use and which will still listen to things like permissive and output audit messages on denials. Signed-off-by: Eric Paris <eparis@xxxxxxxxxx> --- libselinux/include/selinux/selinux.h | 19 +++++++++++++++++ libselinux/man/man3/security_compute_av.3 | 5 ++++ libselinux/src/checkAccess.c | 32 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 0 deletions(-) diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index d766645..826ed71 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -513,6 +513,25 @@ extern const char *selinux_colors_path(void); extern const char *selinux_netfilter_context_path(void); extern const char *selinux_path(void); +/** + * selinux_check_access - Check permissions and perform appropriate auditing. + * @scon: source security context + * @tcon: target security context + * @tclass: target security class string + * @perm: requested permissions string, interpreted based on @tclass + * @auditdata: auxiliary audit data + * + * Check the AVC to determine whether the @perm permissions are granted + * for the SID pair (@scon, @tcon), interpreting the permissions + * based on @tclass. + * Return %0 if all @perm permissions are granted, -%1 with + * @errno set to %EACCES if any permissions are denied or to another + * value upon other errors. + * If auditing or logging is configured the appropriate callbacks will be called + * and passed the auditdata field + */ +extern int selinux_check_access(const security_context_t scon, const security_context_t tcon, const char *tclass, const char *perm, void *auditdata); + /* Check a permission in the passwd class. Return 0 if granted or -1 otherwise. */ extern int selinux_check_passwd_access(access_vector_t requested); diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3 index f2d9f30..1e36952 100644 --- a/libselinux/man/man3/security_compute_av.3 +++ b/libselinux/man/man3/security_compute_av.3 @@ -24,6 +24,8 @@ the SELinux policy database in the kernel. .BI "int security_get_initial_context(const char *" name ", security_context_t "con ); .sp +.BI "int selinux_check_access(const security_context_t " scon, " const security_context_t " tcon, " const char *" class, " const char *" perm, "void *" auditdata); +.sp .BI "int selinux_check_passwd_access(access_vector_t " requested ); .sp .BI "int checkPasswdAccess(access_vector_t " requested ); @@ -74,6 +76,9 @@ source context. It is mainly used by is used to get the context of a kernel initial security identifier specified by .I name +.B selinux_check_access +is used to check if the source context has the access permission for the specified class on the target context. + .B selinux_check_passwd_access is used to check for a permission in the .I passwd diff --git a/libselinux/src/checkAccess.c b/libselinux/src/checkAccess.c index c1982c7..59c8abb 100644 --- a/libselinux/src/checkAccess.c +++ b/libselinux/src/checkAccess.c @@ -4,8 +4,40 @@ #include <errno.h> #include "selinux_internal.h" #include <selinux/flask.h> +#include <selinux/avc.h> #include <selinux/av_permissions.h> +static pthread_once_t once = PTHREAD_ONCE_INIT; + +static void avc_init_once(void) +{ + avc_open(NULL, 0); +} + +int selinux_check_access(const security_context_t scon, const security_context_t tcon, const char *class, const char *perm, void *aux) { + int status = -1; + int rc = -1; + security_id_t scon_id; + security_id_t tcon_id; + security_class_t sclass; + access_vector_t av; + + if (is_selinux_enabled() == 0) + return 0; + + __selinux_once(once, avc_init_once); + + if ((rc = avc_context_to_sid(scon, &scon_id)) < 0) return rc; + + if ((rc = avc_context_to_sid(tcon, &tcon_id)) < 0) return rc; + + if ((sclass = string_to_security_class(class)) == 0) return status; + + if ((av = string_to_av_perm(sclass, perm)) == 0) return status; + + return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux); +} + int selinux_check_passwd_access(access_vector_t requested) { int status = -1; -- 1.7.7