summaryrefslogtreecommitdiff
path: root/plugins/sepolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/sepolicy.c')
-rw-r--r--plugins/sepolicy.c655
1 files changed, 0 insertions, 655 deletions
diff --git a/plugins/sepolicy.c b/plugins/sepolicy.c
deleted file mode 100644
index 86bf1981a..000000000
--- a/plugins/sepolicy.c
+++ /dev/null
@@ -1,655 +0,0 @@
-#include "plugin.h"
-
-#include <errno.h>
-#include <selinux/selinux.h>
-#include <semanage/semanage.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <rpm/rpmpol.h>
-#include <rpm/rpmfileutil.h>
-#include <rpm/rpmmacro.h>
-#include <rpm/rpmbase64.h>
-
-#include "lib/rpmte_internal.h"
-#include "lib/rpmts_internal.h" /* rpmtsSELabelFoo() */
-
-rpmPluginHook PLUGIN_HOOKS = \
- PLUGINHOOK_INIT | \
- PLUGINHOOK_CLEANUP | \
- PLUGINHOOK_OPENTE | \
- PLUGINHOOK_COLL_POST_ADD | \
- PLUGINHOOK_COLL_PRE_REMOVE;
-
-typedef enum sepolAction {
- SEPOL_ACTION_IGNORE,
- SEPOL_ACTION_INSTALL,
- SEPOL_ACTION_REMOVE
-} sepolAction;
-
-typedef struct sepol {
- char *data; /*!< policy data */
- char *name; /*!< policy names */
- ARGV_t types; /*!< policy types */
- uint32_t flags; /*!< policy flags */
- sepolAction action; /*!< install/remove/ignore */
- struct sepol *next; /*!< next in linked list */
-} sepol;
-
-typedef struct sepoltrans {
- int execsemodule; /*!< 0 = use libsemanage to install policy; non-zero = use semodule */
- semanage_handle_t *sh; /*!< handle to libsemanage, only used when execsemodule is zero */
- char *semodulepath; /*!< path to semodule binary */
- ARGV_t semodargs; /*!< argument list to pass to semodule, only used when execsemodule is non-zero */
- ARGV_t filelist; /*!< list of temporary files that have been written to disk during the transaction */
- int changes; /*!< number of changes made during the transaction */
-} sepoltrans;
-
-
-static char * name;
-static rpmts ts;
-
-static sepol * policiesHead;
-static sepol * policiesTail;
-
-
-static sepol *sepolNew(rpmte te);
-static sepol *sepolFree(sepol * pol);
-static int sepolHasType(const sepol * pol, const char *type);
-
-static rpmRC sepolPreparePolicies(sepol * pols, const char *policytype);
-static rpmRC sepolWritePolicy(const sepol * pol, char **path);
-static rpmRC sepolLoadPolicies(const sepol * pols);
-
-static sepoltrans *sepoltransNew(void);
-static sepoltrans *sepoltransFree(sepoltrans * pt);
-
-static rpmRC sepoltransInstall(sepoltrans * pt, const sepol * pol);
-static rpmRC sepoltransRemove(sepoltrans * pt, const sepol * pol);
-static rpmRC sepoltransCommit(sepoltrans * pt);
-
-
-static sepol *sepolNew(rpmte te)
-{
- sepol *head = NULL;
- sepol *ret = NULL;
- sepolAction action;
- Header h;
- struct rpmtd_s policies, names, types, typesidx, flags;
- int i, j;
- int count;
-
- rpmtdReset(&policies);
- rpmtdReset(&names);
- rpmtdReset(&types);
- rpmtdReset(&typesidx);
- rpmtdReset(&flags);
-
- h = rpmteHeader(te);
- if (!h) {
- goto exit;
- }
-
- if (!headerIsEntry(h, RPMTAG_POLICIES)) {
- goto exit;
- }
-
- if (!headerGet(h, RPMTAG_POLICIES, &policies, HEADERGET_MINMEM)) {
- goto exit;
- }
-
- count = rpmtdCount(&policies);
- if (count <= 0) {
- goto exit;
- }
-
- if (!headerGet(h, RPMTAG_POLICYNAMES, &names, HEADERGET_MINMEM)
- || rpmtdCount(&names) != count) {
- goto exit;
- }
-
- if (!headerGet(h, RPMTAG_POLICYFLAGS, &flags, HEADERGET_MINMEM)
- || rpmtdCount(&flags) != count) {
- goto exit;
- }
-
- if (!headerGet(h, RPMTAG_POLICYTYPES, &types, HEADERGET_MINMEM)) {
- goto exit;
- }
-
- if (!headerGet(h, RPMTAG_POLICYTYPESINDEXES, &typesidx, HEADERGET_MINMEM)
- || rpmtdCount(&types) != rpmtdCount(&typesidx)) {
- goto exit;
- }
-
- action = (rpmteType(te) == TR_ADDED) ? SEPOL_ACTION_INSTALL : SEPOL_ACTION_REMOVE;
-
- for (i = 0; i < count; i++) {
- sepol *pol = xcalloc(1, sizeof(*pol));
- pol->next = head;
- head = pol;
-
- pol->data = xstrdup(rpmtdNextString(&policies));
- pol->name = xstrdup(rpmtdNextString(&names));
- pol->flags = *rpmtdNextUint32(&flags);
- pol->action = action;
-
- for (j = 0; j < rpmtdCount(&types); j++) {
- uint32_t index = ((uint32_t *) typesidx.data)[j];
- if (index < 0 || index >= count) {
- goto exit;
- }
- if (index != i) {
- continue;
- }
- argvAdd(&pol->types, rpmtdNextString(&types));
- }
- argvSort(pol->types, NULL);
- }
-
- ret = head;
-
- exit:
- headerFree(h);
-
- rpmtdFreeData(&policies);
- rpmtdFreeData(&names);
- rpmtdFreeData(&types);
- rpmtdFreeData(&typesidx);
- rpmtdFreeData(&flags);
-
- if (!ret) {
- sepolFree(head);
- }
-
- return ret;
-}
-
-static sepol *sepolFree(sepol * pol)
-{
- while (pol) {
- sepol *next = pol->next;
-
- pol->data = _free(pol->data);
- pol->name = _free(pol->name);
- pol->types = argvFree(pol->types);
- pol->next = NULL;
- _free(pol);
-
- pol = next;
- }
-
- return NULL;
-}
-
-int sepolHasType(const sepol * pol, const char *type)
-{
- if (!pol || !type) {
- return 0;
- }
-
- return (argvSearch(pol->types, type, NULL) != NULL) ||
- (argvSearch(pol->types, RPMPOL_TYPE_DEFAULT, NULL) != NULL);
-}
-
-static rpmRC sepolPreparePolicies(sepol * pols, const char *policytype)
-{
- sepol *pol;
- rpmRC rc = RPMRC_OK;
-
- for (pol = pols; pol; pol = pol->next) {
- if (!sepolHasType(pol, policytype)) {
- pol->action = SEPOL_ACTION_IGNORE;
- }
- }
-
- return rc;
-}
-
-static rpmRC sepolWritePolicy(const sepol * pol, char **path)
-{
- char *tmppath = NULL;
- FD_t fd = NULL;
- char *policy = NULL;
- size_t policylen;
- rpmRC rc = RPMRC_FAIL;
-
- if (rpmBase64Decode(pol->data, (void **) &policy, &policylen) != 0) {
- rpmlog(RPMLOG_ERR, _("Failed to decode policy for %s\n"),
- pol->name);
- goto exit;
- }
-
- fd = rpmMkTempFile(NULL, &tmppath);
- if (fd == NULL || Ferror(fd)) {
- rpmlog(RPMLOG_ERR, _("Failed to create temporary file for %s: %s\n"),
- pol->name, strerror(errno));
- goto exit;
- }
-
- if (!Fwrite(policy, sizeof(*policy), policylen, fd)) {
- rpmlog(RPMLOG_ERR, _("Failed to write %s policy to file %s\n"),
- pol->name, tmppath);
- goto exit;
- }
-
- *path = tmppath;
- rc = RPMRC_OK;
-
- exit:
- if (fd)
- Fclose(fd);
- _free(policy);
- if (rc != RPMRC_OK)
- _free(tmppath);
-
- return rc;
-}
-
-static rpmRC sepolLoadPolicies(const sepol * pols)
-{
- const sepol *pol;
- rpmRC rc = RPMRC_FAIL;
- sepoltrans *pt = sepoltransNew();
-
- if (pt == NULL)
- goto exit;
-
- for (pol = pols; pol; pol = pol->next) {
- switch (pol->action) {
- case SEPOL_ACTION_REMOVE:
- rc = sepoltransRemove(pt, pol);
- break;
- case SEPOL_ACTION_INSTALL:
- rc = sepoltransInstall(pt, pol);
- break;
- case SEPOL_ACTION_IGNORE:
- default:
- rc = RPMRC_OK;
- break;
- }
-
- if (rc != RPMRC_OK)
- goto exit;
- }
-
- rc = sepoltransCommit(pt);
-
-exit:
- sepoltransFree(pt);
-
- return rc;
-}
-
-static sepoltrans *sepoltransNew(void)
-{
- sepoltrans *pt = xcalloc(1, sizeof(*pt));
- pt->semodulepath = rpmExpand("%{__semodule}", NULL);
- pt->execsemodule = (!rpmChrootDone() && access(pt->semodulepath, X_OK) == 0);
- pt->changes = 0;
-
- if (pt->execsemodule) {
- argvAdd(&pt->semodargs, "semodule");
- } else {
- pt->sh = semanage_handle_create();
- if (!pt->sh) {
- rpmlog(RPMLOG_ERR, _("Failed to create semanage handle\n"));
- goto err;
- }
- semanage_set_create_store(pt->sh, 1);
- semanage_set_check_contexts(pt->sh, 0);
- if (semanage_connect(pt->sh) < 0) {
- rpmlog(RPMLOG_ERR, _("Failed to connect to policy handler\n"));
- goto err;
- }
- if (semanage_begin_transaction(pt->sh) < 0) {
- rpmlog(RPMLOG_ERR, _("Failed to begin policy transaction: %s\n"),
- errno ? strerror(errno) : "");
- goto err;
- }
- semanage_set_reload(pt->sh, !rpmChrootDone());
- }
-
- return pt;
-
- err:
- if (pt->sh) {
- if (semanage_is_connected(pt->sh)) {
- semanage_disconnect(pt->sh);
- }
- semanage_handle_destroy(pt->sh);
- }
- free(pt);
-
- return NULL;
-}
-
-static sepoltrans *sepoltransFree(sepoltrans * pt)
-{
- ARGV_t file;
-
- if (!pt) {
- return NULL;
- }
-
- for (file = pt->filelist; file && *file; file++) {
- if (unlink(*file) < 0) {
- rpmlog(RPMLOG_WARNING, _("Failed to remove temporary policy file %s: %s\n"),
- *file, strerror(errno));
- }
- }
- argvFree(pt->filelist);
-
- if (pt->execsemodule) {
- argvFree(pt->semodargs);
- } else {
- semanage_disconnect(pt->sh);
- semanage_handle_destroy(pt->sh);
- }
-
- free(pt->semodulepath);
- memset(pt, 0, sizeof(*pt)); /* trash and burn */
-
- free(pt);
- return NULL;
-}
-
-static rpmRC sepoltransInstall(sepoltrans * pt, const sepol * pol)
-{
- rpmRC rc = RPMRC_OK;
- char *path = NULL;
-
- rc = sepolWritePolicy(pol, &path);
- if (rc != RPMRC_OK) {
- return rc;
- }
- argvAdd(&pt->filelist, path);
-
- if (pt->execsemodule) {
- const char *flag = (pol->flags & RPMPOL_FLAG_BASE) ? "-b" : "-i";
- if (argvAdd(&pt->semodargs, flag) < 0 || argvAdd(&pt->semodargs, path) < 0) {
- rc = RPMRC_FAIL;
- }
- } else {
- if (pol->flags & RPMPOL_FLAG_BASE) {
- if (semanage_module_install_base_file(pt->sh, path) < 0) {
- rc = RPMRC_FAIL;
- }
- } else {
- if (semanage_module_install_file(pt->sh, path) < 0) {
- rc = RPMRC_FAIL;
- }
- }
- }
-
- if (rc != RPMRC_OK) {
- rpmlog(RPMLOG_ERR, _("Failed to install policy module: %s (%s)\n"),
- pol->name, path);
- } else {
- pt->changes++;
- }
-
- _free(path);
-
- return rc;
-}
-
-static rpmRC sepoltransRemove(sepoltrans * pt, const sepol * pol)
-{
- rpmRC rc = RPMRC_OK;
-
- if (pol->flags & RPMPOL_FLAG_BASE) {
- return RPMRC_FAIL;
- }
-
- if (pt->execsemodule) {
- if (argvAdd(&pt->semodargs, "-r") < 0 || argvAdd(&pt->semodargs, pol->name) < 0) {
- rc = RPMRC_FAIL;
- }
- } else {
- if (semanage_module_remove(pt->sh, (char *) pol->name) < 0) {
- rc = RPMRC_FAIL;
- }
- }
-
- if (rc != RPMRC_OK) {
- rpmlog(RPMLOG_ERR, _("Failed to remove policy module: %s\n"),
- pol->name);
- } else {
- pt->changes++;
- }
-
- return rc;
-}
-
-static rpmRC sepoltransCommit(sepoltrans * pt)
-{
- rpmRC rc = RPMRC_OK;
-
- if (pt->changes == 0) {
- return rc;
- }
-
- if (pt->execsemodule) {
- int status;
- pid_t pid = fork();
- int fd;
-
- switch (pid) {
- case -1:
- rpmlog(RPMLOG_ERR, _("Failed to fork process: %s\n"),
- strerror(errno));
- rc = RPMRC_FAIL;
- break;
- case 0:
- fd = open("/dev/null", O_RDWR);
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- execv(pt->semodulepath, pt->semodargs);
- rpmlog(RPMLOG_ERR, _("Failed to execute %s: %s\n"),
- pt->semodulepath, strerror(errno));
- exit(1);
- default:
- waitpid(pid, &status, 0);
- if (!WIFEXITED(status)) {
- rpmlog(RPMLOG_ERR, _("%s terminated abnormally\n"),
- pt->semodulepath);
- rc = RPMRC_FAIL;
- } else if (WEXITSTATUS(status)) {
- rpmlog(RPMLOG_ERR, _("%s failed with exit code %i\n"),
- pt->semodulepath, WEXITSTATUS(status));
- rc = RPMRC_FAIL;
- }
- }
- } else {
- if (semanage_commit(pt->sh) < 0) {
- rpmlog(RPMLOG_ERR, _("Failed to commit policy changes\n"));
- rc = RPMRC_FAIL;
- }
- }
-
- return rc;
-}
-
-static rpmRC sepolRelabelFiles(void)
-{
- rpmRC rc = RPMRC_OK;
- pid_t pid;
- int fd;
- int status;
- char *restoreconPath = rpmExpand("%{__restorecon}", NULL);
-
- if (!restoreconPath) {
- rpmlog(RPMLOG_ERR, _("Failed to expand restorecon path"));
- return RPMRC_FAIL;
- }
-
- /* execute restorecon -R / */
- pid = fork();
- switch (pid) {
- case -1:
- rpmlog(RPMLOG_ERR, _("Failed to fork process: %s\n"),
- strerror(errno));
- rc = RPMRC_FAIL;
- break;
- case 0:
- fd = open("/dev/null", O_RDWR);
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- execl(restoreconPath, "restorecon", "-R", "/", NULL);
- rpmlog(RPMLOG_ERR, _("Failed to execute %s: %s\n"), restoreconPath,
- strerror(errno));
- exit(1);
- default:
- waitpid(pid, &status, 0);
- if (!WIFEXITED(status)) {
- rpmlog(RPMLOG_ERR, _("%s terminated abnormally\n"),
- restoreconPath);
- rc = RPMRC_FAIL;
- } else if (WEXITSTATUS(status)) {
- rpmlog(RPMLOG_ERR, _("%s failed with exit code %i\n"),
- restoreconPath, WEXITSTATUS(status));
- rc = RPMRC_FAIL;
- }
- }
-
- _free(restoreconPath);
-
- return rc;
-}
-
-static rpmRC sepolGo(void)
-{
- semanage_handle_t *sh;
- int existingPolicy;
- char *policytype = NULL;
- rpmRC rc = RPMRC_FAIL;
-
- static int performed = 0;
- if (performed) {
- return RPMRC_OK;
- }
- performed = 1;
-
- if (rpmChrootIn()) {
- goto exit;
- }
-
- if (selinux_getpolicytype(&policytype) < 0) {
- goto exit;
- }
-
- sepolPreparePolicies(policiesHead, policytype);
-
- /* determine if this is the first time installing policy */
- sh = semanage_handle_create();
- existingPolicy = (semanage_is_managed(sh) == 1);
- semanage_handle_destroy(sh);
-
- /* now load the policies */
- rc = sepolLoadPolicies(policiesHead);
-
- /* re-init selinux and re-read the files contexts, since things may have changed */
- selinux_reset_config();
- if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
- if (rpmtsSELabelInit(ts, 0) == RPMRC_OK) {
- /* if this was the first time installing policy, every package before
- * policy was installed will be mislabeled (e.g. semodule). So, relabel
- * the entire filesystem if this is the case */
- if (!existingPolicy) {
- if (sepolRelabelFiles() != RPMRC_OK) {
- rpmlog(RPMLOG_WARNING, _("Failed to relabel filesystem. Files may be mislabeled\n"));
- }
- }
- } else {
- rpmlog(RPMLOG_WARNING, _("Failed to reload file contexts. Files may be mislabeled\n"));
- }
- }
-
- exit:
- if (rpmChrootOut()) {
- rc = RPMRC_FAIL;
- }
-
- _free(policytype);
-
- return rc;
-}
-
-static rpmRC sepolAddTE(rpmte te)
-{
- sepol *pol;
- sepol *polTail;
-
- if (!rpmteHasCollection(te, name)) {
- return RPMRC_OK;
- }
-
- pol = sepolNew(te);
- if (!pol) {
- /* something's wrong with the policy information, either missing or
- * corrupt. abort */
- rpmlog(RPMLOG_ERR, _("Failed to extract policy from %s\n"),
- rpmteNEVRA(te));
- return RPMRC_FAIL;
- }
-
- /* find the tail of pol */
- polTail = pol;
- while (polTail->next) {
- polTail = polTail->next;
- }
-
- /* add the new policy to the list */
- if (!policiesHead) {
- policiesHead = pol;
- policiesTail = polTail;
- } else {
- if (rpmteType(te) == TR_ADDED) {
- /* add to the end of the list */
- policiesTail->next = pol;
- policiesTail = polTail;
- } else {
- /* add to the beginning of the list */
- polTail->next = policiesHead;
- policiesHead = pol;
- }
- }
-
- return RPMRC_OK;
-}
-
-
-
-rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *_name, const char *_opts)
-{
- ts = _ts;
- name = strdup(_name);
- policiesHead = policiesTail = NULL;
- return RPMRC_OK;
-}
-
-rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
-{
- _free(name);
- ts = NULL;
- policiesHead = policiesTail = sepolFree(policiesHead);
- return RPMRC_OK;
-}
-
-rpmRC PLUGINHOOK_OPENTE_FUNC(rpmte te)
-{
- return sepolAddTE(te);
-}
-
-rpmRC PLUGINHOOK_COLL_POST_ADD_FUNC(void)
-{
- return sepolGo();
-}
-
-rpmRC PLUGINHOOK_COLL_PRE_REMOVE_FUNC(void)
-{
- return sepolGo();
-}