Exemplo n.º 1
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;
}
Exemplo n.º 2
0
int setfilecon_raw(const char *path, const security_context_t context)
{
	int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
			0);
	if (rc < 0 && errno == ENOTSUP) {
		security_context_t ccontext = NULL;
		int err = errno;
		if ((getfilecon_raw(path, &ccontext) >= 0) &&
		    (strcmp(context,ccontext) == 0)) {
			rc = 0;
		} else {
			errno = err;
		}
		freecon(ccontext);
	}
	return rc;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo 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,
                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
}
Exemplo n.º 7
0
int getfilecon(const char *path, security_context_t *con)
{
    return getfilecon_raw(path, con);
}