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