Security plugin: support for --root option
authorElena Reshetova <elena.reshetova@intel.com>
Fri, 26 Jul 2013 07:09:13 +0000 (10:09 +0300)
committerAnas Nashif <anas.nashif@intel.com>
Mon, 5 Aug 2013 16:53:41 +0000 (12:53 -0400)
 -adding macros to configure location of default policy
 -adding a default security policy to rpm-plugins dir
 -adding copying of policy file to chroot dir when rpm is run with --root param
 -moving policy saving to post_tsm hook

macros.in
packaging/rpm.spec
plugins/msm-plugin.c
plugins/msm.h
plugins/msmconfig.c

index 34edf2b4019122708b2efa5954925a3d039f5921..e285ce16a840c8defbd0a77f1dda8715374a76f9 100644 (file)
--- a/macros.in
+++ b/macros.in
@@ -1082,9 +1082,9 @@ PreReq: python >= %minver, python < %maxver
 #------------------------------------------------------------------------------
 # transaction specific macros
 %__transaction_plugins     msm
-%__plugindir           %{_libdir}/rpm-plugins
-%__transaction_msm       %{__plugindir}/msm.so
-
+%__plugindir                           %{_libdir}/rpm-plugins
+%__transaction_msm                     %{__plugindir}/msm.so
+%__transaction_msm_default_policy      %{_libdir}/rpm-plugins/msm-device-sec-policy
 #------------------------------------------------------------------------------
 # Macros for further automated spec %setup and patch application
 
index e4d1a1602d211f96341aa45808c03fbb5818417a..72010bd8aee96fdc025f7c6a42e628cc84caf8e7 100644 (file)
@@ -162,7 +162,8 @@ cp -a tizen_macros %{buildroot}/usr/lib/rpm
 mkdir -p %{buildroot}/usr/lib/rpm/tizen
 install -m 755 %{SOURCE13} %{buildroot}/usr/lib/rpm/tizen
 install -m 755 %{SOURCE23} %{buildroot}/usr/lib/rpm
-install -m 644 %{SOURCE22} ${RPM_BUILD_ROOT}%{_sysconfdir}/device-sec-policy
+install -m 644 %{SOURCE22} %{buildroot}%{_sysconfdir}/device-sec-policy
+install -m 644 %{SOURCE22} %{buildroot}%{_libdir}/rpm-plugins/msm-device-sec-policy
 ln -s ../tizen_macros %{buildroot}/usr/lib/rpm/tizen/macros
 for d in BUILD RPMS SOURCES SPECS SRPMS BUILDROOT ; do
   mkdir -p %{buildroot}/usr/src/packages/$d
@@ -304,5 +305,6 @@ rm -f var/lib/rpm/Filemd5s var/lib/rpm/Filedigests var/lib/rpm/Requireversion va
 %manifest %{name}.manifest
 %defattr(-,root,root)
 %{_libdir}/rpm-plugins/msm.so
+%{_libdir}/rpm-plugins/msm-device-sec-policy
 %config(noreplace) %{_sysconfdir}/device-sec-policy
 
index 4cb5ec3b0c856487207357649285d29a11d07993..663e119372ccd52843071672bfe9fe8bbe9ed22a 100644 (file)
@@ -90,21 +90,39 @@ static int SmackEnabled = 0;
 static magic_t cookie = NULL;
 static int package_created = 0;
 
+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;
+}
+
 rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
 {
     ts = _ts;
-    int res = 0;
     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");
-        return RPMRC_FAIL;
-    }
 
 #ifndef ENABLE_DCHECKS
     rpmlog(RPMLOG_DEBUG, "ENABLE_DCHECKS is undefined!\n");
@@ -112,40 +130,81 @@ rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
     rpmlog(RPMLOG_DEBUG, "ENABLE_DCHECKS is defined!\n");
 #endif
 
+    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 (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;
+        }
+    }
+
     rpmlog(RPMLOG_DEBUG, "reading device security policy from %s\n", fullPath);
     root = msmProcessDevSecPolicyXml(fullPath);
 
-    if (root) {
+    if (!root) {
+        rpmlog(RPMLOG_ERR, "Failed process sw sources from %s\n", fullPath);
+        goto plugin_error;
+    } else {
         if (msmSetupSWSources(NULL, root, NULL)) {
-           rpmlog(RPMLOG_ERR, "Failed to setup device security policy from %s\n", 
-                  fullPath);
-            return RPMRC_FAIL;
+            rpmlog(RPMLOG_ERR, "Failed to setup security policy from %s\n",fullPath);
+            goto plugin_error;
         }
-    } else {
-        /* Do not allow plug-in to proceed without security policy existing */
-        rpmlog(RPMLOG_ERR, "Failed to process sw sources from %s\n", 
-              fullPath);
-        return RPMRC_FAIL;
     }
 
     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");
-        return RPMRC_FAIL;
+        goto plugin_error;
     }
 
     /* check its own security context and store it for the case when packages without manifest will be installed */
-    struct stat buf;
-
     if (stat(fullPath, &buf) == 0) {
-        res = smack_new_label_from_self(&ownSmackLabel);
+        int res = smack_new_label_from_self(&ownSmackLabel);
         SmackEnabled = 1;
         if (res != 0) {
             rpmlog(RPMLOG_ERR, "Failed to obtain rpm security context\n");
-            return RPMRC_FAIL;
+            goto plugin_error;
         }
     } else {
         rpmlog(RPMLOG_INFO, "Smackfs isn't mounted at %s. Going to the image build mode. \n", fullPath);
@@ -160,7 +219,7 @@ rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
     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");
-       return RPMRC_FAIL;
+       goto plugin_error;
     }
 
     if (stat(fullPath, &buf) != 0) {
@@ -169,12 +228,12 @@ rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
         if (stat(fullPath1, &buf) != 0) {
             if (mkdir(fullPath1, mode) != 0) {
                 rpmlog(RPMLOG_ERR, "Failed to create a sub-directory for smack rules\n");
-                return RPMRC_FAIL;
+                goto plugin_error;
             }    
         }
         if (mkdir(fullPath, mode) != 0){
             rpmlog(RPMLOG_ERR, "Failed to create a directory for smack rules\n");
-            return RPMRC_FAIL;
+            goto plugin_error;
         } 
     }
 
@@ -195,6 +254,12 @@ 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)
@@ -795,6 +860,12 @@ rpmRC PLUGINHOOK_PSM_POST_FUNC(rpmte te, int rpmrc)
 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 (!ctx) return RPMRC_FAIL;
     return RPMRC_OK;
 }
@@ -815,13 +886,6 @@ static packagecontext *msmFree(packagecontext *ctx)
 rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
 {
 
-    msmFreeInternalHashes(); // free hash structures first
-
-    if (root) {
-        msmSaveDeviceSecPolicyXml(root);
-        if (!rootSWSource) root = msmFreeManifestXml(root);
-    }
-
     ts = NULL;
 
     contextsHead = contextsTail = msmFree(contextsHead);
index 4a0423d9a3c33307a5a07d68a84272779020e3fb..bbe09275d53d0411e2aea3302f512cbfa3e2283d 100644 (file)
@@ -438,9 +438,10 @@ int strwcmp(const char *s1, const char *s2);
 /** \ingroup msm
  * Saves configuration into /etc/dev-sec-policy.
  * @param mfx          data to serialize
+ * @param rooDir       ts->rootDir prefix
  * @return             RPMRC_OK or RPMRC_FAIL
  */
-rpmRC msmSaveDeviceSecPolicyXml(manifest_x *root);
+rpmRC msmSaveDeviceSecPolicyXml(manifest_x *root, const char *rootDir);
 
 /** \ingroup msm
  * Depth first tree traversal for sw source tree.
index bc7a3d2ece858e5828241916ee36f552814ffd33..81462fec43b4587c16c60251e6fc91093f4fad7d 100644 (file)
@@ -232,10 +232,18 @@ static void msmHandleSWSource(xmlNode *parent, sw_source_x *sw_source)
  * @param mfx          data to serialize
  * @return             RPMRC_OK or RPMRC_FAIL
  */
-rpmRC msmSaveDeviceSecPolicyXml(manifest_x *mfx)
+rpmRC msmSaveDeviceSecPolicyXml(manifest_x *mfx, const char *rootDir)
 {    
     FILE *outFile;
-    rpmRC rc = RPMRC_OK;    
+    rpmRC rc = RPMRC_OK;
+    char *fullPath = NULL;
+
+    fullPath = rpmGenPath(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");
+        return RPMRC_FAIL;
+    }
 
     /* if data doesn't have sw_source information, no need to do anything */    
     if (mfx && mfx->sw_sources) {    
@@ -247,19 +255,21 @@ rpmRC msmSaveDeviceSecPolicyXml(manifest_x *mfx)
        LISTHEAD(mfx->sw_sources, sw_source);   
         msmHandleSWSource(rootnode, sw_source);
 
-        outFile = fopen(DEVICE_SECURITY_POLICY, "w");
+        outFile = fopen(fullPath, "w");
         if (outFile) {
             xmlElemDump(outFile, doc, rootnode);
             fclose(outFile);
         } else {
-            rpmlog(RPMLOG_ERR, "Unable to write device security policy%s\n", 
-                  DEVICE_SECURITY_POLICY);
+            rpmlog(RPMLOG_ERR, "Unable to write device security policy to %s\n",
+                   fullPath);
+            msmFreePointer((void**)&fullPath);
             rc = RPMRC_FAIL;
         }
         xmlFreeDoc(doc);
         xmlCleanupParser();
     }
 
+    msmFreePointer((void**)&fullPath);
     return rc;
 }