summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena Reshetova <elena.reshetova@intel.com>2013-09-26 11:30:54 +0300
committerElena Reshetova <elena.reshetova@intel.com>2013-09-27 10:41:47 +0300
commit2a4cb0f4d4de732ec10b4e7729c24b4c4fc41e2c (patch)
treea333df5e8b5a447f7b08c13944fec0cfbd51c6b4
parent570bf157b85ce8a272fff03669a3e2eca68da431 (diff)
downloadrpm-2a4cb0f4d4de732ec10b4e7729c24b4c4fc41e2c.tar.gz
rpm-2a4cb0f4d4de732ec10b4e7729c24b4c4fc41e2c.tar.bz2
rpm-2a4cb0f4d4de732ec10b4e7729c24b4c4fc41e2c.zip
Security plugin: plugin hooks code refactoring and improvment
Change-Id: I4d44db47865dd5c83fcf28435ffc26a70164b69d
-rw-r--r--plugins/msm-plugin.c514
-rw-r--r--plugins/msm.h46
-rw-r--r--plugins/msmconfig.c139
-rw-r--r--plugins/msmmanifest.c38
-rw-r--r--plugins/msmxattr.c4
5 files changed, 400 insertions, 341 deletions
diff --git a/plugins/msm-plugin.c b/plugins/msm-plugin.c
index 569f9a2ce..2290ac271 100644
--- a/plugins/msm-plugin.c
+++ b/plugins/msm-plugin.c
@@ -35,7 +35,6 @@
#include <sys/stat.h>
#include <rpm/rpmfileutil.h>
-#include <rpm/rpmmacro.h>
#include <rpm/rpmpgp.h>
#include <rpm/rpmkeyring.h>
#include <rpm/rpmdb.h>
@@ -77,165 +76,179 @@ typedef struct packagecontext {
struct smack_accesses *smack_accesses; /*!< handle to smack_accesses */
} packagecontext;
-static rpmts ts = NULL;
-static int rootSWSource= 0;
-static manifest_x *root = NULL; /* pointer to device security policy file */
+static rpmts ts = NULL; /* rpm transaction */
+static manifest_x *dsp = NULL; /* pointer to device security policy file */
static packagecontext *context = NULL;
static sw_source_x *current = NULL;
static packagecontext *contextsHead = NULL;
static packagecontext *contextsTail = NULL;
static fileconflict *allfileconflicts = NULL;
-static char* ownSmackLabel = NULL;
-static int SmackEnabled = 0;
+static char* ownSmackLabel = NULL; /* rpm smack security context */
+static int SmackEnabled = 0; /* indicates if Smack is enabled in kernel or not */
static magic_t cookie = NULL;
static int package_created = 0;
-static int copyFile(char *old_filename, char *new_filename)
+/* Support functions */
+
+/**
+ * Frees the given pointer and sets it to NULL
+ * @param ptr address of pointer to be freed
+ * @return NULL
+ */
+static packagecontext *msmFree(packagecontext *ctx)
+{
+ while (ctx) {
+ packagecontext *next = ctx->next;
+ msmFreePointer((void**)&ctx->data);
+ ctx->mfx = msmFreeManifestXml(ctx->mfx);
+ if (ctx->smack_accesses) smack_accesses_free(ctx->smack_accesses);
+ msmFreePointer((void**)&ctx);
+ ctx = next;
+ }
+ return NULL;
+}
+
+/**
+ * Frees the given pointer and sets it to NULL
+ * @param ptr address of pointer to be freed
+ * @return
+ */
+void msmFreePointer(void** ptr)
{
- FD_t ptr_old, ptr_new;
- int res;
+ if (*ptr)
+ free(*ptr);
+ *ptr = NULL;
+ return;
+}
+
+/**
+ * Creates a new package context
+ * @param te rpm te struct
+ * @return created package context
+ */
+static packagecontext *msmNew(rpmte te)
+{
+ Header h;
+ struct rpmtd_s msm;
+ int count;
+ packagecontext *ctx = NULL;
+ const char *sw_source = NULL;
+
+ rpmtdReset(&msm);
+
+ h = rpmteHeader(te);
+ if (!h) return NULL;
+
+ ctx = xcalloc(1, sizeof(*ctx));
+ if (!ctx) {
+ goto exit1;
+ }
+ ctx->te = te;
- ptr_old = Fopen(old_filename, "r.fdio");
- ptr_new = Fopen(new_filename, "w.fdio");
+ if (!headerIsEntry(h, RPMTAG_SECMANIFEST)) {
+ goto exit1;
+ }
- if ((ptr_old == NULL) || (Ferror(ptr_old))) {
- return -1;
+ if (!headerGet(h, RPMTAG_SECMANIFEST, &msm, HEADERGET_MINMEM)) {
+ goto exit1;
}
- if ((ptr_new == NULL) || (Ferror(ptr_new))) {
- Fclose(ptr_old);
- return -1;
+ count = rpmtdCount(&msm);
+ if (count != 1) {
+ goto exit2;
+ }
+
+ ctx->data = xstrdup(rpmtdNextString(&msm));
+ rpmlog(RPMLOG_DEBUG, "%s manifest b64 data: %.40s...\n",
+ rpmteN(ctx->te), ctx->data);
+ exit2:
+ rpmtdFreeData(&msm);
+ exit1:
+ if (rpmteType(ctx->te) == TR_ADDED) {
+ /* Save sw_source name into database, we need it when package */
+ /* is removed because signature verify is not called then. */
+ if (current) sw_source = current->name;
+ if (!sw_source || !headerPutString(h, RPMTAG_SECSWSOURCE, sw_source)) {
+ rpmlog(RPMLOG_ERR, "Failed to save sw source for %s, sw_source: %s\n",
+ rpmteN(ctx->te), sw_source);
+ msmFreePointer((void**)&ctx->data);
+ msmFreePointer((void**)&ctx);
+ }
}
+ headerFree(h);
- res = ufdCopy(ptr_old, ptr_new);
+ return ctx;
+}
- Fclose(ptr_new);
- Fclose(ptr_old);
- return res;
+/**
+ * Creates and adds a te package context to a context list
+ * @param te rpm te struct
+ * @return created and added package context
+ */
+static packagecontext *msmAddTE(rpmte te)
+{
+ packagecontext *ctx = msmNew(te);
+ if (ctx) {
+ /* add the new policy to the list */
+ if (!contextsHead) {
+ contextsHead = ctx;
+ contextsTail = ctx;
+ } else {
+ if (rpmteType(te) == TR_ADDED) {
+ /* add to the end of the list */
+ contextsTail->next = ctx;
+ contextsTail = ctx;
+ } else {
+ /* add to the beginning of the list */
+ ctx->next = contextsHead;
+ contextsHead = ctx;
+ }
+ }
+ }
+ return ctx;
}
+/* -------------------- */
+
+/* Implementation of hooks */
+/* Hooks are listed in the call sequence inside rpm code */
+
rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
{
ts = _ts;
- char *fullPath = NULL, *fullPath1 = NULL;
- char *defaultPolicyPath = NULL;
- struct stat buf;
if (!ts)
return RPMRC_FAIL;
- fullPath = rpmGenPath(ts->rootDir, DEVICE_SECURITY_POLICY, NULL);
- rpmlog(RPMLOG_DEBUG, "fullPath %s\n", fullPath);
- if (!fullPath) {
- rpmlog(RPMLOG_ERR, "Building a full path failed for device security policy\n");
- goto plugin_error;
- }
+ if (msmLoadDeviceSecurityPolicy(ts->rootDir, &dsp) == RPMRC_FAIL)
+ return RPMRC_FAIL;
- if (stat(fullPath, &buf) != 0) { // the policy file is missing
- if (ts->rootDir) { // we are running with --root option and policy is missing, need to copy it for now
- // first create prefix for it
- char *sysconfdir = rpmExpand("%{?_sysconfdir}", NULL);
- if (!sysconfdir || !strcmp(sysconfdir, "")) {
- rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
- goto plugin_error;
- }
- fullPath1 = rpmGenPath(ts->rootDir, sysconfdir, NULL);
- rpmlog(RPMLOG_DEBUG, "fullPath1 %s\n", fullPath1);
- msmFreePointer((void**)&sysconfdir);
- if (!fullPath1) {
- rpmlog(RPMLOG_ERR, "Building a full path for sysconfdir failed\n");
- goto plugin_error;
- }
- if (rpmioMkpath(fullPath1, 0755, getuid(), getgid()) != 0) {
- rpmlog(RPMLOG_ERR, "Failed to create a path for policy file\n");
- goto plugin_error;
- }
- defaultPolicyPath = rpmExpand("%{?__transaction_msm_default_policy}", NULL);
- if (!defaultPolicyPath || !strcmp(defaultPolicyPath, "")) {
- rpmlog(RPMLOG_ERR, "Failed to expand transaction_msm_default_policy macro\n");
- goto plugin_error;
- }
- if(copyFile(defaultPolicyPath, fullPath) == -1) {
- /* Do not allow plug-in to proceed without security policy existing */
- rpmlog(RPMLOG_ERR, "Failed to copy the policy outside of chroot. Abort installation.\n");
- goto plugin_error;
- }
- } else {
- /* Do not allow plug-in to proceed without security policy existing */
- rpmlog(RPMLOG_ERR, "Policy file is missing at %s. Abort installation.\n",
- fullPath);
- goto plugin_error;
- }
- }
+ if (!dsp)
+ return RPMRC_FAIL;
- rpmlog(RPMLOG_DEBUG, "reading device security policy from %s\n", fullPath);
- root = msmProcessDevSecPolicyXml(fullPath);
+ /* smackfs path doesn't need to be prefixed with ts->rootDir
+ since it is only used for loading rules to kernel and libsmack will load it
+ by itself to the correct path */
- if (!root) {
- rpmlog(RPMLOG_ERR, "Failed process sw sources from %s\n", fullPath);
- goto plugin_error;
+ if (smack_smackfs_path() == NULL) {
+ rpmlog(RPMLOG_INFO, "Smackfs isn't mounted at %s. Going to the image build mode. \n", smack_smackfs_path());
+ ownSmackLabel = strdup("_");
+ SmackEnabled = 0;
} else {
- if (msmSetupSWSources(NULL, root, NULL)) {
- rpmlog(RPMLOG_ERR, "Failed to setup security policy from %s\n",fullPath);
- goto plugin_error;
- }
- }
-
- msmFreePointer((void**)&fullPath);
- msmFreePointer((void**)&fullPath1);
- msmFreePointer((void**)&defaultPolicyPath);
-
- fullPath = rpmGenPath(ts->rootDir, SMACK_LOAD_PATH, NULL);
- rpmlog(RPMLOG_DEBUG, "fullPath for SMACK_LOAD_PATH %s\n", fullPath);
- if (!fullPath) {
- rpmlog(RPMLOG_ERR, "Building a full path for smack load failed\n");
- goto plugin_error;
- }
-
- /* check its own security context and store it for the case when packages without manifest will be installed */
- if (stat(fullPath, &buf) == 0) {
+ /* check its own security context and store it for the case when packages without manifest will be installed */
int res = smack_new_label_from_self(&ownSmackLabel);
SmackEnabled = 1;
if (res < 0) {
rpmlog(RPMLOG_ERR, "Failed to obtain rpm security context\n");
- goto plugin_error;
- }
- } else {
- rpmlog(RPMLOG_INFO, "Smackfs isn't mounted at %s. Going to the image build mode. \n", fullPath);
- ownSmackLabel = strdup("_");
- SmackEnabled = 0;
- }
-
- msmFreePointer((void**)&fullPath);
- fullPath = rpmGenPath(ts->rootDir, SMACK_RULES_PATH, NULL);
- fullPath1 = rpmGenPath(ts->rootDir, SMACK_RULES_PATH_BEG, NULL);
- rpmlog(RPMLOG_DEBUG, "fullPath for SMACK_RULES_PATH %s\n", fullPath);
- rpmlog(RPMLOG_DEBUG, "fullPath1 for SMACK_RULES_PATH_BEG %s\n", fullPath1);
- if ((!fullPath) || (!fullPath1)){
- rpmlog(RPMLOG_ERR, "Building a full path failed for smack rules path\n");
- goto plugin_error;
- }
-
- if (stat(fullPath, &buf) != 0) {
- rpmlog(RPMLOG_DEBUG, "A directory for writing smack rules is missing. Creating one.\n");
- mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH; // 644 -rwer--r--
- if (stat(fullPath1, &buf) != 0) {
- if (mkdir(fullPath1, mode) != 0) {
- rpmlog(RPMLOG_ERR, "Failed to create a sub-directory for smack rules\n");
- goto plugin_error;
- }
+ return RPMRC_FAIL;
}
- if (mkdir(fullPath, mode) != 0){
- rpmlog(RPMLOG_ERR, "Failed to create a directory for smack rules\n");
- goto plugin_error;
- }
}
- msmFreePointer((void**)&fullPath);
- msmFreePointer((void**)&fullPath1);
-
rpmlog(RPMLOG_DEBUG, "rpm security context: %s\n", ownSmackLabel);
+ if (msmSetupSmackRulesDir(ts->rootDir) == RPMRC_FAIL)
+ return RPMRC_FAIL;
+
cookie = magic_open(0);
if (!cookie)
return RPMRC_FAIL;
@@ -248,18 +261,6 @@ rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
}
return RPMRC_OK;
-
-plugin_error:
- msmFreePointer((void**)&fullPath);
- msmFreePointer((void**)&fullPath1);
- msmFreePointer((void**)&defaultPolicyPath);
- return RPMRC_FAIL;
-}
-
-static int findSWSourceByName(sw_source_x *sw_source, void *param, void* param2)
-{
- const char *name = (const char *)param;
- return strcmp(sw_source->name, name);
}
rpmRC PLUGINHOOK_FILE_CONFLICT_FUNC(rpmts ts, char* path,
@@ -267,18 +268,23 @@ rpmRC PLUGINHOOK_FILE_CONFLICT_FUNC(rpmts ts, char* path,
int rpmrc)
{
fileconflict *fc;
- if (!path)
+ if ((!path) || (!dsp))
return rpmrc;
- rpmlog(RPMLOG_DEBUG, "FILE_CONFLICT_FUNC hook path %s\n",path);
+ rpmlog(RPMLOG_DEBUG, "FILE_CONFLICT_FUNC hook path %s\n",path);
+
+ /* uncomment this code if you wish that plugin obeys --replacefiles rpm flag
+ if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES) {
+ return rpmrc;
+ } */
- const char *name = headerGetString(oldHeader, RPMTAG_SECSWSOURCE);
+ const char *sw_source_name = headerGetString(oldHeader, RPMTAG_SECSWSOURCE);
const char *pkg_name = headerGetString(oldHeader, RPMTAG_NAME);
- if (!name || !root || !pkg_name) {
- return rpmrc; /* no sw source(s) or package name - abnormal state */
+ if (!sw_source_name || !pkg_name) {
+ return rpmrc; /* no sw source or package name - abnormal state */
}
- sw_source_x *sw_source = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)name, NULL);
+ sw_source_x *sw_source = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)sw_source_name, NULL);
if (!sw_source)
return rpmrc; /* no old sw_source - abnormal state */
@@ -301,77 +307,25 @@ rpmRC PLUGINHOOK_FILE_CONFLICT_FUNC(rpmts ts, char* path,
msmFreePointer((void**)&path);
}
- if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES) {
- /* Conflict has been noted, now return ok. It will be actually */
- /* resolved later when conflicting package signature is verified */
- /* and sw_source is known. */
- return rpmrc;
- }
return rpmrc;
}
rpmRC PLUGINHOOK_TSM_PRE_FUNC(rpmts ts)
{
- if (!root) {
- rpmlog(RPMLOG_DEBUG, "Policy is missing. Ending transaction\n");
+ if (!dsp) {
+ rpmlog(RPMLOG_ERR, "Device security policy is missing. Unable to proceed\n");
return RPMRC_FAIL;
}
return RPMRC_OK;
}
-static int findSWSourceBySignature(sw_source_x *sw_source, void *param, void* param2)
-{
- origin_x *origin;
- keyinfo_x *keyinfo;
- pgpDigParams sig = (pgpDigParams)param;
- DIGEST_CTX ctx = (DIGEST_CTX)param2;
- pgpDigParams key = NULL;
-
- for (origin = sw_source->origins; origin; origin = origin->prev) {
- for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
- if (pgpPrtParams(keyinfo->keydata, keyinfo->keylen, PGPTAG_PUBLIC_KEY, &key)) {
- rpmlog(RPMLOG_ERR, "invalid sw source key\n");
- return -1;
- }
- if (pgpVerifySignature(key, sig, ctx) == RPMRC_OK) {
- return 0;
- }
- }
- }
- return 1;
-}
-
rpmRC PLUGINHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig, DIGEST_CTX ctx, int rpmrc)
{
current = NULL;
-#if 0
- if (!root) {
- if (rpmrc == RPMRC_NOKEY) {
- rpmlog(RPMLOG_INFO, "package verified as root sw source\n");
- rootSWSource = 1; /* accept any signed package as root */
- return RPMRC_OK;
- }
- rpmlog(RPMLOG_ERR, "No device security policy, cannot verify signature\n");
- return rpmrc;
- }
-
- // make currently that even non-signed package with root policy will be treated as trusted
-
- if (!root) {
- rpmlog(RPMLOG_INFO, "package verified as root sw source\n");
- rootSWSource = 1; /* accept any signed package as root */
- return RPMRC_OK;
- }
-
- //------------------
-
-#endif
-
- if (!root) {
+ if (!dsp) {
rpmlog(RPMLOG_ERR, "No device policy found\n");
- rootSWSource = 1; /* accept any signed package as root */
return rpmrc;
}
@@ -383,15 +337,15 @@ rpmRC PLUGINHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig,
if (rpmrc) {
/* RPM failed to verify signature */
rpmlog(RPMLOG_ERR, "Invalid signature, cannot search sw source\n");
- return rpmrc;
+ goto exit;
}
if (sigtd->tag != RPMSIGTAG_RSA) {
/* Not RSA, revert to unknown sw source. */
- rpmlog(RPMLOG_DEBUG, "no RSA signature, cannot search sw source\n");
+ rpmlog(RPMLOG_DEBUG, "not an RSA signature, cannot search sw source\n");
goto exit;
}
- current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceBySignature, sig, ctx);
+ current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceBySignature, sig, ctx);
if (current)
rpmlog(RPMLOG_DEBUG, "signature matches sw source %s\n", current->name);
else
@@ -399,11 +353,11 @@ rpmRC PLUGINHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig,
exit:
if (!current) {
- current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"_default_", NULL);
+ current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"_default_", NULL);
if (current) {
rpmlog(RPMLOG_DEBUG, "using _default_ sw source\n");
} else { // for now in case default sw source isn't there yet, allow to think that it is coming from root
- current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"root", NULL);
+ current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"root", NULL);
if (current)
rpmlog(RPMLOG_DEBUG, "using _root_ sw source now for testing\n");
}
@@ -412,85 +366,6 @@ rpmRC PLUGINHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig,
return rpmrc;
}
-static packagecontext *msmNew(rpmte te)
-{
- Header h;
- struct rpmtd_s msm;
- int count;
- packagecontext *ctx = NULL;
- const char *sw_source = NULL;
-
- rpmtdReset(&msm);
-
- h = rpmteHeader(te);
- if (!h) return NULL;
-
- ctx = xcalloc(1, sizeof(*ctx));
- if (!ctx) {
- goto exit1;
- }
- ctx->te = te;
-
- if (!headerIsEntry(h, RPMTAG_SECMANIFEST)) {
- goto exit1;
- }
-
- if (!headerGet(h, RPMTAG_SECMANIFEST, &msm, HEADERGET_MINMEM)) {
- goto exit1;
- }
-
- count = rpmtdCount(&msm);
- if (count != 1) {
- goto exit2;
- }
-
- ctx->data = xstrdup(rpmtdNextString(&msm));
- rpmlog(RPMLOG_DEBUG, "%s manifest b64 data: %.40s...\n",
- rpmteN(ctx->te), ctx->data);
- exit2:
- rpmtdFreeData(&msm);
- exit1:
- if (rpmteType(ctx->te) == TR_ADDED) {
- /* Save sw_source name into database, we need it when package */
- /* is removed because signature verify is not called then. */
- if (current) sw_source = current->name;
- else if (rootSWSource) sw_source = rpmteN(ctx->te);
-
- if (!sw_source || !headerPutString(h, RPMTAG_SECSWSOURCE, sw_source)) {
- rpmlog(RPMLOG_ERR, "Failed to save sw source for %s, sw_source: %s\n",
- rpmteN(ctx->te), sw_source);
- msmFreePointer((void**)&ctx->data);
- msmFreePointer((void**)&ctx);
- }
- }
- headerFree(h);
-
- return ctx;
-}
-
-static packagecontext *msmAddTE(rpmte te)
-{
- packagecontext *ctx = msmNew(te);
- if (ctx) {
- /* add the new policy to the list */
- if (!contextsHead) {
- contextsHead = ctx;
- contextsTail = ctx;
- } else {
- if (rpmteType(te) == TR_ADDED) {
- /* add to the end of the list */
- contextsTail->next = ctx;
- contextsTail = ctx;
- } else {
- /* add to the beginning of the list */
- ctx->next = contextsHead;
- contextsHead = ctx;
- }
- }
- }
- return ctx;
-}
-
rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
{
packagecontext *ctx = NULL;
@@ -502,18 +377,18 @@ rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
package_created = 0;
- if (!root && !rootSWSource) {
- /* no sw source config, just exit */
- goto exit;
+ if (!dsp) {
+ rpmlog(RPMLOG_ERR, "Device security policy is missing. Unable to proceed\n");
+ return RPMRC_FAIL;
}
if (!current) {
/* this means that verify hook has not been called */
- current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)"_default_", NULL);
+ current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"_default_", NULL);
if (current) {
rpmlog(RPMLOG_DEBUG, "using _default_ sw source\n");
} else {
- rpmlog(RPMLOG_ERR, "Default source isn't availiable. Package source can't be determined. Abort installation\n");
+ rpmlog(RPMLOG_ERR, "Default source isn't avaliable. Package source can't be determined. Abort installation\n");
goto fail;
}
}
@@ -531,7 +406,7 @@ rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
if (h) {
const char *name = headerGetString(h, RPMTAG_SECSWSOURCE);
if (name) {
- current = msmSWSourceTreeTraversal(root->sw_sources, findSWSourceByName, (void *)name, NULL);
+ current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)name, NULL);
rpmlog(RPMLOG_DEBUG, "removing %s from sw source %s\n",
rpmteN(ctx->te), name);
}
@@ -590,11 +465,12 @@ rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
rpmlog(RPMLOG_DEBUG, "Installing the package\n");
package_x *package = NULL;
- if (rootSWSource) {
- /* this is the first package */
+ /*if (rootSWSource) {
+ // this is the first package that brings the policy
package = msmCreatePackage(mfx->name, mfx->sw_sources,
mfx->provides, NULL);
- } else if (mfx->sw_source) {
+ } else */
+ if (mfx->sw_source) {
/* all packages must have sw_source */
package = msmCreatePackage(mfx->name, mfx->sw_source,
mfx->provides, NULL);
@@ -628,15 +504,17 @@ rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
}
package_created = 1;
- if (rootSWSource) {
- /* current is root */
- root = ctx->mfx;
- }
+
+ /*if (rootSWSource) {
+ // current configuration becomes dsp
+ dsp = ctx->mfx;
+ } */
rpmlog(RPMLOG_DEBUG, "Starting the security setup...\n");
unsigned int smackLabel = 0;
- if (rootSWSource || ctx->mfx->sw_source) {
+ /*if (rootSWSource || ctx->mfx->sw_source) {*/
+ if (ctx->mfx->sw_source) {
if (ctx->mfx->sw_sources) {
smackLabel = 1; /* setting this one on since this manifest doesn't have any define/request section */
ret = msmSetupSWSources(ctx->smack_accesses, ctx->mfx, ts);
@@ -719,7 +597,7 @@ rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
rpmRC PLUGINHOOK_FSM_INIT_FUNC(const char* path, mode_t mode)
{
- //check if there any conflicts that prevent file being written to the disk
+ /* Check if there any conflicts that prevent file being written to the disk */
fileconflict *fc;
packagecontext *ctx = context;
@@ -735,8 +613,6 @@ rpmRC PLUGINHOOK_FSM_INIT_FUNC(const char* path, mode_t mode)
if (cleanedPath)
*cleanedPath = '\0';
- //rpmlog(RPMLOG_DEBUG, "dupapth: %s\n", dupPath);
-
HASH_FIND(hh, allfileconflicts, dupPath, strlen(dupPath), fc);
msmFreePointer((void**)&dupPath);
@@ -761,13 +637,16 @@ rpmRC PLUGINHOOK_FSM_INIT_FUNC(const char* path, mode_t mode)
rpmRC PLUGINHOOK_FSM_COMMIT_FUNC(const char* path, mode_t mode, int type)
{
+ /* Setup xattrs for the given path */
+
packagecontext *ctx = context;
+
+ rpmlog(RPMLOG_DEBUG, "Started with FSM_COMMIT_FUNC hook for file: %s\n", path);
+
if (!ctx) return RPMRC_FAIL;
if (!path) return RPMRC_FAIL;
- /* the type is ignored for now */
-
- rpmlog(RPMLOG_DEBUG, "Started with FSM_COMMIT_FUNC hook for file: %s\n", path);
+ /* the type option is ignored for now */
if (ctx->mfx) {
file_x *file = xcalloc(1, sizeof(*file));
@@ -818,10 +697,10 @@ rpmRC PLUGINHOOK_PSM_POST_FUNC(rpmte te, int rpmrc)
return RPMRC_FAIL;
}
- if (rootSWSource) {
- /* current is root */
- root = context->mfx;
- }
+ /* if (rootSWSource) {
+ // current configuration becomes dsp
+ dsp = context->mfx;
+ } */
if (rpmteType(ctx->te) == TR_REMOVED) {
if (ctx->mfx->sw_source) {
@@ -847,27 +726,16 @@ rpmRC PLUGINHOOK_TSM_POST_FUNC(rpmts ts, int rpmrc)
packagecontext *ctx = context;
msmFreeInternalHashes(); // free hash structures first
- if (root) {
- msmSaveDeviceSecPolicyXml(root, ts->rootDir);
- if (!rootSWSource) root = msmFreeManifestXml(root);
+ if (dsp) {
+ msmSaveDeviceSecPolicyXml(dsp, ts->rootDir);
+ /* if (!rootSWSource) dsp = msmFreeManifestXml(dsp); */
+ dsp = msmFreeManifestXml(dsp);
+
}
if (!ctx) return RPMRC_FAIL;
return RPMRC_OK;
}
-static packagecontext *msmFree(packagecontext *ctx)
-{
- while (ctx) {
- packagecontext *next = ctx->next;
- msmFreePointer((void**)&ctx->data);
- ctx->mfx = msmFreeManifestXml(ctx->mfx);
- if (ctx->smack_accesses) smack_accesses_free(ctx->smack_accesses);
- msmFreePointer((void**)&ctx);
- ctx = next;
- }
- return NULL;
-}
-
rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
{
@@ -891,11 +759,3 @@ rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
return RPMRC_OK;
}
-
-void msmFreePointer(void** ptr)
-{
- if (*ptr)
- free(*ptr);
- *ptr = NULL;
- return;
-}
diff --git a/plugins/msm.h b/plugins/msm.h
index 1a4853a2a..f1bdcc819 100644
--- a/plugins/msm.h
+++ b/plugins/msm.h
@@ -29,15 +29,12 @@
#ifndef MSM_H
#define MSM_H
-#define IMA "security.ima"
-#define SMACK64TRANSMUTE "security.SMACK64TRANSMUTE"
#define SMACK64 "security.SMACK64"
#define SMACK64EXEC "security.SMACK64EXEC"
+#define SMACK64TRANSMUTE "security.SMACK64TRANSMUTE"
#define SMACK_RULES_PATH "/etc/smack/accesses.d/"
-#define SMACK_RULES_PATH_BEG "/etc/smack/"
#define DEVICE_SECURITY_POLICY "/etc/device-sec-policy"
-#define SMACK_LOAD_PATH "/sys/fs/smackfs/load"
#define SMACK_ISOLATED_LABEL "Isolated"
@@ -312,6 +309,14 @@ void msmFreePointer(void **ptr);
manifest_x *msmProcessManifestXml(const char *buffer, int size, sw_source_x *current, const char *packagename);
/** \ingroup msm
+ * Loads device security policy.
+ * @param rootDir --root rpm optional prefix
+ * @param dsp pointer to the loaded policy
+ * @return RPMRC_OK or RPMRC_FAIL
+ */
+rpmRC msmLoadDeviceSecurityPolicy(const char* rootDir, manifest_x **dsp);
+
+/** \ingroup msm
* Process device security policy file.
* @param filename file name
* @return pointer to structure on success
@@ -319,6 +324,13 @@ manifest_x *msmProcessManifestXml(const char *buffer, int size, sw_source_x *cur
manifest_x *msmProcessDevSecPolicyXml(const char *filename);
/** \ingroup msm
+ * Creates a directory for the smack rules.
+ * @param rootDir --root rpm optional prefix
+ * @return RPMRC_OK or RPMRC_FAIL
+ */
+rpmRC msmSetupSmackRulesDir(const char* rootDir);
+
+/** \ingroup msm
* Free all structures reserved during manifest processing.
* @param mfx pointer to structure
*/
@@ -457,4 +469,30 @@ sw_source_x *msmSWSourceTreeTraversal(sw_source_x *sw_sources, int (func)(sw_sou
* Free internal hashes.
*/
void msmFreeInternalHashes(void);
+
+/** \ingroup msm
+ * Finds a sw source by key info.
+ * @param sw_source sw source
+ * @param param searched param
+ * @return 0 if found
+ */
+int msmFindSWSourceByKey(sw_source_x *sw_source, void *param);
+
+/** \ingroup msm
+ * Finds a sw source by sw source name.
+ * @param sw_source sw source
+ * @param param searched param
+ * @return 0 if found
+ */
+int msmFindSWSourceByName(sw_source_x *sw_source, void *param);
+
+/** \ingroup msm
+ * Finds a sw source by sw source signature.
+ * @param sw_source sw source
+ * @param param searched param
+ * @param param2 searched param2
+ * @return 0 if found
+ */
+int msmFindSWSourceBySignature(sw_source_x *sw_source, void *param, void* param2);
+
#endif
diff --git a/plugins/msmconfig.c b/plugins/msmconfig.c
index 81462fec4..1551c6e5f 100644
--- a/plugins/msmconfig.c
+++ b/plugins/msmconfig.c
@@ -30,6 +30,8 @@
#include "rpmio/rpmbase64.h"
#include "rpmio/rpmlog.h"
+#include "rpm/rpmfileutil.h"
+#include <rpm/rpmmacro.h>
#include "msm.h"
@@ -273,3 +275,140 @@ rpmRC msmSaveDeviceSecPolicyXml(manifest_x *mfx, const char *rootDir)
return rc;
}
+/**
+ * Copies a file
+ * @param old_filename old file name
+ * @param new_filename new file name
+ * @return result of copy or -1 on failure
+ */
+static int copyFile(char *old_filename, char *new_filename)
+{
+ FD_t ptr_old, ptr_new;
+ int res;
+
+ ptr_old = Fopen(old_filename, "r.fdio");
+ ptr_new = Fopen(new_filename, "w.fdio");
+
+ if ((ptr_old == NULL) || (Ferror(ptr_old))) {
+ return -1;
+ }
+
+ if ((ptr_new == NULL) || (Ferror(ptr_new))) {
+ Fclose(ptr_old);
+ return -1;
+ }
+
+ res = ufdCopy(ptr_old, ptr_new);
+
+ Fclose(ptr_new);
+ Fclose(ptr_old);
+ return res;
+}
+
+/**
+ * Loads device security policy.
+ * @param rootDir --root rpm optional prefix
+ * @param dsp pointer to the loaded policy
+ * @return RPMRC_OK or RPMRC_FAIL
+ */
+rpmRC msmLoadDeviceSecurityPolicy(const char* rootDir, manifest_x **dsp)
+{
+ char *dspFullPath = NULL, *dspFullPathDir = NULL;
+ char *defaultdspPath = NULL;
+ struct stat buf;
+
+ dspFullPath = rpmGenPath(rootDir, (const char*)DEVICE_SECURITY_POLICY, NULL);
+ rpmlog(RPMLOG_DEBUG, "Device Security policy full path %s\n", dspFullPath);
+ if (!dspFullPath) {
+ rpmlog(RPMLOG_ERR, "Building a full path failed for the device security policy\n");
+ goto ldsp_error;
+ }
+
+ if (stat(dspFullPath, &buf) != 0) { // the policy file is missing
+ if (rootDir) { // we are running with --root option and policy is missing, need to copy it for now
+ // first create prefix for it
+ char *sysconfdir = rpmExpand((const char*)"%{?_sysconfdir}", NULL);
+ if (!sysconfdir || !strcmp(sysconfdir, "")) {
+ rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
+ goto ldsp_error;
+ }
+
+ dspFullPathDir = rpmGenPath(rootDir, sysconfdir, NULL);
+ rpmlog(RPMLOG_DEBUG, "Device Security policy full path dir %s\n", dspFullPathDir);
+ msmFreePointer((void**)&sysconfdir);
+ if (!dspFullPathDir) {
+ rpmlog(RPMLOG_ERR, "Building a full path for the device security policy dir failed\n");
+ goto ldsp_error;
+ }
+ if (rpmioMkpath(dspFullPathDir, 0755, getuid(), getgid()) != 0) {
+ rpmlog(RPMLOG_ERR, "Failed to create a path for the device security policy dir\n");
+ goto ldsp_error;
+ }
+ defaultdspPath = rpmExpand((const char*)"%{?__transaction_msm_default_policy}", NULL);
+ if (!defaultdspPath || !strcmp(defaultdspPath, "")) {
+ rpmlog(RPMLOG_ERR, "Failed to expand transaction_msm_default_policy macro\n");
+ goto ldsp_error;
+ }
+ if(copyFile(defaultdspPath, dspFullPath) == -1) {
+ /* Do not allow plug-in to proceed without security policy existing */
+ rpmlog(RPMLOG_ERR, "Failed to copy the device security policy to the chroot environment\n");
+ goto ldsp_error;
+ }
+ } else {
+ /* Do not allow plug-in to proceed without security policy existing */
+ rpmlog(RPMLOG_ERR, "Policy file is missing at %s\n",
+ dspFullPath);
+ goto ldsp_error;
+ }
+ }
+
+ rpmlog(RPMLOG_DEBUG, "reading the device security policy from %s\n", dspFullPath);
+ *dsp = msmProcessDevSecPolicyXml(dspFullPath);
+
+ if (!*dsp) {
+ rpmlog(RPMLOG_ERR, "Failed to process sw sources from %s\n", dspFullPath);
+ goto ldsp_error;
+ } else {
+ if (msmSetupSWSources(NULL, *dsp, NULL)) {
+ rpmlog(RPMLOG_ERR, "Failed to setup the device security policy from %s\n", dspFullPath);
+ goto ldsp_error;
+ }
+ }
+
+ return RPMRC_OK;
+
+ldsp_error:
+ msmFreePointer((void**)&dspFullPath);
+ msmFreePointer((void**)&dspFullPathDir);
+ msmFreePointer((void**)&defaultdspPath);
+ return RPMRC_FAIL;
+}
+
+/**
+ * Creates a directory for the smack rules.
+ * @param rootDir --root rpm optional prefix
+ * @return RPMRC_OK or RPMRC_FAIL
+ */
+rpmRC msmSetupSmackRulesDir(const char* rootDir)
+{
+ char *smackRulesFullPath = NULL;
+ rpmRC res = RPMRC_FAIL;
+
+ smackRulesFullPath = rpmGenPath(rootDir, SMACK_RULES_PATH, NULL);
+ rpmlog(RPMLOG_DEBUG, "smackRulesFullPath for SMACK_RULES_PATH %s\n", smackRulesFullPath);
+
+ if (!smackRulesFullPath){
+ rpmlog(RPMLOG_ERR, "Building a full path failed for smack rules path\n");
+ return res;
+ }
+
+ if (rpmioMkpath(smackRulesFullPath, 0744, getuid(), getgid()) != 0) {
+ rpmlog(RPMLOG_ERR, "Failed to create a directory for smack rules\n");
+ } else {
+ res = RPMRC_OK;
+ }
+
+ msmFreePointer((void**)&smackRulesFullPath);
+ return res;
+}
+
diff --git a/plugins/msmmanifest.c b/plugins/msmmanifest.c
index c7139237e..d1f211bce 100644
--- a/plugins/msmmanifest.c
+++ b/plugins/msmmanifest.c
@@ -822,7 +822,7 @@ static int msmProcessDefine(xmlTextReaderPtr reader, define_x *define, manifest_
return ret;
}
-static int findSWSourceByKey(sw_source_x *sw_source, void *param)
+int msmFindSWSourceByKey(sw_source_x *sw_source, void *param)
{
origin_x *origin;
keyinfo_x *keyinfo;
@@ -839,6 +839,34 @@ static int findSWSourceByKey(sw_source_x *sw_source, void *param)
return 1;
}
+int msmFindSWSourceByName(sw_source_x *sw_source, void *param)
+{
+ const char *name = (const char *)param;
+ return strcmp(sw_source->name, name);
+}
+
+int msmFindSWSourceBySignature(sw_source_x *sw_source, void *param, void* param2)
+{
+ origin_x *origin;
+ keyinfo_x *keyinfo;
+ pgpDigParams sig = (pgpDigParams)param;
+ DIGEST_CTX ctx = (DIGEST_CTX)param2;
+ pgpDigParams key = NULL;
+
+ for (origin = sw_source->origins; origin; origin = origin->prev) {
+ for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
+ if (pgpPrtParams(keyinfo->keydata, keyinfo->keylen, PGPTAG_PUBLIC_KEY, &key)) {
+ rpmlog(RPMLOG_ERR, "invalid sw source key\n");
+ return -1;
+ }
+ if (pgpVerifySignature(key, sig, ctx) == RPMRC_OK) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
static int msmProcessKeyinfo(xmlTextReaderPtr reader, origin_x *origin, sw_source_x *parent)
{
const xmlChar *keydata;
@@ -858,7 +886,7 @@ static int msmProcessKeyinfo(xmlTextReaderPtr reader, origin_x *origin, sw_sourc
}
if (!ret) {
// check that keys aren't matching
- sw_source_x *old = msmSWSourceTreeTraversal(parent, findSWSourceByKey, (void *)keyinfo, NULL);
+ sw_source_x *old = msmSWSourceTreeTraversal(parent, msmFindSWSourceByKey, (void *)keyinfo, NULL);
if (old) {
rpmlog(RPMLOG_ERR, "SW source with this key has already been installed\n");
return -1;
@@ -976,12 +1004,6 @@ static int msmProcessAllow(xmlTextReaderPtr reader, sw_source_x *sw_source)
return ret;
}
-static int msmFindSWSourceByName(sw_source_x *sw_source, void *param)
-{
- const char *name = (const char *)param;
- return strcmp(sw_source->name, name);
-}
-
static int msmProcessSWSource(xmlTextReaderPtr reader, sw_source_x *sw_source, const char *parentkey, manifest_x *mfx)
{
const xmlChar *name, *node, *rank, *rankkey;
diff --git a/plugins/msmxattr.c b/plugins/msmxattr.c
index eaf064dd1..0661ae365 100644
--- a/plugins/msmxattr.c
+++ b/plugins/msmxattr.c
@@ -1194,8 +1194,8 @@ int msmSetFileXAttributes(manifest_x *mfx, const char* filepath, magic_t cookie)
}
len = strlen(filesystem->path);
rpmlog(RPMLOG_DEBUG, "filepath: %s, filesystem->type %s\n", filepath, filesystem->type);
- rpmlog(RPMLOG_DEBUG, "filesystem->path: %s, length %d, match %d\n", filesystem->path, len, match);
- rpmlog(RPMLOG_DEBUG, "filesystem->path + len - 1: %s\n", filesystem->path + len - 1);
+ //rpmlog(RPMLOG_DEBUG, "filesystem->path: %s, length %d, match %d\n", filesystem->path, len, match);
+ //rpmlog(RPMLOG_DEBUG, "filesystem->path + len - 1: %s\n", filesystem->path + len - 1);
if (len > match) {
if ((!strncmp(filepath, filesystem->path, len)) && (filesystem->type)) {
/* partial match and the directory marked as transmutable*/