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