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