Esempio n. 1
0
static int
selinux_post_config(apr_pool_t *pconf, apr_pool_t *plog,
                    apr_pool_t *ptemp, server_rec *s)
{
    security_context_t  context;
    char   *domain;
    int     rc;

    if (!server_domain)
        return OK;

    if (getcon_raw(&context) < 0) {
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
                     "SELinux: getcon_raw() failed");
        return DONE;
    }

    domain = apr_pstrdup(ptemp, server_domain);

    rc = do_set_domain(context, domain, s);
    if (rc < 0) {
        freecon(context);
        return DONE;
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "SELinux: %s: %s/%s",
                 (rc == 0 ? "replace server domain"
                          : "no need to change server domain"),
                 context, server_domain);
    freecon(context);

    return OK;
}
Esempio n. 2
0
int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
        int r = -EOPNOTSUPP;

#ifdef HAVE_SELINUX
        _cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
        security_class_t sclass;

        assert(exe);
        assert(label);

        if (!mac_selinux_have())
                return -EOPNOTSUPP;

        r = getcon_raw(&mycon);
        if (r < 0)
                return -errno;

        r = getfilecon_raw(exe, &fcon);
        if (r < 0)
                return -errno;

        sclass = string_to_security_class("process");
        r = security_compute_create_raw(mycon, fcon, sclass, label);
        if (r < 0)
                return -errno;
#endif

        return r;
}
Esempio n. 3
0
int mac_selinux_get_our_label(char **label) {
        int r = -EOPNOTSUPP;

        assert(label);

#ifdef HAVE_SELINUX
        if (!mac_selinux_have())
                return -EOPNOTSUPP;

        r = getcon_raw(label);
        if (r < 0)
                return -errno;
#endif

        return r;
}
Esempio n. 4
0
static security_context_t get_scon(void)
{
	static char dummy_NIL[1] = "";
	security_context_t con = NULL;
	int ret = -1;
	int raw = TRUE;

	switch (opts->from_type) {
	case OPTS_FROM_ARG:
		if (!(con = strdup(opts->f.arg)))
			err(EXIT_FAILURE,
			    " Couldn't allocate security context");
		raw = !opts->disp_raw;	/* always do conversion */
		break;

	case OPTS_FROM_STDIN:
		{
			char buf[4096] = "";
			char *ptr = buf;

			while (!*ptr) {
				if (!(ptr = fgets(buf, sizeof(buf), stdin)))
					err(EXIT_FAILURE,
					    " Couldn't read security context");

				ptr += strspn(ptr, " \n\t");
				ptr[strcspn(ptr, " \n\t")] = 0;
			}

			if (!(con = strdup(ptr)))
				err(EXIT_FAILURE,
				    " Couldn't allocate security context");

			raw = !opts->disp_raw;	/* always do conversion */
			break;
		}

	case OPTS_FROM_CUR:
		ret = getcon_raw(&con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get current security context");
		break;
	case OPTS_FROM_CUREXE:
		ret = getexeccon_raw(&con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get current exec security context");

		if (!con)
			con = strdup(dummy_NIL);
		break;
	case OPTS_FROM_CURFS:
		ret = getfscreatecon_raw(&con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get current fs security context");

		if (!con)
			con = strdup(dummy_NIL);
		break;
	case OPTS_FROM_CURKEY:
		ret = getkeycreatecon_raw(&con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get current key security context");

		if (!con)
			con = strdup(dummy_NIL);
		break;

	case OPTS_FROM_PROC:
		ret = getpidcon_raw(opts->f.pid, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for pid %lu",
			    (unsigned long)opts->f.pid);
		break;
	case OPTS_FROM_PROCEXE:
		ret = my_getpidexeccon_raw(opts->f.pid, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for pid %lu",
			    (unsigned long)opts->f.pid);

		if (!con)
			con = strdup(dummy_NIL);
		break;
	case OPTS_FROM_PROCFS:
		ret = my_getpidfscreatecon_raw(opts->f.pid, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for pid %lu",
			    (unsigned long)opts->f.pid);

		if (!con)
			con = strdup(dummy_NIL);
		/* disabled -- override with normal context ...
		   {
		   opts->from_type = OPTS_FROM_PROC;
		   return (get_scon());
		   } */
		break;
	case OPTS_FROM_PROCKEY:
		ret = my_getpidkeycreatecon_raw(opts->f.pid, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for pid %lu",
			    (unsigned long)opts->f.pid);

		if (!con)
			con = strdup(dummy_NIL);
		break;

	case OPTS_FROM_FILE:
		ret = getfilecon_raw(opts->f.file, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for file %s",
			    opts->f.file);
		break;

	case OPTS_FROM_LINK:
		ret = lgetfilecon_raw(opts->f.link, &con);

		if (ret == -1)
			err(EXIT_FAILURE,
			    " Couldn't get security context for symlink %s",
			    opts->f.link);
		break;

	default:
		assert(FALSE);
	}

	if (opts->disp_raw != raw) {
		security_context_t ncon = NULL;

		if (opts->disp_raw)
			selinux_trans_to_raw_context(con, &ncon);
		else
			selinux_raw_to_trans_context(con, &ncon);

		freecon(con);
		con = ncon;
	}

	return (con);
}
Esempio n. 5
0
int mac_selinux_setup(bool *loaded_policy) {

#ifdef HAVE_SELINUX
        int enforce = 0;
        usec_t before_load, after_load;
        security_context_t con;
        int r;
        union selinux_callback cb;
        bool initialized = false;

        assert(loaded_policy);

        /* Turn off all of SELinux' own logging, we want to do that */
        cb.func_log = null_log;
        selinux_set_callback(SELINUX_CB_LOG, cb);

        /* Don't load policy in the initrd if we don't appear to have
         * it.  For the real root, we check below if we've already
         * loaded policy, and return gracefully.
         */
        if (in_initrd() && access(selinux_path(), F_OK) < 0)
                return 0;

        /* Already initialized by somebody else? */
        r = getcon_raw(&con);
        if (r == 0) {
                initialized = !streq(con, "kernel");
                freecon(con);
        }

        /* Make sure we have no fds open while loading the policy and
         * transitioning */
        log_close();

        /* Now load the policy */
        before_load = now(CLOCK_MONOTONIC);
        r = selinux_init_load_policy(&enforce);
        if (r == 0) {
                _cleanup_(mac_selinux_freep) char *label = NULL;
                char timespan[FORMAT_TIMESPAN_MAX];

                mac_selinux_retest();

                /* Transition to the new context */
                r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label);
                if (r < 0 || !label) {
                        log_open();
                        log_error("Failed to compute init label, ignoring.");
                } else {
                        r = setcon_raw(label);

                        log_open();
                        if (r < 0)
                                log_error("Failed to transition into init label '%s', ignoring.", label);
                }

                after_load = now(CLOCK_MONOTONIC);

                log_info("Successfully loaded SELinux policy in %s.",
                         format_timespan(timespan, sizeof(timespan), after_load - before_load, 0));

                *loaded_policy = true;

        } else {
Esempio n. 6
0
/*
   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) {

        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
        const char *tclass = NULL, *scon = NULL;
        struct audit_info audit_info = {};
        _cleanup_free_ char *cl = NULL;
        char *fcon = NULL;
        char **cmdline = NULL;
        int r = 0;

        assert(message);
        assert(permission);
        assert(error);

        r = 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_raw(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_raw(&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;
}
Esempio n. 7
0
int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
        int r = -EOPNOTSUPP;

#ifdef HAVE_SELINUX
        _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
        _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
        security_class_t sclass;
        const char *range = NULL;

        assert(socket_fd >= 0);
        assert(exe);
        assert(label);

        if (!mac_selinux_have())
                return -EOPNOTSUPP;

        r = getcon_raw(&mycon);
        if (r < 0)
                return -errno;

        r = getpeercon_raw(socket_fd, &peercon);
        if (r < 0)
                return -errno;

        if (!exec_label) {
                /* If there is no context set for next exec let's use context
                   of target executable */
                r = getfilecon_raw(exe, &fcon);
                if (r < 0)
                        return -errno;
        }

        bcon = context_new(mycon);
        if (!bcon)
                return -ENOMEM;

        pcon = context_new(peercon);
        if (!pcon)
                return -ENOMEM;

        range = context_range_get(pcon);
        if (!range)
                return -errno;

        r = context_range_set(bcon, range);
        if (r)
                return -errno;

        freecon(mycon);
        mycon = strdup(context_str(bcon));
        if (!mycon)
                return -ENOMEM;

        sclass = string_to_security_class("process");
        r = security_compute_create_raw(mycon, fcon, sclass, label);
        if (r < 0)
                return -errno;
#endif

        return r;
}
Esempio n. 8
0
/*
 * selinux_set_domain
 *
 *   It assigns an appropriate security context on the current
 *   working thread based on attributes of the given request.
 */
static int selinux_set_domain(request_rec *r)
{
    security_context_t  context;
    selinux_config *sconf;
    selinux_list   *entry;
    const char     *envval;
    char           *domain;
    int             rc = 0;

    sconf = ap_get_module_config(r->per_dir_config,
                                 &selinux_module);
    if (!sconf || !sconf->list)
        return 0;

    for (entry = sconf->list; !rc && entry; entry = entry->next)
    {
        switch (entry->method)
        {
        case SELINUX_DOMAIN_MAP:
            rc = selinux_lookup_mapfile(r, entry->value, &domain);
            break;

        case SELINUX_DOMAIN_ENV:
            envval = apr_table_get(r->subprocess_env, entry->value);
            if (envval) {
                domain = apr_pstrdup(r->pool, envval);
                rc = 1;
            }
            break;

        default: /* SELINUX_DOMAIN_VAL */
            domain = apr_pstrdup(r->pool, entry->value);
            rc = 1;
            break;
        }

        if (rc < 0)
            return -1;
    }

    /* no matched entry */
    if (rc == 0)
        return 0;

    if (getcon_raw(&context) < 0) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "SELinux: getcon_raw() failed");
        return -1;
    }

    rc = do_set_domain(context, domain, r->server);
    if (rc < 0) {
        freecon(context);
        return -1;
    }

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                  "SELinux: %s: %s/%s (uri=%s dir=%s user=%s remote=%s)",
                  (rc == 0 ? "replace handler domain"
                           : "no need to change handler domain"),
                  context, domain,
                  r->uri, sconf->dirname, r->user,
                  r->connection->remote_ip);

    freecon(context);
    return 0;
}
Esempio n. 9
0
/*
   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,
                bool system,
                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;

        r = sd_bus_creds_get_selinux_context(creds, &scon);
        if (r < 0)
                goto finish;

        tclass = "service";

        if (path && !system) {
                /* Get the file context of the unit file */

                r = getfilecon_raw(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;
                }
        } else {
                r = getcon_raw(&fcon);
                if (r < 0) {
                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                        goto finish;
                }
                if (system)
                        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
}
Esempio n. 10
0
uint32_t
mselinux_check_alloc(selinux_engine_t *se, const void *cookie,
					 const void *key, size_t keylen)
{
	static security_id_t	tsid = NULL;
	mcache_t	   *mcache;
	security_id_t	ssid;
	security_id_t	nsid;
	uint32_t		secid;

	if (!se->config.selinux)
		return 0;

	if (!tsid)
	{
		security_context_t	context;

		if (getcon_raw(&context) < 0)
			return 0;

		if (avc_context_to_sid_raw(context, &tsid) < 0)
		{
			freecon(context);
			return 0;
		}
		freecon(context);
	}

	/*
	 * It the new allocation tries to replace an existing key,
	 * we copy security id from the older chunk.
	 */
	mcache = mcache_get(se, key, keylen);
	if (mcache)
	{
		secid = mcache->mchunk->item.secid;
		if (secid > 0)
		{
			mchunk_t   *lchunk = mlabel_lookup_secid(se, secid);
			if (!lchunk)
				secid = 0;
			else
				lchunk->label.refcount++;
		}
		mcache_put(se, mcache);
		return secid;
	}

	ssid = se->server.core->get_engine_specific(cookie);

	pthread_rwlock_rdlock(&permissions.lock);

	avc_compute_create(ssid, tsid, permissions.tclass, &nsid);

	pthread_rwlock_unlock(&permissions.lock);

	secid = mlabel_get(se, nsid->ctx);

	if (se->config.debug)
		fprintf(stderr, "%s: ssid=%s tsid=%s nsid=%s (secid=%u)\n",
				__FUNCTION__, ssid->ctx, tsid->ctx, nsid->ctx, secid);
	return secid;
}
Esempio n. 11
0
int getcon(security_context_t *context)
{
    return getcon_raw(context);
}
Esempio n. 12
0
int selinux_setup(bool *loaded_policy) {

#ifdef HAVE_SELINUX
       int enforce = 0;
       usec_t before_load, after_load;
       security_context_t con;
       int r;
       union selinux_callback cb;

       assert(loaded_policy);

       /* Turn off all of SELinux' own logging, we want to do that */
       cb.func_log = null_log;
       selinux_set_callback(SELINUX_CB_LOG, cb);

       /* Already initialized by somebody else? */
       r = getcon_raw(&con);
       if (r == 0) {
               bool initialized;

               initialized = !streq(con, "kernel");
               freecon(con);

               if (initialized)
                       return 0;
       }

       /* Make sure we have no fds open while loading the policy and
        * transitioning */
       log_close();

       /* Now load the policy */
       before_load = now(CLOCK_MONOTONIC);
       r = selinux_init_load_policy(&enforce);
       if (r == 0) {
               char timespan[FORMAT_TIMESPAN_MAX];
               char *label;

               retest_selinux();

               /* Transition to the new context */
               r = label_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label);
               if (r < 0 || label == NULL) {
                       log_open();
                       log_error("Failed to compute init label, ignoring.");
               } else {
                       r = setcon(label);

                       log_open();
                       if (r < 0)
                               log_error("Failed to transition into init label '%s', ignoring.", label);

                       label_free(label);
               }

               after_load = now(CLOCK_MONOTONIC);

               log_info("Successfully loaded SELinux policy in %s.",
                         format_timespan(timespan, sizeof(timespan), after_load - before_load));

               *loaded_policy = true;

       } else {
               log_open();

               if (enforce > 0) {
                       log_error("Failed to load SELinux policy. Freezing.");
                       return -EIO;
               } else
                       log_debug("Unable to load SELinux policy. Ignoring.");
       }
#endif

       return 0;
}