xref: /aosp_15_r20/external/selinux/libselinux/src/checkAccess.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
3*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
4*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
5*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
6*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
7*2d543d20SAndroid Build Coastguard Worker #include <selinux/avc.h>
8*2d543d20SAndroid Build Coastguard Worker #include "avc_internal.h"
9*2d543d20SAndroid Build Coastguard Worker 
10*2d543d20SAndroid Build Coastguard Worker static pthread_once_t once = PTHREAD_ONCE_INIT;
11*2d543d20SAndroid Build Coastguard Worker static int selinux_enabled;
12*2d543d20SAndroid Build Coastguard Worker 
avc_init_once(void)13*2d543d20SAndroid Build Coastguard Worker static void avc_init_once(void)
14*2d543d20SAndroid Build Coastguard Worker {
15*2d543d20SAndroid Build Coastguard Worker 	selinux_enabled = is_selinux_enabled();
16*2d543d20SAndroid Build Coastguard Worker 	if (selinux_enabled == 1) {
17*2d543d20SAndroid Build Coastguard Worker 		if (avc_open(NULL, 0))
18*2d543d20SAndroid Build Coastguard Worker 			return;
19*2d543d20SAndroid Build Coastguard Worker 	}
20*2d543d20SAndroid Build Coastguard Worker }
21*2d543d20SAndroid Build Coastguard Worker 
selinux_check_access(const char * scon,const char * tcon,const char * class,const char * perm,void * aux)22*2d543d20SAndroid Build Coastguard Worker int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
23*2d543d20SAndroid Build Coastguard Worker 	int rc;
24*2d543d20SAndroid Build Coastguard Worker 	security_id_t scon_id;
25*2d543d20SAndroid Build Coastguard Worker 	security_id_t tcon_id;
26*2d543d20SAndroid Build Coastguard Worker 	security_class_t sclass;
27*2d543d20SAndroid Build Coastguard Worker 	access_vector_t av;
28*2d543d20SAndroid Build Coastguard Worker 
29*2d543d20SAndroid Build Coastguard Worker 	__selinux_once(once, avc_init_once);
30*2d543d20SAndroid Build Coastguard Worker 
31*2d543d20SAndroid Build Coastguard Worker 	if (selinux_enabled != 1)
32*2d543d20SAndroid Build Coastguard Worker 		return 0;
33*2d543d20SAndroid Build Coastguard Worker 
34*2d543d20SAndroid Build Coastguard Worker 	rc = avc_context_to_sid(scon, &scon_id);
35*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
36*2d543d20SAndroid Build Coastguard Worker 		return rc;
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker 	rc = avc_context_to_sid(tcon, &tcon_id);
39*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
40*2d543d20SAndroid Build Coastguard Worker 		return rc;
41*2d543d20SAndroid Build Coastguard Worker 
42*2d543d20SAndroid Build Coastguard Worker 	(void) selinux_status_updated();
43*2d543d20SAndroid Build Coastguard Worker 
44*2d543d20SAndroid Build Coastguard Worker        sclass = string_to_security_class(class);
45*2d543d20SAndroid Build Coastguard Worker        if (sclass == 0) {
46*2d543d20SAndroid Build Coastguard Worker 	       rc = errno;
47*2d543d20SAndroid Build Coastguard Worker 	       avc_log(SELINUX_ERROR, "Unknown class %s", class);
48*2d543d20SAndroid Build Coastguard Worker 	       if (security_deny_unknown() == 0)
49*2d543d20SAndroid Build Coastguard Worker 		       return 0;
50*2d543d20SAndroid Build Coastguard Worker 	       errno = rc;
51*2d543d20SAndroid Build Coastguard Worker 	       return -1;
52*2d543d20SAndroid Build Coastguard Worker        }
53*2d543d20SAndroid Build Coastguard Worker 
54*2d543d20SAndroid Build Coastguard Worker        av = string_to_av_perm(sclass, perm);
55*2d543d20SAndroid Build Coastguard Worker        if (av == 0) {
56*2d543d20SAndroid Build Coastguard Worker 	       rc = errno;
57*2d543d20SAndroid Build Coastguard Worker 	       avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
58*2d543d20SAndroid Build Coastguard Worker 	       if (security_deny_unknown() == 0)
59*2d543d20SAndroid Build Coastguard Worker 		       return 0;
60*2d543d20SAndroid Build Coastguard Worker 	       errno = rc;
61*2d543d20SAndroid Build Coastguard Worker 	       return -1;
62*2d543d20SAndroid Build Coastguard Worker        }
63*2d543d20SAndroid Build Coastguard Worker 
64*2d543d20SAndroid Build Coastguard Worker        return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
65*2d543d20SAndroid Build Coastguard Worker }
66*2d543d20SAndroid Build Coastguard Worker 
selinux_check_passwd_access_internal(access_vector_t requested)67*2d543d20SAndroid Build Coastguard Worker static int selinux_check_passwd_access_internal(access_vector_t requested)
68*2d543d20SAndroid Build Coastguard Worker {
69*2d543d20SAndroid Build Coastguard Worker 	int status = -1;
70*2d543d20SAndroid Build Coastguard Worker 	char *user_context;
71*2d543d20SAndroid Build Coastguard Worker 	if (is_selinux_enabled() == 0)
72*2d543d20SAndroid Build Coastguard Worker 		return 0;
73*2d543d20SAndroid Build Coastguard Worker 	if (getprevcon_raw(&user_context) == 0) {
74*2d543d20SAndroid Build Coastguard Worker 		security_class_t passwd_class;
75*2d543d20SAndroid Build Coastguard Worker 		struct av_decision avd;
76*2d543d20SAndroid Build Coastguard Worker 		int retval;
77*2d543d20SAndroid Build Coastguard Worker 
78*2d543d20SAndroid Build Coastguard Worker 		passwd_class = string_to_security_class("passwd");
79*2d543d20SAndroid Build Coastguard Worker 		if (passwd_class == 0) {
80*2d543d20SAndroid Build Coastguard Worker 			freecon(user_context);
81*2d543d20SAndroid Build Coastguard Worker 			if (security_deny_unknown() == 0)
82*2d543d20SAndroid Build Coastguard Worker 				return 0;
83*2d543d20SAndroid Build Coastguard Worker 			return -1;
84*2d543d20SAndroid Build Coastguard Worker 		}
85*2d543d20SAndroid Build Coastguard Worker 
86*2d543d20SAndroid Build Coastguard Worker 		retval = security_compute_av_raw(user_context,
87*2d543d20SAndroid Build Coastguard Worker 						     user_context,
88*2d543d20SAndroid Build Coastguard Worker 						     passwd_class,
89*2d543d20SAndroid Build Coastguard Worker 						     requested,
90*2d543d20SAndroid Build Coastguard Worker 						     &avd);
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker 		if ((retval == 0) && ((requested & avd.allowed) == requested)) {
93*2d543d20SAndroid Build Coastguard Worker 			status = 0;
94*2d543d20SAndroid Build Coastguard Worker 		}
95*2d543d20SAndroid Build Coastguard Worker 		freecon(user_context);
96*2d543d20SAndroid Build Coastguard Worker 	}
97*2d543d20SAndroid Build Coastguard Worker 
98*2d543d20SAndroid Build Coastguard Worker 	if (status != 0 && security_getenforce() == 0)
99*2d543d20SAndroid Build Coastguard Worker 		status = 0;
100*2d543d20SAndroid Build Coastguard Worker 
101*2d543d20SAndroid Build Coastguard Worker 	return status;
102*2d543d20SAndroid Build Coastguard Worker }
103*2d543d20SAndroid Build Coastguard Worker 
selinux_check_passwd_access(access_vector_t requested)104*2d543d20SAndroid Build Coastguard Worker int selinux_check_passwd_access(access_vector_t requested) {
105*2d543d20SAndroid Build Coastguard Worker 	return selinux_check_passwd_access_internal(requested);
106*2d543d20SAndroid Build Coastguard Worker }
107*2d543d20SAndroid Build Coastguard Worker 
checkPasswdAccess(access_vector_t requested)108*2d543d20SAndroid Build Coastguard Worker int checkPasswdAccess(access_vector_t requested)
109*2d543d20SAndroid Build Coastguard Worker {
110*2d543d20SAndroid Build Coastguard Worker 	return selinux_check_passwd_access_internal(requested);
111*2d543d20SAndroid Build Coastguard Worker }
112