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