16cd6a6acSopenharmony_ci/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
26cd6a6acSopenharmony_ci#include <unistd.h>
36cd6a6acSopenharmony_ci#include <sys/types.h>
46cd6a6acSopenharmony_ci#include <stdlib.h>
56cd6a6acSopenharmony_ci#include <errno.h>
66cd6a6acSopenharmony_ci#include "selinux_internal.h"
76cd6a6acSopenharmony_ci#include <selinux/avc.h>
86cd6a6acSopenharmony_ci#include "avc_internal.h"
96cd6a6acSopenharmony_ci
106cd6a6acSopenharmony_cistatic pthread_once_t once = PTHREAD_ONCE_INIT;
116cd6a6acSopenharmony_cistatic int selinux_enabled;
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_cistatic void avc_init_once(void)
146cd6a6acSopenharmony_ci{
156cd6a6acSopenharmony_ci	selinux_enabled = is_selinux_enabled();
166cd6a6acSopenharmony_ci	if (selinux_enabled == 1) {
176cd6a6acSopenharmony_ci		if (avc_open(NULL, 0))
186cd6a6acSopenharmony_ci			return;
196cd6a6acSopenharmony_ci	}
206cd6a6acSopenharmony_ci}
216cd6a6acSopenharmony_ci
226cd6a6acSopenharmony_ciint selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
236cd6a6acSopenharmony_ci	int rc;
246cd6a6acSopenharmony_ci	security_id_t scon_id;
256cd6a6acSopenharmony_ci	security_id_t tcon_id;
266cd6a6acSopenharmony_ci	security_class_t sclass;
276cd6a6acSopenharmony_ci	access_vector_t av;
286cd6a6acSopenharmony_ci
296cd6a6acSopenharmony_ci	__selinux_once(once, avc_init_once);
306cd6a6acSopenharmony_ci
316cd6a6acSopenharmony_ci	if (selinux_enabled != 1)
326cd6a6acSopenharmony_ci		return 0;
336cd6a6acSopenharmony_ci
346cd6a6acSopenharmony_ci	rc = avc_context_to_sid(scon, &scon_id);
356cd6a6acSopenharmony_ci	if (rc < 0)
366cd6a6acSopenharmony_ci		return rc;
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_ci	rc = avc_context_to_sid(tcon, &tcon_id);
396cd6a6acSopenharmony_ci	if (rc < 0)
406cd6a6acSopenharmony_ci		return rc;
416cd6a6acSopenharmony_ci
426cd6a6acSopenharmony_ci	(void) selinux_status_updated();
436cd6a6acSopenharmony_ci
446cd6a6acSopenharmony_ci       sclass = string_to_security_class(class);
456cd6a6acSopenharmony_ci       if (sclass == 0) {
466cd6a6acSopenharmony_ci	       rc = errno;
476cd6a6acSopenharmony_ci	       avc_log(SELINUX_ERROR, "Unknown class %s", class);
486cd6a6acSopenharmony_ci	       if (security_deny_unknown() == 0)
496cd6a6acSopenharmony_ci		       return 0;
506cd6a6acSopenharmony_ci	       errno = rc;
516cd6a6acSopenharmony_ci	       return -1;
526cd6a6acSopenharmony_ci       }
536cd6a6acSopenharmony_ci
546cd6a6acSopenharmony_ci       av = string_to_av_perm(sclass, perm);
556cd6a6acSopenharmony_ci       if (av == 0) {
566cd6a6acSopenharmony_ci	       rc = errno;
576cd6a6acSopenharmony_ci	       avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
586cd6a6acSopenharmony_ci	       if (security_deny_unknown() == 0)
596cd6a6acSopenharmony_ci		       return 0;
606cd6a6acSopenharmony_ci	       errno = rc;
616cd6a6acSopenharmony_ci	       return -1;
626cd6a6acSopenharmony_ci       }
636cd6a6acSopenharmony_ci
646cd6a6acSopenharmony_ci       return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
656cd6a6acSopenharmony_ci}
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_cistatic int selinux_check_passwd_access_internal(access_vector_t requested)
686cd6a6acSopenharmony_ci{
696cd6a6acSopenharmony_ci	int status = -1;
706cd6a6acSopenharmony_ci	char *user_context;
716cd6a6acSopenharmony_ci	if (is_selinux_enabled() == 0)
726cd6a6acSopenharmony_ci		return 0;
736cd6a6acSopenharmony_ci	if (getprevcon_raw(&user_context) == 0) {
746cd6a6acSopenharmony_ci		security_class_t passwd_class;
756cd6a6acSopenharmony_ci		struct av_decision avd;
766cd6a6acSopenharmony_ci		int retval;
776cd6a6acSopenharmony_ci
786cd6a6acSopenharmony_ci		passwd_class = string_to_security_class("passwd");
796cd6a6acSopenharmony_ci		if (passwd_class == 0) {
806cd6a6acSopenharmony_ci			freecon(user_context);
816cd6a6acSopenharmony_ci			if (security_deny_unknown() == 0)
826cd6a6acSopenharmony_ci				return 0;
836cd6a6acSopenharmony_ci			return -1;
846cd6a6acSopenharmony_ci		}
856cd6a6acSopenharmony_ci
866cd6a6acSopenharmony_ci		retval = security_compute_av_raw(user_context,
876cd6a6acSopenharmony_ci						     user_context,
886cd6a6acSopenharmony_ci						     passwd_class,
896cd6a6acSopenharmony_ci						     requested,
906cd6a6acSopenharmony_ci						     &avd);
916cd6a6acSopenharmony_ci
926cd6a6acSopenharmony_ci		if ((retval == 0) && ((requested & avd.allowed) == requested)) {
936cd6a6acSopenharmony_ci			status = 0;
946cd6a6acSopenharmony_ci		}
956cd6a6acSopenharmony_ci		freecon(user_context);
966cd6a6acSopenharmony_ci	}
976cd6a6acSopenharmony_ci
986cd6a6acSopenharmony_ci	if (status != 0 && security_getenforce() == 0)
996cd6a6acSopenharmony_ci		status = 0;
1006cd6a6acSopenharmony_ci
1016cd6a6acSopenharmony_ci	return status;
1026cd6a6acSopenharmony_ci}
1036cd6a6acSopenharmony_ci
1046cd6a6acSopenharmony_ciint selinux_check_passwd_access(access_vector_t requested) {
1056cd6a6acSopenharmony_ci	return selinux_check_passwd_access_internal(requested);
1066cd6a6acSopenharmony_ci}
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_ciint checkPasswdAccess(access_vector_t requested)
1096cd6a6acSopenharmony_ci{
1106cd6a6acSopenharmony_ci	return selinux_check_passwd_access_internal(requested);
1116cd6a6acSopenharmony_ci}
112