Blame plugins/selinux.c

Packit Service 7203c3
#include "system.h"
Packit Service 7203c3
Packit Service 7203c3
#include <selinux/selinux.h>
Packit Service 7203c3
#include <selinux/context.h>
Packit Service 7203c3
#include <selinux/label.h>
Packit Service 7203c3
#include <selinux/avc.h>
Packit Service 7203c3
#include <rpm/rpmlog.h>
Packit Service 7203c3
#include <rpm/rpmts.h>
Packit Service 7203c3
#include "lib/rpmplugin.h"
Packit Service 7203c3
Packit Service 7203c3
#include "debug.h"
Packit Service 7203c3
Packit Service 7203c3
static struct selabel_handle * sehandle = NULL;
Packit Service 7203c3
Packit Service 7203c3
static void sehandle_fini(int close_status)
Packit Service 7203c3
{
Packit Service 7203c3
    if (sehandle) {
Packit Service 7203c3
	selabel_close(sehandle);
Packit Service 7203c3
	sehandle = NULL;
Packit Service 7203c3
    }
Packit Service 7203c3
    if (close_status) {
Packit Service 7203c3
	selinux_status_close();
Packit Service 7203c3
    }
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
static rpmRC sehandle_init(int open_status)
Packit Service 7203c3
{
Packit Service 7203c3
    const char * path = selinux_file_context_path();
Packit Service 7203c3
    struct selinux_opt opts[] = {
Packit Service 7203c3
	{ .type = SELABEL_OPT_PATH, .value = path }
Packit Service 7203c3
    };
Packit Service 7203c3
    
Packit Service 7203c3
    if (path == NULL)
Packit Service 7203c3
	return RPMRC_FAIL;
Packit Service 7203c3
Packit Service 7203c3
    if (open_status) {
Packit Service 7203c3
	selinux_status_close();
Packit Service 7203c3
	if (selinux_status_open(0) < 0) {
Packit Service 7203c3
	    return RPMRC_FAIL;
Packit Service 7203c3
	}
Packit Service 7203c3
    } else if (!selinux_status_updated() && sehandle) {
Packit Service 7203c3
	return RPMRC_OK;
Packit Service 7203c3
    }
Packit Service 7203c3
Packit Service 7203c3
    if (sehandle)
Packit Service 7203c3
	sehandle_fini(0);
Packit Service 7203c3
Packit Service 7203c3
    sehandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
Packit Service 7203c3
Packit Service 924817
    rpmlog((sehandle == NULL) ? RPMLOG_ERR : RPMLOG_DEBUG, "selabel_open: (%s) %s\n",
Packit Service 7203c3
	   path, (sehandle == NULL ? strerror(errno) : ""));
Packit Service 7203c3
Packit Service 7203c3
    return (sehandle != NULL) ? RPMRC_OK : RPMRC_FAIL;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
static rpmRC selinux_tsm_pre(rpmPlugin plugin, rpmts ts)
Packit Service 7203c3
{
Packit Service 7203c3
    rpmRC rc = RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
    /* If SELinux isn't enabled on the system, dont mess with it */
Packit Service 7203c3
    if (!is_selinux_enabled()) {
Packit Service 7203c3
	rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
Packit Service 7203c3
    }
Packit Service 7203c3
Packit Service 7203c3
    /* If not enabled or a test-transaction, dont bother with labels */
Packit Service 7203c3
    if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOCONTEXTS|RPMTRANS_FLAG_TEST))) {
Packit Service 7203c3
	rc = sehandle_init(1);
Packit Service 7203c3
    }
Packit Service 7203c3
Packit Service 7203c3
    return rc;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
static rpmRC selinux_tsm_post(rpmPlugin plugin, rpmts ts, int rc)
Packit Service 7203c3
{
Packit Service 7203c3
    if (sehandle) {
Packit Service 7203c3
	sehandle_fini(1);
Packit Service 7203c3
    }
Packit Service 7203c3
    return RPMRC_OK;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
static rpmRC selinux_psm_pre(rpmPlugin plugin, rpmte te)
Packit Service 7203c3
{
Packit Service 7203c3
    rpmRC rc = RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
    if (sehandle) {
Packit Service 7203c3
	/* reload the labels if policy changed underneath */
Packit Service 7203c3
	rc = sehandle_init(0);
Packit Service 7203c3
    }
Packit Service 7203c3
    return rc;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
#ifndef HAVE_SETEXECFILECON
Packit Service 7203c3
static int setexecfilecon(const char *path, const char *fallback_type)
Packit Service 7203c3
{
Packit Service 7203c3
    int rc = -1;
Packit Service 7203c3
    security_context_t mycon = NULL, fcon = NULL, newcon = NULL;
Packit Service 7203c3
    context_t con = NULL;
Packit Service 7203c3
Packit Service 7203c3
    /* Figure the context to for next exec() */
Packit Service 7203c3
    if (getcon(&mycon) < 0)
Packit Service 7203c3
	goto exit;
Packit Service 7203c3
    if (getfilecon(path, &fcon) < 0)
Packit Service 7203c3
	goto exit;
Packit Service 7203c3
    if (security_compute_create(mycon, fcon,
Packit Service 7203c3
			string_to_security_class("process"), &newcon) < 0)
Packit Service 7203c3
	goto exit;
Packit Service 7203c3
Packit Service 7203c3
    if (rstreq(mycon, newcon)) {
Packit Service 7203c3
	con = context_new(mycon);
Packit Service 7203c3
	if (!con)
Packit Service 7203c3
	    goto exit;
Packit Service 7203c3
	if (context_type_set(con, fallback_type))
Packit Service 7203c3
	    goto exit;
Packit Service 7203c3
	freecon(newcon);
Packit Service 7203c3
	newcon = xstrdup(context_str(con));
Packit Service 7203c3
    }
Packit Service 7203c3
Packit Service 7203c3
    rc = setexeccon(newcon);
Packit Service 7203c3
Packit Service 7203c3
exit:
Packit Service 7203c3
    context_free(con);
Packit Service 7203c3
    freecon(newcon);
Packit Service 7203c3
    freecon(fcon);
Packit Service 7203c3
    freecon(mycon);
Packit Service 7203c3
    return rc;
Packit Service 7203c3
}
Packit Service 7203c3
#endif
Packit Service 7203c3
Packit Service 7203c3
static rpmRC selinux_scriptlet_fork_post(rpmPlugin plugin,
Packit Service 7203c3
						 const char *path, int type)
Packit Service 7203c3
{
Packit Service 7203c3
    /* No default transition, use rpm_script_t for now. */
Packit Service 7203c3
    const char *script_type  = "rpm_script_t";
Packit Service 7203c3
    rpmRC rc = RPMRC_FAIL;
Packit Service 7203c3
Packit Service 7203c3
    if (sehandle == NULL)
Packit Service 7203c3
	return RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
    if (setexecfilecon(path, script_type) == 0)
Packit Service 7203c3
	rc = RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
    /* If selinux is not enforcing, we don't care either */
Packit Service 7203c3
    if (rc && security_getenforce() < 1)
Packit Service 7203c3
	rc = RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
    rpmlog(rc ? RPMLOG_ERR : RPMLOG_DEBUG, "setexecfilecon: (%s, %s) %s\n",
Packit Service 7203c3
	   path, script_type, rc ? strerror(errno) : "");
Packit Service 7203c3
Packit Service 7203c3
    return rc;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
static rpmRC selinux_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
Packit Service 7203c3
					const char *path, const char *dest,
Packit Service 7203c3
				        mode_t file_mode, rpmFsmOp op)
Packit Service 7203c3
{
Packit Service 7203c3
    rpmRC rc = RPMRC_FAIL; /* assume failure */
Packit Service 7203c3
    rpmFileAction action = XFO_ACTION(op);
Packit Service 7203c3
Packit Service 7203c3
    if (sehandle && !XFA_SKIPPING(action)) {
Packit Service 7203c3
	security_context_t scon = NULL;
Packit Service 7203c3
	if (selabel_lookup_raw(sehandle, &scon, dest, file_mode) == 0) {
Packit Service 7203c3
	    int conrc = lsetfilecon(path, scon);
Packit Service 7203c3
Packit Service 7203c3
	    if (conrc == 0 || (conrc < 0 && errno == EOPNOTSUPP))
Packit Service 7203c3
		rc = RPMRC_OK;
Packit Service 7203c3
Packit Service 7203c3
	    rpmlog((rc != RPMRC_OK) ? RPMLOG_ERR : RPMLOG_DEBUG,
Packit Service 7203c3
		   "lsetfilecon: (%s, %s) %s\n",
Packit Service 7203c3
		   path, scon, (conrc < 0 ? strerror(errno) : ""));
Packit Service 7203c3
Packit Service 7203c3
	    freecon(scon);
Packit Service 7203c3
	} else {
Packit Service 7203c3
	    /* No context for dest is not our headache */
Packit Service 7203c3
	    if (errno == ENOENT)
Packit Service 7203c3
		rc = RPMRC_OK;
Packit Service 7203c3
	}
Packit Service 7203c3
    } else {
Packit Service 7203c3
	rc = RPMRC_OK;
Packit Service 7203c3
    }
Packit Service 7203c3
Packit Service 7203c3
    return rc;
Packit Service 7203c3
}
Packit Service 7203c3
Packit Service 7203c3
struct rpmPluginHooks_s selinux_hooks = {
Packit Service 7203c3
    .tsm_pre = selinux_tsm_pre,
Packit Service 7203c3
    .tsm_post = selinux_tsm_post,
Packit Service 7203c3
    .psm_pre = selinux_psm_pre,
Packit Service 7203c3
    .scriptlet_fork_post = selinux_scriptlet_fork_post,
Packit Service 7203c3
    .fsm_file_prepare = selinux_fsm_file_prepare,
Packit Service 7203c3
};