int copy_security_context(const char *from_file, const char *to_file) { int status = 0; #ifdef WITH_SELINUX security_context_t from_context; security_context_t to_context; if (selinux_enabled == -1) selinux_enabled = (is_selinux_enabled() > 0); if (!selinux_enabled) return 0; if (getfilecon(from_file, &from_context) < 0) { /* * If the filesystem doesn't support extended * attributes, the original had no special security * context and the target cannot have one either. */ if (errno == EOPNOTSUPP) return 0; error(0, errno, joe_gettext(_("Could not get security context for %s")), from_file); return 1; } if (getfilecon(to_file, &to_context) < 0) { MSG_PUTS(_(joe_gettext(_("\nCould not get security context for ")))); msg_outtrans(to_file); msg_putchar('\n'); freecon(from_context); return 1; } if (zcmp(from_context, to_context) != 0) { if (setfilecon(to_file, from_context) < 0) { error(0, errno, joe_gettext(_("Could not set security context for %s")), to_file); status = 1; } } freecon(to_context); freecon(from_context); #endif return status; }
/* * Function: getFileCon * Purpose: retrieves the context associated with the given path in the file system * Parameters: * path: given path in the file system * Returns: * string representing the security context string of the file object * the string may be NULL if an error occured * Exceptions: NullPointerException if the path object is null */ static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) { #ifdef HAVE_SELINUX if (isSELinuxDisabled) return NULL; if (path == NULL) { throw_NullPointerException(env, "Trying to check security context of a null path."); return NULL; } const char *objectPath = env->GetStringUTFChars(path, NULL); security_context_t context = NULL; jstring securityString = NULL; if (getfilecon(objectPath, &context) == -1) goto bail; ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath); securityString = env->NewStringUTF(context); bail: if (context != NULL) freecon(context); env->ReleaseStringUTFChars(path, objectPath); return securityString; #else return NULL; #endif }
static int testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles) { size_t i; security_context_t ctx; for (i = 0; i < nfiles; i++) { ctx = NULL; if (getfilecon(files[i].file, &ctx) < 0) { if (errno == ENODATA) { /* nothing to do */ } else if (errno == EOPNOTSUPP) { if (VIR_STRDUP(ctx, "EOPNOTSUPP") < 0) return -1; } else { virReportSystemError(errno, "Cannot read label on %s", files[i].file); return -1; } } if (STRNEQ_NULLABLE(files[i].context, ctx)) { virReportError(VIR_ERR_INTERNAL_ERROR, "File %s context '%s' did not match epected '%s'", files[i].file, ctx, files[i].context); VIR_FREE(ctx); return -1; } VIR_FREE(ctx); } return 0; }
static context_t runcon_compute_new_context(char *user, char *role, char *type, char *range, char *command, int compute_trans) { context_t con; security_context_t cur_context; if (getcon(&cur_context)) bb_error_msg_and_die("can't get current context"); if (compute_trans) { security_context_t file_context, new_context; if (getfilecon(command, &file_context) < 0) bb_error_msg_and_die("can't retrieve attributes of '%s'", command); if (security_compute_create(cur_context, file_context, SECCLASS_PROCESS, &new_context)) bb_error_msg_and_die("unable to compute a new context"); cur_context = new_context; } con = context_new(cur_context); if (!con) bb_error_msg_and_die("'%s' is not a valid context", cur_context); if (user && context_user_set(con, user)) bb_error_msg_and_die("can't set new user '%s'", user); if (type && context_type_set(con, type)) bb_error_msg_and_die("can't set new type '%s'", type); if (range && context_range_set(con, range)) bb_error_msg_and_die("can't set new range '%s'", range); if (role && context_role_set(con, role)) bb_error_msg_and_die("can't set new role '%s'", role); return con; }
void setup_selinux_pty(const char *name, const char *tty) { if (is_selinux_enabled() > 0) { security_context_t new_tty_context=NULL, user_context=NULL, old_tty_context=NULL; user_context=selinux_get_user_context(name); if (getfilecon(tty, &old_tty_context) < 0) { error("getfilecon(%.100s) failed: %.100s", tty, strerror(errno)); } else { if (security_compute_relabel(user_context,old_tty_context, SECCLASS_CHR_FILE, &new_tty_context) != 0) { error("security_compute_relabel(%.100s) failed: " "%.100s", tty, strerror(errno)); } else { if (setfilecon (tty, new_tty_context) != 0) error("setfilecon(%.100s, %s) failed: %.100s", tty, new_tty_context, strerror(errno)); freecon(new_tty_context); } freecon(old_tty_context); } if (user_context) { freecon(user_context); } } }
static void pw_unlock(void) { char tmp[FILENAMELEN+4]; sprintf(tmp, "%s%s", orig_file, ".OLD"); unlink(tmp); link(orig_file, tmp); #ifdef HAVE_LIBSELINUX if (is_selinux_enabled()) { security_context_t passwd_context=NULL; int ret=0; if (getfilecon(orig_file,&passwd_context) < 0) { (void) fprintf(stderr,_("%s: Can't get context for %s"),progname,orig_file); pw_error(orig_file, 1, 1); } ret=setfilecon(tmp_file,passwd_context); freecon(passwd_context); if (ret!=0) { (void) fprintf(stderr,_("%s: Can't set context for %s"),progname,tmp_file); pw_error(tmp_file, 1, 1); } } #endif if (rename(tmp_file, orig_file) == -1) { int errsv = errno; fprintf(stderr, _("%s: can't unlock %s: %s (your changes are still in %s)\n"), progname, orig_file, strerror(errsv), tmp_file); exit(1); } unlink(tmp_file); }
static int unmount_rename(const char *mtab, const char *mtab_new) { int res; struct stat sbuf; if (stat(mtab, &sbuf) == 0) chown(mtab_new, sbuf.st_uid, sbuf.st_gid); #ifdef HAVE_LIBSELINUX { security_context_t filecon; if (getfilecon(mtab, &filecon) > 0) { setfilecon(mtab_new, filecon); if (filecon != NULL) freecon(filecon); } } #endif res = rename(mtab_new, mtab); if (res == -1) { fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname, mtab_new, mtab, strerror(errno)); return -1; } return 0; }
static int computecon (char const *path, mode_t mode, char **con) { char *scon = NULL; char *tcon = NULL; security_class_t tclass; int rc = -1; char *dir = dir_name (path); if (!dir) goto quit; if (getcon (&scon) < 0) goto quit; if (getfilecon (dir, &tcon) < 0) goto quit; tclass = mode_to_security_class (mode); if (!tclass) goto quit; rc = security_compute_create (scon, tcon, tclass, con); quit: free (dir); freecon (scon); freecon (tcon); return rc; }
int output_security_context(const char *from_file) { #ifdef WITH_SELINUX security_context_t scontext; if (selinux_enabled == -1) selinux_enabled = (is_selinux_enabled() > 0); if (!selinux_enabled) return 0; if (getfilecon(from_file, &scontext) < 0) { /* * If the filesystem doesn't support extended * attributes, the original had no special security * context and the target cannot have one either. */ if (errno == EOPNOTSUPP) return 0; error(0, errno,joe_gettext(_("Could not get security context for %s")), from_file); return 1; } error(0, 0, joe_gettext(_("%s Security Context %s")), from_file, scontext); freecon(scontext); #endif return 0; }
// Copy security info from "from_file" to "to_file". void mch_copy_sec(char_u *from_file, char_u *to_file) { if (from_file == NULL) return; if (selinux_enabled == -1) selinux_enabled = is_selinux_enabled(); if (selinux_enabled > 0) { security_context_t from_context = NULL; security_context_t to_context = NULL; if (getfilecon((char *)from_file, &from_context) < 0) { // If the filesystem doesn't support extended attributes, // the original had no special security context and the // target cannot have one either. if (errno == EOPNOTSUPP) { return; } MSG_PUTS(_("\nCould not get security context for ")); msg_outtrans(from_file); msg_putchar('\n'); return; } if (getfilecon((char *)to_file, &to_context) < 0) { MSG_PUTS(_("\nCould not get security context for ")); msg_outtrans(to_file); msg_putchar('\n'); freecon (from_context); return; } if (strcmp(from_context, to_context) != 0) { if (setfilecon((char *)to_file, from_context) < 0) { MSG_PUTS(_("\nCould not set security context for ")); msg_outtrans(to_file); msg_putchar('\n'); } } freecon(to_context); freecon(from_context); } }
static int set_context_from_socket( const struct service_config *scp, int fd ) { security_context_t curr_context = NULL; security_context_t peer_context = NULL; security_context_t exec_context = NULL; context_t bcon = NULL; context_t pcon = NULL; security_context_t new_context = NULL; security_context_t new_exec_context = NULL; int retval = -1; const char *exepath = NULL; if (getcon(&curr_context) < 0) goto fail; if (getpeercon(fd, &peer_context) < 0) goto fail; exepath = SC_SERVER_ARGV( scp )[0]; if (getfilecon(exepath, &exec_context) < 0) goto fail; if (!(bcon = context_new(curr_context))) goto fail; if (!(pcon = context_new(peer_context))) goto fail; if (!context_range_get(pcon)) goto fail; if (context_range_set(bcon, context_range_get(pcon))) goto fail; if (!(new_context = context_str(bcon))) goto fail; if (security_compute_create(new_context, exec_context, SECCLASS_PROCESS, &new_exec_context) < 0) goto fail; retval = set_context(new_exec_context); freecon(new_exec_context); fail: context_free(pcon); context_free(bcon); freecon(exec_context); freecon(peer_context); freecon(curr_context); return retval; }
static unsigned long chcon_parse_options(int argc, char *argv[]) { unsigned long opts; char *reference_file = NULL; #ifdef CONFIG_FEATURE_CHCON_LONG_OPTIONS bb_applet_long_options = chcon_options; #endif opts = bb_getopt_ulflags(argc, argv, "Rchf\n:u:r:t:l:v?\b", &reference_file, &user, &role, &type, &range); if (opts & OPT_CHCON_VERSION) { printf("%s - busybox %s (build: %s)\n", argv[0], BB_VER, BB_BT); exit(0); } if (opts & (OPT_CHCON_HELP | BB_GETOPT_ERROR)) bb_show_usage(); if ((opts & OPT_CHCON_QUIET) && (opts & OPT_CHCON_VERBOSE)) { fprintf(stderr, "could not specify quiet and verbose option same time\n"); bb_show_usage(); } if ((opts & OPT_CHCON_REFERENCE) && (opts & OPT_CHCON_COMPONENT_SPECIFIED)) { fprintf(stderr, "conflicting security context specifiers given\n"); bb_show_usage(); } else if (opts & OPT_CHCON_REFERENCE) { /* FIXME: lgetfilecon() should be used when '-h' is specified. */ if (getfilecon(reference_file, &specified_context) < 0) { fprintf(stderr, "getfilecon('%s'), errno=%d (%s)\n", reference_file, errno, strerror(errno)); exit(1); } } else if ((opts & OPT_CHCON_COMPONENT_SPECIFIED) == 0) { specified_context = argv[optind++]; if (!specified_context) { fprintf(stderr, "too few arguments\n"); bb_show_usage(); } } target_files = argv + optind; if (!*target_files) { fprintf(stderr, "too few arguments\n"); bb_show_usage(); } return opts; }
/* Set the context of all files associated with this VM to the new context * complete with the unique generated category. */ static int file_con_fixup (data_t *data) { security_context_t sec_con = { 0, }; context_t con = { 0, }; char mcs_str[9] = { 0, }; int ret = 0, p_ret = 0, i = 0;; p_ret = snprintf (mcs_str, sizeof (mcs_str), "s0:c%d", data->category); if (p_ret < 0 || p_ret > 9) { syslog (LOG_CRIT, "insufficient buffer size"); return -1; } for (i = 0; data->files [i] != NULL; ++i) { if (getfilecon (data->files [i], &sec_con) == -1) { syslog (LOG_CRIT, "error getting context from file: %s, error %s", data->files [i], strerror (errno)); continue; } con = context_new (sec_con); if (con == NULL) { syslog (LOG_CRIT, "Error creating new context from string: %s", sec_con); ret = -1; goto err_freecon; } if (context_range_set (con, mcs_str) == -1) { syslog (LOG_CRIT, "Error setting context range to %s, " "error: %s", mcs_str, strerror (errno)); ret = -1; goto err_confree; } syslog (LOG_INFO, "Setting context for file %s to %s", data->files [i], context_str (con)); ret = setfilecon (data->files [i], context_str (con)); if (ret != 0) syslog (LOG_CRIT, "setfilecon error:%s", strerror (errno)); context_free (con); freecon (sec_con); } return ret; err_confree: context_free (con); err_freecon: freecon (sec_con); return ret; }
/* 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; }
int chcon_main(int argc, char **argv) { char *reference_file; char *fname; int i, errors = 0; #if ENABLE_FEATURE_CHCON_LONG_OPTIONS applet_long_options = chcon_longopts; #endif opt_complementary = "-1" /* at least 1 param */ ":?" /* error if exclusivity constraints are violated */ #if ENABLE_FEATURE_CHCON_LONG_OPTIONS ":\xff--urtl:u--\xff:r--\xff:t--\xff:l--\xff" #endif ":f--v:v--f"; /* 'verbose' and 'quiet' are exclusive */ getopt32(argv, "Rchfu:r:t:l:v", &user, &role, &type, &range, &reference_file); argv += optind; #if ENABLE_FEATURE_CHCON_LONG_OPTIONS if (option_mask32 & OPT_REFERENCE) { /* FIXME: lgetfilecon() should be used when '-h' is specified. But current implementation follows the original one. */ if (getfilecon(reference_file, &specified_context) < 0) bb_perror_msg_and_die("getfilecon('%s') failed", reference_file); } else #endif if ((option_mask32 & OPT_COMPONENT_SPECIFIED) == 0) { specified_context = *argv++; /* specified_context is never NULL - * "-1" in opt_complementary prevents this. */ if (!argv[0]) bb_error_msg_and_die("too few arguments"); } for (i = 0; (fname = argv[i]) != NULL; i++) { int fname_len = strlen(fname); while (fname_len > 1 && fname[fname_len - 1] == '/') fname_len--; fname[fname_len] = '\0'; if (recursive_action(fname, 1<<option_mask32 & OPT_RECURSIVE, change_filedir_context, change_filedir_context, NULL, 0) != TRUE) errors = 1; } return errors; }
static security_context_t security_label_tty(pam_handle_t *pamh, char *tty, security_context_t usercon) { char ttybuf[PATH_MAX]; int status=0; security_context_t newdev_context=NULL; /* The new context of a device */ security_context_t prev_context=NULL; /* The new context of a device */ const char *ptr; if(strncmp("/dev/", tty, 5)) { snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty); ptr = ttybuf; } else ptr = tty; if (getfilecon(ptr, &prev_context) < 0) { if(errno != ENOENT) pam_syslog(pamh, LOG_NOTICE, "Warning! Could not get current context for %s, not relabeling: %m", ptr); return NULL; } if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE, &newdev_context)!=0) { pam_syslog(pamh, LOG_NOTICE, "Warning! Could not get new context for %s, not relabeling: %m", ptr); pam_syslog(pamh, LOG_NOTICE, "usercon=%s, prev_context=%s", usercon, prev_context); freecon(prev_context); return NULL; } status=setfilecon(ptr,newdev_context); if (status) { pam_syslog(pamh, LOG_NOTICE, "Warning! Could not relabel %s with %s, not relabeling: %m", ptr,newdev_context); freecon(prev_context); prev_context=NULL; } freecon(newdev_context); return prev_context; }
static void append_context_for_mount(char *mntpt, struct mkfs_opts *mop) { security_context_t fcontext; if (getfilecon(mntpt, &fcontext) < 0) { /* Continuing with default behaviour */ fprintf(stderr, "%s: Get file context failed : %s\n", progname, strerror(errno)); return; } if (fcontext != NULL) { append_unique(mop->mo_ldd.ldd_mount_opts, ",", "context", fcontext, sizeof(mop->mo_ldd.ldd_mount_opts)); freecon(fcontext); } }
/* Set the TTY context for the specified user */ void ssh_selinux_setup_pty(char *pwname, const char *tty) { security_context_t new_tty_ctx = NULL; security_context_t user_ctx = NULL; security_context_t old_tty_ctx = NULL; if (!ssh_selinux_enabled()) return; debug3("%s: setting TTY context on %s", __func__, tty); user_ctx = ssh_selinux_getctxbyname(pwname); /* XXX: should these calls fatal() upon failure in enforcing mode? */ if (getfilecon(tty, &old_tty_ctx) == -1) { error("%s: getfilecon: %s", __func__, strerror(errno)); goto out; } if (security_compute_relabel(user_ctx, old_tty_ctx, SECCLASS_CHR_FILE, &new_tty_ctx) != 0) { error("%s: security_compute_relabel: %s", __func__, strerror(errno)); goto out; } if (setfilecon(tty, new_tty_ctx) != 0) error("%s: setfilecon: %s", __func__, strerror(errno)); out: if (new_tty_ctx != NULL) freecon(new_tty_ctx); if (old_tty_ctx != NULL) freecon(old_tty_ctx); if (user_ctx != NULL) freecon(user_ctx); debug3("%s: done", __func__); }
} UINT32 aerofgt_state::aerofgt_ol2_tile_callback( UINT32 code ) { return m_spriteram2[code % (m_spriteram2.bytes()/2)]; } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE16_MEMBER(aerofgt_state::aerofgt_bg1videoram_w) { COMBINE_DATA(&m_bg1videoram[offset]); m_bg1_tilemap->mark_tile_dirty(offset); } WRITE16_MEMBER(aerofgt_state::aerofgt_bg2videoram_w) { COMBINE_DATA(&m_bg2videoram[offset]); m_bg2_tilemap->mark_tile_dirty(offset); } void aerofgt_state::setbank( tilemap_t *tmap, int num, int bank ) { if (m_gfxbank[num] != bank) {
/* * Function: getFileCon * Purpose: retrieves the context associated with the given path in the file system * Parameters: * path: given path in the file system * Returns: * string representing the security context string of the file object * the string may be NULL if an error occured * Exceptions: NullPointerException if the path object is null */ static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { if (isSELinuxDisabled) { return NULL; } ScopedUtfChars path(env, pathStr); if (path.c_str() == NULL) { return NULL; } security_context_t tmp = NULL; int ret = getfilecon(path.c_str(), &tmp); Unique_SecurityContext context(tmp); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } ALOGV("getFileCon(%s) => %s", path.c_str(), context.get()); return securityString.release(); }
static void initselinux(char *username, char *full_tty, security_context_t *user_sid) { security_context_t old_tty_sid, new_tty_sid; if (!is_selinux_enabled()) return; if (get_default_context(username, NULL, user_sid)) { bb_error_msg_and_die("can't get SID for %s", username); } if (getfilecon(full_tty, &old_tty_sid) < 0) { bb_perror_msg_and_die("getfilecon(%s) failed", full_tty); } if (security_compute_relabel(*user_sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0) { bb_perror_msg_and_die("security_change_sid(%s) failed", full_tty); } if (setfilecon(full_tty, new_tty_sid) != 0) { bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid); } }
int label_get_socket_label_from_exe(const char *exe, char **label) { int r = 0; #ifdef HAVE_SELINUX security_context_t mycon = NULL, fcon = NULL; security_class_t sclass; if (!use_selinux()) { *label = NULL; return 0; } r = getcon(&mycon); if (r < 0) goto fail; r = getfilecon(exe, &fcon); if (r < 0) goto fail; sclass = string_to_security_class("process"); r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); if (r == 0) log_debug("SELinux Socket context for %s will be set to %s", exe, *label); fail: if (r < 0 && security_getenforce() == 1) r = -errno; freecon(mycon); freecon(fcon); #endif return r; }
const char * rpmsxGetfilecon(rpmsx sx, const char *fn) { const char * scon = NULL; if (sx == NULL) sx = rpmsxI(); if (_rpmsx_debug) fprintf(stderr, "--> %s(%p,%s) sxfn %s\n", __FUNCTION__, sx, fn, sx->fn); #if defined(WITH_SELINUX) if (sx->fn && fn) { security_context_t _con = NULL; int rc = getfilecon(fn, &_con); if (rc > 0 && _con != NULL) scon = (const char *) _con; else freecon(_con); } #endif if (_rpmsx_debug) fprintf(stderr, "<-- %s(%p,%s) scon %s\n", __FUNCTION__, sx, fn, scon); return scon; }
static void pw_write(void) { char tmp[FILENAMELEN + 4]; sprintf(tmp, "%s%s", orig_file, ".OLD"); unlink(tmp); if (link(orig_file, tmp)) warn(_("%s: create a link to %s failed"), orig_file, tmp); #ifdef HAVE_LIBSELINUX if (is_selinux_enabled() > 0) { security_context_t passwd_context = NULL; int ret = 0; if (getfilecon(orig_file, &passwd_context) < 0) { warnx(_("Can't get context for %s"), orig_file); pw_error(orig_file, 1, 1); } ret = setfilecon(tmp_file, passwd_context); freecon(passwd_context); if (ret != 0) { warnx(_("Can't set context for %s"), tmp_file); pw_error(tmp_file, 1, 1); } } #endif if (rename(tmp_file, orig_file) == -1) { int errsv = errno; errx(EXIT_FAILURE, ("cannot write %s: %s (your changes are still in %s)"), orig_file, strerror(errsv), tmp_file); } unlink(tmp_file); free(tmp_file); }
static int change_file_context(const char *file, unsigned long opts) { security_context_t file_context = NULL; security_context_t context_string; context_t context; int errors = 0; int status = 0; if (opts & OPT_CHCON_NODEREFERENCE) { status = lgetfilecon(file, &file_context); } else { status = getfilecon(file, &file_context); } if (status < 0 && errno != ENODATA) { if ((opts & OPT_CHCON_QUIET) == 0) fprintf(stderr, "could not obtain security context: %s\n", file); return 1; } if (file_context == NULL && specified_context == NULL) { fprintf(stderr, "can't apply partial context to unlabeled file %s", file); return 1; } if (specified_context == NULL) { context = compute_context_from_mask(file_context, opts); if (!context) { fprintf(stderr, "couldn't compute security context from %s", file_context); return 1; } } else { context = context_new(specified_context); if (!context) { fprintf(stderr, "invalid context: %s", specified_context); return 1; } } context_string = context_str(context); if (file_context == NULL || strcmp(context_string, file_context)!=0) { int fail = 0; if (opts & OPT_CHCON_NODEREFERENCE) { fail = lsetfilecon (file, context_string); } else { fail = setfilecon (file, context_string); } if ((opts & OPT_CHCON_VERBOSE) || ((opts & OPT_CHCON_CHANHES) && !fail)) { printf(!fail ? "context of %s changed to %s\n" : "failed to change context of %s to %s\n", file, context_string); } if (fail) { errors = 1; if ((opts & OPT_CHCON_QUIET) == 0) fprintf(stderr, "failed to change context of %s to %s\n", file, context_string); } } else if (opts & OPT_CHCON_VERBOSE) { printf("context of %s retained as %s\n", file, context_string); } context_free(context); freecon(file_context); if (opts & OPT_CHCON_RECURSIVE) { struct stat file_stats; if (lstat(file, &file_stats) == 0 && S_ISDIR(file_stats.st_mode)) errors |= change_dir_context(file, opts); } return errors; }
/* This function communicates with the kernel to check whether or not it should allow the access. If the machine is in permissive mode it will return ok. Audit messages will still be generated if the access would be denied in enforcing mode. */ int selinux_access_check( DBusConnection *connection, DBusMessage *message, const char *path, const char *permission, DBusError *error) { security_context_t scon = NULL, fcon = NULL; int r = 0; const char *tclass = NULL; struct auditstruct audit; assert(connection); assert(message); assert(permission); assert(error); if (!use_selinux()) return 0; r = selinux_access_init(error); if (r < 0) return r; log_debug("SELinux access check for path=%s permission=%s", strna(path), permission); audit.uid = audit.loginuid = (uid_t) -1; audit.gid = (gid_t) -1; audit.cmdline = NULL; audit.path = path; r = get_calling_context(connection, message, &scon, error); if (r < 0) { log_error("Failed to get caller's security context on: %m"); goto finish; } if (path) { tclass = "service"; /* get the file context of the unit file */ r = getfilecon(path, &fcon); if (r < 0) { dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path); r = -errno; log_error("Failed to get security context on %s: %m",path); goto finish; } } else { tclass = "system"; r = getcon(&fcon); if (r < 0) { dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context."); r = -errno; log_error("Failed to get current process context on: %m"); goto finish; } } (void) get_audit_data(connection, message, &audit, error); errno = 0; r = selinux_check_access(scon, fcon, tclass, permission, &audit); if (r < 0) { dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); r = -errno; log_error("SELinux policy denies access."); } log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r); finish: free(audit.cmdline); freecon(scon); freecon(fcon); if (r && security_getenforce() != 1) { dbus_error_init(error); r = 0; } return r; }
void service_start(struct service *svc, const char *dynamic_args) { struct stat s; pid_t pid; int needs_console; int n; #ifdef HAVE_SELINUX char *scon = NULL; int rc; #endif /* starting a service removes it from the disabled or reset * state and immediately takes it out of the restarting * state if it was in there */ svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET)); svc->time_started = 0; /* running processes require no additional work -- if * they're in the process of exiting, we've ensured * that they will immediately restart on exit, unless * they are ONESHOT */ if (svc->flags & SVC_RUNNING) { return; } needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; if (needs_console && (!have_console)) { ERROR("service '%s' requires console\n", svc->name); svc->flags |= SVC_DISABLED; return; } if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } #ifdef HAVE_SELINUX if (is_selinux_enabled() > 0) { char *mycon = NULL, *fcon = NULL; INFO("computing context for service '%s'\n", svc->args[0]); rc = getcon(&mycon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } rc = getfilecon(svc->args[0], &fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); freecon(mycon); return; } rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon); freecon(mycon); freecon(fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } } #endif NOTICE("starting '%s'\n", svc->name); pid = fork(); if (pid == 0) { struct socketinfo *si; struct svcenvinfo *ei; char tmp[32]; int fd, sz; umask(077); #ifdef __arm__ /* * b/7188322 - Temporarily revert to the compat memory layout * to avoid breaking third party apps. * * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE. * * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466 * changes the kernel mapping from bottom up to top-down. * This breaks some programs which improperly embed * an out of date copy of Android's linker. */ int current = personality(0xffffFFFF); personality(current | ADDR_COMPAT_LAYOUT); #endif if (properties_inited()) { get_property_workspace(&fd, &sz); sprintf(tmp, "%d,%d", dup(fd), sz); add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); } for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); #ifdef HAVE_SELINUX setsockcreatecon(scon); #endif for (si = svc->sockets; si; si = si->next) { int socket_type = ( !strcmp(si->type, "stream") ? SOCK_STREAM : (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET)); int s = create_socket(si->name, socket_type, si->perm, si->uid, si->gid); if (s >= 0) { publish_socket(si->name, s); } } #ifdef HAVE_SELINUX freecon(scon); scon = NULL; setsockcreatecon(NULL); #endif if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); } } if (needs_console) { setsid(); open_console(); } else { zap_stdio(); } #if 0 for (n = 0; svc->args[n]; n++) { INFO("args[%d] = '%s'\n", n, svc->args[n]); } for (n = 0; ENV[n]; n++) { INFO("env[%d] = '%s'\n", n, ENV[n]); } #endif setpgid(0, getpid()); /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { if (setgid(svc->gid) != 0) { ERROR("setgid failed: %s\n", strerror(errno)); _exit(127); } } if (svc->nr_supp_gids) { if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) { ERROR("setgroups failed: %s\n", strerror(errno)); _exit(127); } } if (svc->uid) { if (setuid(svc->uid) != 0) { ERROR("setuid failed: %s\n", strerror(errno)); _exit(127); } } #ifdef HAVE_SELINUX if (svc->seclabel) { if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) { ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno)); _exit(127); } } #endif if (!dynamic_args) { if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); } } else { char *arg_ptrs[INIT_PARSER_MAXARGS+1]; int arg_idx = svc->nargs; char *tmp = strdup(dynamic_args); char *next = tmp; char *bword; /* Copy the static arguments */ memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *))); while((bword = strsep(&next, " "))) { arg_ptrs[arg_idx++] = bword; if (arg_idx == INIT_PARSER_MAXARGS) break; } arg_ptrs[arg_idx] = '\0'; execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); } _exit(127); } #ifdef HAVE_SELINUX freecon(scon); #endif if (pid < 0) { ERROR("failed to start '%s'\n", svc->name); svc->pid = 0; return; } svc->time_started = gettime(); svc->pid = pid; svc->flags |= SVC_RUNNING; if (properties_inited()) notify_service_state(svc->name, "running"); }
int rpl_getfilecon (char const *file, security_context_t *con) { int ret = getfilecon (file, con); return map_to_failure (ret, con); }
/* This function communicates with the kernel to check whether or not it should allow the access. If the machine is in permissive mode it will return ok. Audit messages will still be generated if the access would be denied in enforcing mode. */ int mac_selinux_generic_access_check( sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error) { #ifdef HAVE_SELINUX _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; const char *tclass = NULL, *scon = NULL; struct audit_info audit_info = {}; _cleanup_free_ char *cl = NULL; security_context_t fcon = NULL; char **cmdline = NULL; int r = 0; assert(message); assert(permission); assert(error); if (!mac_selinux_use()) return 0; r = mac_selinux_access_init(error); if (r < 0) return r; r = sd_bus_query_sender_creds( message, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID| SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID| SD_BUS_CREDS_SELINUX_CONTEXT| SD_BUS_CREDS_AUGMENT /* get more bits from /proc */, &creds); if (r < 0) goto finish; /* The SELinux context is something we really should have * gotten directly from the message or sender, and not be an * augmented field. If it was augmented we cannot use it for * authorization, since this is racy and vulnerable. Let's add * an extra check, just in case, even though this really * shouldn't be possible. */ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_SELINUX_CONTEXT) == 0, -EPERM); r = sd_bus_creds_get_selinux_context(creds, &scon); if (r < 0) goto finish; if (path) { /* Get the file context of the unit file */ r = getfilecon(path, &fcon); if (r < 0) { r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path); goto finish; } tclass = "service"; } else { r = getcon(&fcon); if (r < 0) { r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context."); goto finish; } tclass = "system"; } sd_bus_creds_get_cmdline(creds, &cmdline); cl = strv_join(cmdline, " "); audit_info.creds = creds; audit_info.path = path; audit_info.cmdline = cl; r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); if (r < 0) r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r); finish: freecon(fcon); if (r < 0 && security_getenforce() != 1) { sd_bus_error_free(error); r = 0; } return r; #else return 0; #endif }
int main(int argc, char **argv) { /* these vars are reused several times */ int rc, opt, i, c; char *context, *root_path; /* files that need context checks */ char *fc[MAX_CHECK]; char *cterm = ttyname(0); int nfc = 0; struct stat m; /* processes that need context checks */ char *pc[MAX_CHECK]; int npc = 0; /* booleans */ char **bools; int nbool; int verbose = 0; int show_bools = 0; /* policy */ const char *pol_name, *root_dir; char *pol_path; while (1) { opt = getopt(argc, argv, "vb"); if (opt == -1) break; switch (opt) { case 'v': verbose = 1; break; case 'b': show_bools = 1; break; default: /* invalid option */ printf("\nUsage: %s [OPTION]\n\n", basename(argv[0])); printf(" -v Verbose check of process and file contexts.\n"); printf(" -b Display current state of booleans.\n"); printf("\nWithout options, show SELinux status.\n"); return -1; } } printf_tab("SELinux status:"); rc = is_selinux_enabled(); switch (rc) { case 1: printf("enabled\n"); break; case 0: printf("disabled\n"); return 0; break; default: printf("unknown (%s)\n", strerror(errno)); return 0; break; } printf_tab("SELinuxfs mount:"); if (selinux_mnt != NULL) { printf("%s\n", selinux_mnt); } else { printf("not mounted\n\n"); printf("Please mount selinuxfs for proper results.\n"); return -1; } printf_tab("SELinux root directory:"); root_dir = selinux_path(); if (root_dir == NULL) { printf("error (%s)\n", strerror(errno)); return -1; } /* The path has a trailing '/' so duplicate to edit */ root_path = strdup(root_dir); if (!root_path) { printf("malloc error (%s)\n", strerror(errno)); return -1; } /* actually blank the '/' */ root_path[strlen(root_path) - 1] = '\0'; printf("%s\n", root_path); free(root_path); /* Dump all the path information */ printf_tab("Loaded policy name:"); pol_path = strdup(selinux_policy_root()); if (pol_path) { pol_name = basename(pol_path); puts(pol_name); free(pol_path); } else { printf("error (%s)\n", strerror(errno)); } printf_tab("Current mode:"); rc = security_getenforce(); switch (rc) { case 1: printf("enforcing\n"); break; case 0: printf("permissive\n"); break; default: printf("unknown (%s)\n", strerror(errno)); break; } printf_tab("Mode from config file:"); if (selinux_getenforcemode(&rc) == 0) { switch (rc) { case 1: printf("enforcing\n"); break; case 0: printf("permissive\n"); break; case -1: printf("disabled\n"); break; } } else { printf("error (%s)\n", strerror(errno)); } printf_tab("Policy MLS status:"); rc = is_selinux_mls_enabled(); switch (rc) { case 0: printf("disabled\n"); break; case 1: printf("enabled\n"); break; default: printf("error (%s)\n", strerror(errno)); break; } printf_tab("Policy deny_unknown status:"); rc = security_deny_unknown(); switch (rc) { case 0: printf("allowed\n"); break; case 1: printf("denied\n"); break; default: printf("error (%s)\n", strerror(errno)); break; } rc = security_policyvers(); printf_tab("Max kernel policy version:"); if (rc < 0) printf("unknown (%s)\n", strerror(errno)); else printf("%d\n", rc); if (show_bools) { /* show booleans */ if (security_get_boolean_names(&bools, &nbool) >= 0) { printf("\nPolicy booleans:\n"); for (i = 0; i < nbool; i++) { if (strlen(bools[i]) + 1 > COL) COL = strlen(bools[i]) + 1; } for (i = 0; i < nbool; i++) { printf_tab(bools[i]); rc = security_get_boolean_active(bools[i]); switch (rc) { case 1: printf("on"); break; case 0: printf("off"); break; default: printf("unknown (%s)", strerror(errno)); break; } c = security_get_boolean_pending(bools[i]); if (c != rc) switch (c) { case 1: printf(" (activate pending)"); break; case 0: printf(" (inactivate pending)"); break; default: printf(" (pending error: %s)", strerror(errno)); break; } printf("\n"); /* free up the booleans */ free(bools[i]); } free(bools); } } /* only show contexts if -v is given */ if (!verbose) return 0; load_checks(pc, &npc, fc, &nfc); printf("\nProcess contexts:\n"); printf_tab("Current context:"); if (getcon(&context) >= 0) { printf("%s\n", context); freecon(context); } else printf("unknown (%s)\n", strerror(errno)); printf_tab("Init context:"); if (getpidcon(1, &context) >= 0) { printf("%s\n", context); freecon(context); } else printf("unknown (%s)\n", strerror(errno)); for (i = 0; i < npc; i++) { rc = pidof(pc[i]); if (rc > 0) { if (getpidcon(rc, &context) < 0) continue; printf_tab(pc[i]); printf("%s\n", context); freecon(context); } } printf("\nFile contexts:\n"); /* controlling term */ printf_tab("Controlling terminal:"); if (lgetfilecon(cterm, &context) >= 0) { printf("%s\n", context); freecon(context); } else { printf("unknown (%s)\n", strerror(errno)); } for (i = 0; i < nfc; i++) { if (lgetfilecon(fc[i], &context) >= 0) { printf_tab(fc[i]); /* check if this is a symlink */ if (lstat(fc[i], &m)) { printf ("%s (could not check link status (%s)!)\n", context, strerror(errno)); freecon(context); continue; } if (S_ISLNK(m.st_mode)) { /* print link target context */ printf("%s -> ", context); freecon(context); if (getfilecon(fc[i], &context) >= 0) { printf("%s\n", context); freecon(context); } else { printf("unknown (%s)\n", strerror(errno)); } } else { printf("%s\n", context); freecon(context); } } } return 0; }