1c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ 213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h> 313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h> 413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h> 513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h> 613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h" 79c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh#include <selinux/avc.h> 87bdc38ccb21133155658279895b10ceb347b0b5aStephen Smalley#include "avc_internal.h" 913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 109c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walshstatic pthread_once_t once = PTHREAD_ONCE_INIT; 112fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalleystatic int selinux_enabled; 129c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh 13b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalleystatic int avc_reset_callback(uint32_t event __attribute__((unused)), 14b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley security_id_t ssid __attribute__((unused)), 15b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley security_id_t tsid __attribute__((unused)), 16b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley security_class_t tclass __attribute__((unused)), 17b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley access_vector_t perms __attribute__((unused)), 18b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley access_vector_t *out_retained __attribute__((unused))) 19b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley{ 20b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley flush_class_cache(); 21b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley return 0; 22b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley} 23b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley 249c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walshstatic void avc_init_once(void) 259c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh{ 262fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley selinux_enabled = is_selinux_enabled(); 27b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley if (selinux_enabled == 1) { 28b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley if (avc_open(NULL, 0)) 29b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley return; 30b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley avc_add_callback(avc_reset_callback, AVC_CALLBACK_RESET, 31b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley 0, 0, 0, 0); 32b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley } 339c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh} 349c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh 359eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) { 36c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh int rc; 379c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh security_id_t scon_id; 389c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh security_id_t tcon_id; 399c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh security_class_t sclass; 409c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh access_vector_t av; 419c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh 429c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh __selinux_once(once, avc_init_once); 439c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh 442fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley if (selinux_enabled != 1) 452fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley return 0; 462fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley 47c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh rc = avc_context_to_sid(scon, &scon_id); 48c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh if (rc < 0) 49c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return rc; 50c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh 51b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley rc = avc_context_to_sid(tcon, &tcon_id); 52b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley if (rc < 0) 53b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley return rc; 54b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley 55b408d72ca9104cb0c1bc4e154d8732cc7c0a9190Stephen Smalley (void) avc_netlink_check_nb(); 56c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh 57c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh sclass = string_to_security_class(class); 58c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh if (sclass == 0) { 59c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh rc = errno; 607bdc38ccb21133155658279895b10ceb347b0b5aStephen Smalley avc_log(SELINUX_ERROR, "Unknown class %s", class); 61c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh if (security_deny_unknown() == 0) 62c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return 0; 63c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh errno = rc; 64c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return -1; 65c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh } 66c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh 67c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh av = string_to_av_perm(sclass, perm); 68c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh if (av == 0) { 69c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh rc = errno; 707bdc38ccb21133155658279895b10ceb347b0b5aStephen Smalley avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class); 71c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh if (security_deny_unknown() == 0) 72c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return 0; 73c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh errno = rc; 74c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return -1; 75c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh } 76c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh 77c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux); 789c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh} 799c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh 8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint selinux_check_passwd_access(access_vector_t requested) 8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{ 8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle int status = -1; 839eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley char *user_context; 8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (is_selinux_enabled() == 0) 8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle return 0; 8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (getprevcon_raw(&user_context) == 0) { 8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle security_class_t passwd_class; 8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle struct av_decision avd; 8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle int retval; 9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle passwd_class = string_to_security_class("passwd"); 9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (passwd_class == 0) 9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle return 0; 9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle retval = security_compute_av_raw(user_context, 9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle user_context, 9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle passwd_class, 9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle requested, 9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle &avd); 10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if ((retval == 0) && ((requested & avd.allowed) == requested)) { 10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle status = 0; 10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle freecon(user_context); 10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle } 10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle if (status != 0 && security_getenforce() == 0) 10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle status = 0; 10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle return status; 11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} 11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_check_passwd_access) 11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle 11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint checkPasswdAccess(access_vector_t requested) 11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{ 11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle return selinux_check_passwd_access(requested); 11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle} 119