int within_range(security_context_t sl, security_context_t range) { int rtn = 1; security_id_t slsid; security_id_t rangesid; struct av_decision avd; security_class_t tclass; access_vector_t av; if (!selinux_ready) { /* mls may not be enabled */ DBG_log("selinux check failed"); return 0; } /* * * Get the sids for the sl and range contexts * */ rtn = avc_context_to_sid(sl, &slsid); if (rtn != 0) { DBG_log( "within_range: Unable to retrieve sid for sl context (%s)", sl); return 0; } rtn = avc_context_to_sid(range, &rangesid); if (rtn != 0) { DBG_log( "within_range: Unable to retrieve sid for range context (%s)", range); sidput(slsid); return 0; } /* ** Straight up test between sl and range **/ tclass = SECCLASS_ASSOCIATION; av = ASSOCIATION__POLMATCH; rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd); if (rtn != 0) { DBG_log( "within_range: The sl (%s) is not within range of (%s)", sl, range); sidput(slsid); sidput(rangesid); return 0; } DBG_log("within_range: The sl (%s) is within range of (%s)", sl, range); return 1; }
/* Check the permission from the caller (via getpeercon) to nscd. Returns 0 if access is allowed, 1 if denied, and -1 on error. */ int nscd_request_avc_has_perm (int fd, request_type req) { /* Initialize to NULL so we know what to free in case of failure. */ security_context_t scon = NULL; security_context_t tcon = NULL; security_id_t ssid = NULL; security_id_t tsid = NULL; int rc = -1; if (getpeercon (fd, &scon) < 0) { dbg_log (_("Error getting context of socket peer")); goto out; } if (getcon (&tcon) < 0) { dbg_log (_("Error getting context of nscd")); goto out; } if (avc_context_to_sid (scon, &ssid) < 0 || avc_context_to_sid (tcon, &tsid) < 0) { dbg_log (_("Error getting sid from context")); goto out; } #ifndef NSCD__GETSERV if (perms[req] == 0) { dbg_log (_("compile-time support for database policy missing")); goto out; } #endif rc = avc_has_perm (ssid, tsid, SECCLASS_NSCD, perms[req], &aeref, NULL) < 0; out: if (scon) freecon (scon); if (tcon) freecon (tcon); if (ssid) sidput (ssid); if (tsid) sidput (tsid); return rc; }
int within_range(security_context_t sl, security_context_t range) { int rtn = 1; security_id_t slsid; security_id_t rangesid; struct av_decision avd; security_class_t tclass; access_vector_t av; if (!selinux_ready) { /* mls may not be enabled */ dbg("selinux check failed"); return 0; } /* * * Get the sids for the sl and range contexts */ rtn = avc_context_to_sid(sl, &slsid); if (rtn != 0) { dbg("within_range: Unable to retrieve sid for sl context (%s)", sl); return 0; } rtn = avc_context_to_sid(range, &rangesid); if (rtn != 0) { dbg("within_range: Unable to retrieve sid for range context (%s)", range); sidput(slsid); return 0; } /* ** Straight up test between sl and range **/ tclass = string_to_security_class("association"); av = string_to_av_perm(tclass, "polmatch"); rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd); if (rtn != 0) { dbg("within_range: The sl (%s) is not within range of (%s)", sl, range); sidput(slsid); sidput(rangesid); return 0; } dbg("within_range: The sl (%s) is within range of (%s)", sl, range); return 1; }
static void mselinux_on_connect(const void *cookie, ENGINE_EVENT_TYPE type, const void *event_data, const void *cb_data) { selinux_engine_t *se = (selinux_engine_t *)cb_data; security_context_t context; security_id_t ssid; int sockfd; sockfd = se->server.core->get_socket_fd(cookie); if (getpeercon_raw(sockfd, &context) < 0) context = "user_u:user_r:user_t:s0"; if (avc_context_to_sid(context, &ssid) < 0) ssid = NULL; se->server.core->store_engine_specific(cookie, ssid); }
/* Check the permission from the caller (via getpeercon) to nscd. Returns 0 if access is allowed, 1 if denied, and -1 on error. The SELinux policy, enablement, and permission bits are all dynamic and the caching done by glibc is not entirely correct. This nscd support should be rewritten to use selinux_check_permission. A rewrite is risky though and requires some refactoring. Currently we use symbolic mappings instead of compile time constants (which SELinux upstream says are going away), and we use security_deny_unknown to determine what to do if selinux-policy* doesn't have a definition for the the permission or object class we are looking up. */ int nscd_request_avc_has_perm (int fd, request_type req) { /* Initialize to NULL so we know what to free in case of failure. */ security_context_t scon = NULL; security_context_t tcon = NULL; security_id_t ssid = NULL; security_id_t tsid = NULL; int rc = -1; security_class_t sc_nscd; access_vector_t perm; int avc_deny_unknown; /* Check if SELinux denys or allows unknown object classes and permissions. It is 0 if they are allowed, 1 if they are not allowed and -1 on error. */ if ((avc_deny_unknown = security_deny_unknown ()) == -1) dbg_log (_("Error querying policy for undefined object classes " "or permissions.")); /* Get the security class for nscd. If this fails we will likely be unable to do anything unless avc_deny_unknown is 0. */ sc_nscd = string_to_security_class ("nscd"); if (sc_nscd == 0 && avc_deny_unknown == 1) dbg_log (_("Error getting security class for nscd.")); /* Convert permission to AVC bits. */ perm = string_to_av_perm (sc_nscd, perms[req]); if (perm == 0 && avc_deny_unknown == 1) dbg_log (_("Error translating permission name " "\"%s\" to access vector bit."), perms[req]); /* If the nscd security class was not found or perms were not found and AVC does not deny unknown values then allow it. */ if ((sc_nscd == 0 || perm == 0) && avc_deny_unknown == 0) return 0; if (getpeercon (fd, &scon) < 0) { dbg_log (_("Error getting context of socket peer")); goto out; } if (getcon (&tcon) < 0) { dbg_log (_("Error getting context of nscd")); goto out; } if (avc_context_to_sid (scon, &ssid) < 0 || avc_context_to_sid (tcon, &tsid) < 0) { dbg_log (_("Error getting sid from context")); goto out; } /* The SELinux API for avc_has_perm conflates access denied and error into the return code -1, while nscd_request_avs_has_perm has distinct error (-1) and denied (1) return codes. We map the avc_has_perm access denied or error into an access denied at the nscd interface level (we do accurately report error for the getpeercon, getcon, and avc_context_to_sid interfaces used above). */ rc = avc_has_perm (ssid, tsid, sc_nscd, perm, &aeref, NULL) < 0; out: if (scon) freecon (scon); if (tcon) freecon (tcon); if (ssid) sidput (ssid); if (tsid) sidput (tsid); return rc; }