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
139c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walshstatic void avc_init_once(void)
149c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh{
152fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley	selinux_enabled = is_selinux_enabled();
162fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley	if (selinux_enabled == 1)
172fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley		avc_open(NULL, 0);
189c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh}
199c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh
209eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
21c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	int rc;
229c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh	security_id_t scon_id;
239c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh	security_id_t tcon_id;
249c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh	security_class_t sclass;
259c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh	access_vector_t av;
269c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh
279c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh	__selinux_once(once, avc_init_once);
289c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh
292fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley	if (selinux_enabled != 1)
302fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley		return 0;
312fa21cc840bce76274ba5d1b9ddbb0abebfaf06dStephen Smalley
32c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	rc = avc_context_to_sid(scon, &scon_id);
33c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	if (rc < 0)
34c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh		return rc;
35c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh
36c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       rc = avc_context_to_sid(tcon, &tcon_id);
37c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       if (rc < 0)
38c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       return rc;
39c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh
40c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       sclass = string_to_security_class(class);
41c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       if (sclass == 0) {
42c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       rc = errno;
437bdc38ccb21133155658279895b10ceb347b0b5aStephen Smalley	       avc_log(SELINUX_ERROR, "Unknown class %s", class);
44c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       if (security_deny_unknown() == 0)
45c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh		       return 0;
46c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       errno = rc;
47c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       return -1;
48c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       }
49c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh
50c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       av = string_to_av_perm(sclass, perm);
51c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       if (av == 0) {
52c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       rc = errno;
537bdc38ccb21133155658279895b10ceb347b0b5aStephen Smalley	       avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
54c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       if (security_deny_unknown() == 0)
55c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh		       return 0;
56c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       errno = rc;
57c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh	       return -1;
58c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       }
59c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh
60c7d749efe2fa6f1e765b0bc215476d533f1b4d7bDan Walsh       return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
619c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh}
629c46a0a3153124753e3afbd2090fea65a09e1df1Dan Walsh
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint selinux_check_passwd_access(access_vector_t requested)
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int status = -1;
669eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char *user_context;
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (is_selinux_enabled() == 0)
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (getprevcon_raw(&user_context) == 0) {
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		security_class_t passwd_class;
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		struct av_decision avd;
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		int retval;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		passwd_class = string_to_security_class("passwd");
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (passwd_class == 0)
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return 0;
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		retval = security_compute_av_raw(user_context,
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						     user_context,
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						     passwd_class,
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						     requested,
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						     &avd);
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if ((retval == 0) && ((requested & avd.allowed) == requested)) {
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			status = 0;
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		freecon(user_context);
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (status != 0 && security_getenforce() == 0)
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		status = 0;
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return status;
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_check_passwd_access)
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint checkPasswdAccess(access_vector_t requested)
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return selinux_check_passwd_access(requested);
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
102