/* * selinux_file_context - Set the security context before any file or * directory creation. * * selinux_file_context () should be called before any creation of file, * symlink, directory, ... * * Callers may have to Reset SELinux to create files with default * contexts: * setfscreatecon (NULL); */ int selinux_file_context (const char *dst_name) { static bool selinux_checked = false; static bool selinux_enabled; security_context_t scontext = NULL; if (!selinux_checked) { selinux_enabled = is_selinux_enabled () > 0; selinux_checked = true; } if (selinux_enabled) { /* Get the default security context for this file */ if (matchpathcon (dst_name, 0, &scontext) < 0) { if (security_getenforce () != 0) { return 1; } } /* Set the security context for the next created file */ if (setfscreatecon (scontext) < 0) { if (security_getenforce () != 0) { return 1; } } freecon (scontext); } return 0; }
/* Attempt to change the label of PATH to TCON. If OPTIONAL is true, * return 1 if labelling was not possible. Otherwise, require a label * change, and return 0 for success, -1 for failure. */ static int SELinuxSetFileconHelper(const char *path, char *tcon, bool optional) { security_context_t econ; VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon); if (setfilecon(path, tcon) < 0) { int setfilecon_errno = errno; if (getfilecon(path, &econ) >= 0) { if (STREQ(tcon, econ)) { freecon(econ); /* It's alright, there's nothing to change anyway. */ return optional ? 1 : 0; } freecon(econ); } /* if the error complaint is related to an image hosted on * an nfs mount, or a usbfs/sysfs filesystem not supporting * labelling, then just ignore it & hope for the best. * The user hopefully set one of the necessary SELinux * virt_use_{nfs,usb,pci} boolean tunables to allow it... */ if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP) { virReportSystemError(setfilecon_errno, _("unable to set security context '%s' on '%s'"), tcon, path); if (security_getenforce() == 1) return -1; } else { const char *msg; if ((virStorageFileIsSharedFSType(path, VIR_STORAGE_FILE_SHFS_NFS) == 1) && security_get_boolean_active("virt_use_nfs") != 1) { msg = _("Setting security context '%s' on '%s' not supported. " "Consider setting virt_use_nfs"); if (security_getenforce() == 1) VIR_WARN(msg, tcon, path); else VIR_INFO(msg, tcon, path); } else { VIR_INFO("Setting security context '%s' on '%s' not supported", tcon, path); } if (optional) return 1; } } return 0; }
static int SELinuxGetSecurityProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainObjPtr vm, virSecurityLabelPtr sec) { security_context_t ctx; if (getpidcon(vm->pid, &ctx) == -1) { virReportSystemError(errno, _("unable to get PID %d security context"), vm->pid); return -1; } if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) { virSecurityReportError(VIR_ERR_INTERNAL_ERROR, _("security label exceeds " "maximum length: %d"), VIR_SECURITY_LABEL_BUFLEN - 1); freecon(ctx); return -1; } strcpy(sec->label, (char *) ctx); freecon(ctx); sec->enforcing = security_getenforce(); if (sec->enforcing == -1) { virReportSystemError(errno, "%s", _("error calling security_getenforce()")); return -1; } return 0; }
static const security_context_t selinux_get_user_context(const char *name) { security_context_t user_context=NULL; char *role=NULL; int ret = -1; char *seuser=NULL; char *level=NULL; if (the_authctxt) role=the_authctxt->role; if (getseuserbyname(name, &seuser, &level)==0) { if (role != NULL && role[0]) ret=get_default_context_with_rolelevel(seuser, role, level,NULL, &user_context); else ret=get_default_context_with_level(seuser, level, NULL,&user_context); } if ( ret < 0 ) { if (security_getenforce() > 0) fatal("Failed to get default security context for %s.", name); else error("Failed to get default security context for %s." "Continuing in permissive mode", name); } return user_context; }
int getenforce_main(int argc, char **argv) { int rc; rc = is_selinux_enabled(); if (rc < 0) { bb_error_msg("is_selinux_enabled() failed"); return 2; } if (rc == 1) { rc = security_getenforce(); if (rc < 0) { bb_error_msg("getenforce() failed"); return 2; } if (rc) puts("Enforcing"); else puts("Permissive"); } else { puts("Disabled"); } return 0; }
static int access_init(sd_bus_error *error) { if (!mac_selinux_use()) return 0; if (initialized) return 1; if (avc_open(NULL, 0) != 0) { int enforce, saved_errno = errno; enforce = security_getenforce(); log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m"); /* If enforcement isn't on, then let's suppress this * error, and just don't do any AVC checks. The * warning we printed is hence all the admin will * see. */ if (enforce == 0) return 0; /* Return an access denied error, if we couldn't load * the AVC but enforcing mode was on, or we couldn't * determine whether it is one. */ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror(saved_errno)); } selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); initialized = true; return 1; }
int main(int argc __attribute__ ((unused)), char **argv) { int rc; rc = is_selinux_enabled(); if (rc < 0) { fputs("getenforce: is_selinux_enabled() failed", stderr); return 2; } if (rc == 1) { rc = security_getenforce(); if (rc < 0) { fputs("getenforce: getenforce() failed", stderr); return 2; } if (rc) puts("Enforcing"); else puts("Permissive"); } else { puts("Disabled"); } return 0; }
/* * Function: isSELinuxEnforced * Purpose: return the current SELinux enforce mode * Parameters: none * Return value: true (enforcing) or false (permissive) * Exceptions: none */ static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) { #ifdef HAVE_SELINUX return (security_getenforce() == 1) ? true : false; #else return false; #endif }
/* Set the execution context to the default for the specified user */ void ssh_selinux_setup_exec_context(char *pwname) { security_context_t user_ctx = NULL; if (!ssh_selinux_enabled()) return; debug3("%s: setting execution context", __func__); user_ctx = ssh_selinux_getctxbyname(pwname); if (setexeccon(user_ctx) != 0) { switch (security_getenforce()) { case -1: fatal("%s: security_getenforce() failed", __func__); case 0: error("%s: Failed to set SELinux execution " "context for %s", __func__, pwname); break; default: fatal("%s: Failed to set SELinux execution context " "for %s (in enforcing mode)", __func__, pwname); } } if (user_ctx != NULL) freecon(user_ctx); debug3("%s: done", __func__); }
int label_socket_set(const char *label) { #ifdef HAVE_SELINUX if (!use_selinux()) return 0; if (setsockcreatecon((security_context_t) label) < 0) { log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to set SELinux context (%s) on socket: %m", label); if (security_getenforce() == 1) return -errno; } #endif return 0; }
static int selinux_file_context (const char *dst_name) { security_context_t scontext = NULL; if (selinux_enabled < 0) selinux_enabled = is_selinux_enabled () > 0; if (selinux_enabled) { if (matchpathcon (dst_name, 0, &scontext) < 0) if (security_getenforce ()) return 1; if (setfscreatecon (scontext) < 0) if (security_getenforce ()) return 1; freecon (scontext); } return 0; }
int sestatus_main(int argc, char **argv) { unsigned opts; const char *pol_path; int rc; opt_complementary = "?0"; /* no arguments are required. */ opts = getopt32(argv, "vb"); /* SELinux status: line */ rc = is_selinux_enabled(); if (rc < 0) goto error; printf(COL_FMT "%s\n", "SELinux status:", rc == 1 ? "enabled" : "disabled"); /* SELinuxfs mount: line */ if (!selinux_mnt) goto error; printf(COL_FMT "%s\n", "SELinuxfs mount:", selinux_mnt); /* Current mode: line */ rc = security_getenforce(); if (rc < 0) goto error; printf(COL_FMT "%s\n", "Current mode:", rc == 0 ? "permissive" : "enforcing"); /* Mode from config file: line */ if (selinux_getenforcemode(&rc) != 0) goto error; printf(COL_FMT "%s\n", "Mode from config file:", rc < 0 ? "disabled" : (rc == 0 ? "permissive" : "enforcing")); /* Policy version: line */ rc = security_policyvers(); if (rc < 0) goto error; printf(COL_FMT "%u\n", "Policy version:", rc); /* Policy from config file: line */ pol_path = selinux_policy_root(); if (!pol_path) goto error; printf(COL_FMT "%s\n", "Policy from config file:", bb_basename(pol_path)); if (opts & OPT_BOOLEAN) display_boolean(); if (opts & OPT_VERBOSE) display_verbose(); return 0; error: bb_perror_msg_and_die("libselinux returns unknown state"); }
/* * sepgsql_getenforce * * It returns whether the current working mode tries to enforce access * control decision, or not. It shall be enforced when sepgsql_mode is * SEPGSQL_MODE_DEFAULT and system is running in enforcing mode. */ bool sepgsql_getenforce(void) { if (sepgsql_mode == SEPGSQL_MODE_DEFAULT && security_getenforce() > 0) return true; return false; }
/** Initialize Xposed (unless it is disabled). */ bool initialize(bool zygote, bool startSystemServer, const char* className, int argc, char* const argv[]) { #if !defined(XPOSED_ENABLE_FOR_TOOLS) if (!zygote) return false; #endif if (isMinimalFramework()) { ALOGI("Not loading Xposed for minimal framework (encrypted device)"); return false; } xposed->zygote = zygote; xposed->startSystemServer = startSystemServer; xposed->startClassName = className; xposed->xposedVersionInt = xposedVersionInt; #if XPOSED_WITH_SELINUX xposed->isSELinuxEnabled = is_selinux_enabled() == 1; xposed->isSELinuxEnforcing = xposed->isSELinuxEnabled && security_getenforce() == 1; #else xposed->isSELinuxEnabled = false; xposed->isSELinuxEnforcing = false; #endif // XPOSED_WITH_SELINUX if (startSystemServer) { xposed::logcat::start(); } else if (zygote) { // TODO Find a better solution for this // Give the primary Zygote process a little time to start first. // This also makes the log easier to read, as logs for the two Zygotes are not mixed up. sleep(10); } printRomInfo(); if (startSystemServer) { if (!xposed::service::startAll()) return false; #if XPOSED_WITH_SELINUX } else if (xposed->isSELinuxEnabled) { if (!xposed::service::startMembased()) return false; #endif // XPOSED_WITH_SELINUX } // FIXME Zygote has no access to input devices, this would need to be check in system_server context if (zygote && !isSafemodeDisabled() && detectSafemodeTrigger(shouldSkipSafemodeDelay())) disableXposed(); if (isDisabled() || (!zygote && shouldIgnoreCommand(argc, argv))) return false; return addJarToClasspath(); }
int label_fix(const char *path, bool ignore_enoent) { int r = 0; #ifdef HAVE_SELINUX struct stat st; security_context_t fcon; if (!use_selinux() || !label_hnd) return 0; r = lstat(path, &st); if (r == 0) { r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r == 0) { r = setfilecon(path, fcon); freecon(fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == ENOTSUP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Unable to fix label of %s: %m", path); r = security_getenforce() == 1 ? -errno : 0; } #endif return r; }
int label_init(void) { int r = 0; #ifdef HAVE_SELINUX if (!use_selinux()) return 0; if (label_hnd) return 0; label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); if (!label_hnd) { log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m"); r = security_getenforce() == 1 ? -errno : 0; } #endif return r; }
/* * Set the exec and tty contexts in preparation for fork/exec. * Must run as root, before the uid change. * If ptyfd is not -1, it indicates we are running * in a pty and do not need to reset std{in,out,err}. * Returns 0 on success and -1 on failure. */ int selinux_setup(const char *role, const char *type, const char *ttyn, int ptyfd) { int ret = -1; debug_decl(selinux_setup, SUDO_DEBUG_SELINUX) /* Store the caller's SID in old_context. */ if (getprevcon(&se_state.old_context)) { sudo_warn(U_("failed to get old_context")); goto done; } se_state.enforcing = security_getenforce(); if (se_state.enforcing < 0) { sudo_warn(U_("unable to determine enforcing mode.")); goto done; } #ifdef DEBUG sudo_warnx("your old context was %s", se_state.old_context); #endif se_state.new_context = get_exec_context(se_state.old_context, role, type); if (!se_state.new_context) { #ifdef HAVE_LINUX_AUDIT audit_role_change(se_state.old_context, "?", se_state.ttyn, 0); #endif goto done; } if (relabel_tty(ttyn, ptyfd) < 0) { sudo_warn(U_("unable to set tty context to %s"), se_state.new_context); goto done; } #ifdef DEBUG if (se_state.ttyfd != -1) { sudo_warnx("your old tty context is %s", se_state.tty_context); sudo_warnx("your new tty context is %s", se_state.new_tty_context); } #endif #ifdef HAVE_LINUX_AUDIT audit_role_change(se_state.old_context, se_state.new_context, se_state.ttyn, 1); #endif ret = 0; done: debug_return_int(ret); }
/* * selinux_file_context - Set the security context before any file or * directory creation. * * selinux_file_context () should be called before any creation of file, * symlink, directory, ... * * Callers may have to Reset SELinux to create files with default * contexts: * reset_selinux_file_context(); */ int selinux_file_context(const char *dst_name) { security_context_t scontext = NULL; if (is_selinux_enabled() == 1) { /* Get the default security context for this file */ if (matchpathcon(dst_name, 0, &scontext) < 0) { if (security_getenforce () != 0) { return 1; } } /* Set the security context for the next created file */ if (setfscreatecon(scontext) < 0) { if (security_getenforce() != 0) { return 1; } } freecon(scontext); } return 0; }
int label_mkdir( const char *path, mode_t mode) { /* Creates a directory and labels it according to the SELinux policy */ #ifdef HAVE_SELINUX int r; security_context_t fcon = NULL; if (use_selinux() && label_hnd) { if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &fcon, path, mode); else { char *newpath = NULL; if (!(newpath = path_make_absolute_cwd(path))) return -ENOMEM; r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode); free(newpath); } if (r == 0) r = setfscreatecon(fcon); if (r < 0 && errno != ENOENT) { log_error("Failed to set security context %s for %s: %m", fcon, path); r = -errno; if (security_getenforce() == 1) goto finish; } } if ((r = mkdir(path, mode)) < 0) r = -errno; finish: if (use_selinux() && label_hnd) { setfscreatecon(NULL); freecon(fcon); } return r; #else return mkdir(path, mode); #endif }
/* Function must be called once to initialize the SELinux AVC environment. Sets up callbacks. If you want to cleanup memory you should need to call selinux_access_finish. */ static int access_init(void) { int r = 0; if (avc_open(NULL, 0)) return log_error_errno(errno, "avc_open() failed: %m"); selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); if (security_getenforce() < 0){ r = -errno; avc_destroy(); } return r; }
/* Return the default security context for the given username */ static security_context_t ssh_selinux_getctxbyname(char *pwname) { security_context_t sc = NULL; char *sename = NULL, *lvl = NULL; int r; #ifdef HAVE_GETSEUSERBYNAME if (getseuserbyname(pwname, &sename, &lvl) != 0) return NULL; #else sename = pwname; lvl = NULL; #endif #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL r = get_default_context_with_level(sename, lvl, NULL, &sc); #else r = get_default_context(sename, NULL, &sc); #endif if (r != 0) { switch (security_getenforce()) { case -1: fatal("%s: ssh_selinux_getctxbyname: " "security_getenforce() failed", __func__); case 0: error("%s: Failed to get default SELinux security " "context for %s", __func__, pwname); sc = NULL; break; default: fatal("%s: Failed to get default SELinux security " "context for %s (in enforcing mode)", __func__, pwname); } } #ifdef HAVE_GETSEUSERBYNAME if (sename != NULL) xfree(sename); if (lvl != NULL) xfree(lvl); #endif return sc; }
int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { #ifdef HAVE_SELINUX struct stat st; int r; assert(path); /* if mac_selinux_init() wasn't called before we are a NOOP */ if (!label_hnd) return 0; r = lstat(path, &st); if (r >= 0) { _cleanup_freecon_ char* fcon = NULL; r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); /* If there's no label to set, then exit without warning */ if (r < 0 && errno == ENOENT) return 0; if (r >= 0) { r = lsetfilecon_raw(path, fcon); /* If the FS doesn't support labels, then exit without warning */ if (r < 0 && errno == EOPNOTSUPP) return 0; } } if (r < 0) { /* Ignore ENOENT in some cases */ if (ignore_enoent && errno == ENOENT) return 0; if (ignore_erofs && errno == EROFS) return 0; log_enforcing("Unable to fix SELinux security context of %s: %m", path); if (security_getenforce() == 1) return -errno; } #endif return 0; }
/* * Set the exec and tty contexts in preparation for fork/exec. * Must run as root, before the uid change. * If ptyfd is not -1, it indicates we are running * in a pty and do not need to reset std{in,out,err}. * Returns 0 on success and -1 on failure. */ int selinux_setup(const char *role, const char *type, const char *ttyn, int ptyfd) { int rval = -1; /* Store the caller's SID in old_context. */ if (getprevcon(&se_state.old_context)) { warning("failed to get old_context"); goto done; } se_state.enforcing = security_getenforce(); if (se_state.enforcing < 0) { warning("unable to determine enforcing mode."); goto done; } #ifdef DEBUG warningx("your old context was %s", se_state.old_context); #endif se_state.new_context = get_exec_context(se_state.old_context, role, type); if (!se_state.new_context) goto done; if (relabel_tty(ttyn, ptyfd) < 0) { warning("unable to setup tty context for %s", se_state.new_context); goto done; } #ifdef DEBUG if (se_state.ttyfd != -1) { warningx("your old tty context is %s", se_state.tty_context); warningx("your new tty context is %s", se_state.new_tty_context); } #endif #ifdef HAVE_LINUX_AUDIT linux_audit_role_change(se_state.old_context, se_state.new_context, se_state.ttyn); #endif rval = 0; done: return rval; }
int mac_selinux_apply(const char *path, const char *label) { #ifdef HAVE_SELINUX if (!mac_selinux_use()) return 0; assert(path); assert(label); if (setfilecon(path, label) < 0) { log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path); if (security_getenforce() > 0) return -errno; } #endif return 0; }
static int check_selinux_access (const char *changed_user, uid_t changed_uid, access_vector_t requested_access) { int status = -1; security_context_t user_context; context_t c; const char *user; /* if in permissive mode then allow the operation */ if (security_getenforce() == 0) { return 0; } /* get the context of the process which executed passwd */ if (getprevcon(&user_context) != 0) { return -1; } /* get the "user" portion of the context (the part before the first colon) */ c = context_new(user_context); user = context_user_get(c); /* if changing a password for an account with UID==0 or for an account where the identity matches then return success */ if (changed_uid != 0 && strcmp(changed_user, user) == 0) { status = 0; } else { struct av_decision avd; int retval; retval = security_compute_av(user_context, user_context, SECCLASS_PASSWD, requested_access, &avd); if ((retval == 0) && ((requested_access & avd.allowed) == requested_access)) { status = 0; } } context_free(c); freecon(user_context); return status; }
int mac_selinux_create_socket_prepare(const char *label) { #ifdef HAVE_SELINUX if (!mac_selinux_use()) return 0; assert(label); if (setsockcreatecon(label) < 0) { log_enforcing("Failed to set SELinux security context %s for sockets: %m", label); if (security_getenforce() == 1) return -errno; } #endif return 0; }
/* Function must be called once to initialize the SELinux AVC environment. Sets up callbacks. If you want to cleanup memory you should need to call selinux_access_finish. */ static int access_init(void) { int r; if (avc_open(NULL, 0)) { log_error("avc_open() failed: %m"); return -errno; } selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); if (security_getenforce() >= 0) return 0; r = -errno; avc_destroy(); return r; }
int selinux_util_label(const char *path) { int retval = 0; int enforce; struct stat st; security_context_t con; enforce = security_getenforce(); if (retval < 0) return retval; if (!hnd) return (enforce) ? -1 : 0; retval = lstat(path, &st); if (retval < 0) { if (errno == ENOENT) return 0; return (enforce) ? -1 : 0; } /* lookup the context */ retval = selabel_lookup_raw(hnd, &con, path, st.st_mode); if (retval < 0) { if (errno == ENOENT) return 0; return (enforce) ? -1 : 0; } /* apply the context */ retval = lsetfilecon(path, con); freecon(con); if (retval < 0) { if (errno == ENOENT) return 0; if (errno == ENOTSUP) return 0; return (enforce) ? -1 : 0; } return 0; }
int mac_selinux_create_file_prepare(const char *path, mode_t mode) { #ifdef HAVE_SELINUX _cleanup_freecon_ char *filecon = NULL; int r; assert(path); if (!label_hnd) return 0; if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &filecon, path, mode); else { _cleanup_free_ char *newpath = NULL; r = path_make_absolute_cwd(path, &newpath); if (r < 0) return r; r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode); } if (r < 0) { /* No context specified by the policy? Proceed without setting it. */ if (errno == ENOENT) return 0; log_enforcing("Failed to determine SELinux security context for %s: %m", path); } else { if (setfscreatecon_raw(filecon) >= 0) return 0; /* Success! */ log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); } if (security_getenforce() > 0) return -errno; #endif return 0; }
void setup_selinux_exec_context(char *name) { if (is_selinux_enabled() > 0) { security_context_t user_context=selinux_get_user_context(name); if (setexeccon(user_context)) { if (security_getenforce() > 0) fatal("Failed to set exec security context %s for %s.", user_context, name); else error("Failed to set exec security context %s for %s. " "Continuing in permissive mode", user_context, name); } if (user_context) { freecon(user_context); } } }