From b15f72976965d2ae1a1273558bf45be7de077b79 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 15 Dec 2010 22:51:38 +0100 Subject: [PATCH] Cache the security class and bit values and translate the remaining hardcoded values. --- src/cron.c | 4 +++ src/funcs.h | 2 ++ src/security.c | 82 ++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/cron.c b/src/cron.c index 9159164..ac9bba7 100644 --- a/src/cron.c +++ b/src/cron.c @@ -198,6 +198,10 @@ int main(int argc, char *argv[]) { exit(1); } + if (cron_init_security() < 0) { + log_it("CRON", pid, "DEATH", "Critical security parameters not initialized", 0); + } + /* Get the default locale character set for the mail * "Content-Type: ...; charset=" header */ diff --git a/src/funcs.h b/src/funcs.h index fabd0b2..a1645e9 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -85,6 +85,8 @@ long get_gmtoff(time_t *, struct tm *); /* Red Hat security stuff (security.c): */ +int cron_init_security( void ); + void cron_restore_default_security_context( void ); int cron_set_job_security_context( entry *e, user *u, char ***jobenvp ); diff --git a/src/security.c b/src/security.c index 3ea7a1f..65cea73 100644 --- a/src/security.c +++ b/src/security.c @@ -80,6 +80,11 @@ static char **build_env(char **cronenv); static int cron_change_selinux_range(user * u, security_context_t ucontext); static int cron_get_job_range(user * u, security_context_t * ucontextp, char **jobenv); + +static security_class_t file_class; +static security_class_t context_class; +static access_vector_t entrypoint_bit; +static access_vector_t contains_bit; #endif void cron_restore_default_security_context() { @@ -88,6 +93,40 @@ void cron_restore_default_security_context() { #endif } +int cron_init_security() { +#ifdef WITH_SELINUX + int rv = -1; + + if (is_selinux_enabled() <= 0) + return 0; + + if (security_getenforce() <= 0) + rv = 0; + + file_class = string_to_security_class("file"); + if (!file_class) { + log_it("CRON", getpid(), "ERROR", "Failed to translate security class file", errno); + return rv; + } + context_class = string_to_security_class("context"); + if (!context_class) { + log_it("CRON", getpid(), "ERROR", "Failed to translate security class context", errno); + return rv; + } + entrypoint_bit = string_to_av_perm(file_class, "entrypoint"); + if (!entrypoint_bit) { + log_it("CRON", getpid(), "ERROR", "Failed to translate av perm entrypoint", errno); + return rv; + } + contains_bit = string_to_av_perm(context_class, "contains"); + if (!contains_bit) { + log_it("CRON", getpid(), "ERROR", "Failed to translate av perm contains", errno); + return rv; + } +#endif + return 0; +} + int cron_set_job_security_context(entry * e, user * u, char ***jobenv) { time_t minutely_time = 0; #ifdef WITH_PAM @@ -254,12 +293,6 @@ static int cron_authorize_context(security_context_t scontext, struct av_decision avd; int retval; - security_class_t tclass = string_to_security_class("file"); - if (!tclass) - return 0; - access_vector_t bit = string_to_av_perm(tclass, "entrypoint"); - if (!bit) - return 0; /* * Since crontab files are not directly executed, * crond must ensure that the crontab file has @@ -267,9 +300,11 @@ static int cron_authorize_context(security_context_t scontext, * the user cron job. It performs an entrypoint * permission check for this purpose. */ + if (!file_class || !entrypoint_bit) + return 0; retval = security_compute_av(scontext, file_context, - tclass, bit, &avd); - if (retval || ((bit & avd.allowed) != bit)) + file_class, entrypoint_bit, &avd); + if (retval || ((entrypoint_bit & avd.allowed) != entrypoint_bit)) return 0; #endif return 1; @@ -280,16 +315,17 @@ static int cron_authorize_range(security_context_t scontext, #ifdef WITH_SELINUX struct av_decision avd; int retval; - unsigned int bit = CONTEXT__CONTAINS; /* * Since crontab files are not directly executed, * so crond must ensure that any user specified range * falls within the seusers-specified range for that Linux user. */ + if (!context_class || !contains_bit) + return 0; retval = security_compute_av(scontext, ucontext, - SECCLASS_CONTEXT, bit, &avd); + context_class, contains_bit, &avd); - if (retval || ((bit & avd.allowed) != bit)) + if (retval || ((contains_bit & avd.allowed) != contains_bit)) return 0; #endif return 1; @@ -527,22 +563,30 @@ int crontab_security_access(void) { security_context_t user_context; if (getprevcon_raw(&user_context) == 0) { security_class_t passwd_class; + access_vector_t crontab_bit; struct av_decision avd; - int retval; + int retval = 0; passwd_class = string_to_security_class("passwd"); if (passwd_class == 0) { - selinux_check_passwd_access = -1; fprintf(stderr, "Security class \"passwd\" is not defined in the SELinux policy.\n"); + retval = -1; + } + + if (retval == 0) { + crontab_bit = string_to_av_perm(passwd_class, "crontab"); + if (crontab_bit == 0) { + fprintf(stderr, "Security av permission \"crontab\" is not defined in the SELinux policy.\n"); + retval = -1; + } } - retval = security_compute_av_raw(user_context, - user_context, - passwd_class, - PASSWD__CRONTAB, - &avd); + if (retval == 0) + retval = security_compute_av_raw(user_context, + user_context, passwd_class, + crontab_bit, &avd); - if ((retval == 0) && ((PASSWD__CRONTAB & avd.allowed) == PASSWD__CRONTAB)) { + if ((retval == 0) && ((crontab_bit & avd.allowed) == crontab_bit)) { selinux_check_passwd_access = 0; } freecon(user_context); -- 2.40.0