Implement a mechanism for permissible file repair
authorFilip Skrzeczkowski <f.skrzeczkow@samsung.com>
Thu, 28 Sep 2023 11:19:50 +0000 (13:19 +0200)
committerTomasz Swierczek <t.swierczek@samsung.com>
Wed, 29 Nov 2023 10:07:29 +0000 (11:07 +0100)
Permissible files that have been marked as invalid due to their hash
not matching can now be repaired by fetching the relevant data directly
form PrivilegeDb. This works for both the service and the client library.
As the client lacks the privileges to do it on their own, in that case
a request is sent to the Security Manager daemon.

Change-Id: I43fee3d39c015a7fbba0e674c29c904ac26e91bf

src/client/client-label-monitor.cpp
src/common/include/permissible-set.h
src/common/include/protocols.h
src/common/include/service_impl.h
src/common/permissible-set.cpp
src/common/protocols.cpp
src/common/service_impl.cpp
src/server/service/include/service.h
src/server/service/service.cpp

index 195837617549bb739cd50e17caa7eca70b717d62..7050cf2cecb6e3b0678cc601f739c6037c8491f2 100644 (file)
@@ -44,6 +44,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <client-request.h>
 #include <config.h>
 #include <dpl/log/log.h>
 #include <dpl/errno_string.h>
@@ -51,6 +52,7 @@
 #include <permissible-set.h>
 #include <protocols.h>
 #include <smack-labels.h>
+#include <tzplatform-config.h>
 #include <utils.h>
 
 struct app_labels_monitor {
@@ -58,24 +60,93 @@ struct app_labels_monitor {
     int global_labels_file_watch;
     int user_labels_file_watch;
     bool fresh;
+    uid_t uid;
     std::string user_label_file_path;
     std::string global_label_file_path;
     app_labels_monitor() : inotify(-1), global_labels_file_watch(-1), user_labels_file_watch(-1),
-                           fresh(true) {}
+                           fresh(true), uid(-1) {}
 };
 
-static lib_retcode apply_relabel_list(const std::string &global_label_file,
-        const std::string &user_label_file)
+static lib_retcode inotify_add_watch_full(int fd, const char* pathname, uint32_t mask, int *wd)
+{
+    int inotify_fd = inotify_add_watch(fd, pathname, mask);
+    if (inotify_fd == -1) {
+        LogErrno("Inotify watch on file " << pathname);
+        return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
+    }
+    *wd = inotify_fd;
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+static lib_retcode monitor_repair_permissible_file(uid_t uid, const std::string &label_file_path, app_install_type install_type)
+{
+    LogWarning("Permissible file may be corrupted, sending request to repair: " << label_file_path);
+
+    ClientRequest request(SecurityModuleCall::REPAIR_PERMISSIBLE_FILE);
+    if (request.send(uid, install_type).failed()) {
+        return SECURITY_MANAGER_ERROR_SOCKET;
+    }
+    if (request.getStatus() != SECURITY_MANAGER_SUCCESS) {
+        return SECURITY_MANAGER_ERROR_FILE_INTEGRITY;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+static lib_retcode initialize_inotify(app_labels_monitor *monitor)
+{
+    lib_retcode ret_lib;
+    int ret = inotify_init();
+    if (ret == -1) {
+        LogErrno("Inotify init");
+        return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
+    }
+    monitor->inotify = ret;
+    ret_lib = inotify_add_watch_full(monitor->inotify, monitor->global_label_file_path.c_str(),
+            IN_CLOSE_WRITE | IN_DELETE_SELF, &(monitor->global_labels_file_watch));
+    if (ret_lib != SECURITY_MANAGER_SUCCESS) {
+        security_manager_app_labels_monitor_finish(monitor);
+        return ret_lib;
+    }
+    ret_lib = inotify_add_watch_full(monitor->inotify, monitor->user_label_file_path.c_str(),
+            IN_CLOSE_WRITE | IN_DELETE_SELF, &(monitor->user_labels_file_watch));
+    if (ret_lib != SECURITY_MANAGER_SUCCESS) {
+        security_manager_app_labels_monitor_finish(monitor);
+        return ret_lib;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+static void readPermissibleFile(std::vector<std::string> &appLabels, const std::string &filePath, app_install_type installType, uid_t uid)
+{
+    try {
+        PermissibleSet::readLabelsFromPermissibleFile(filePath, appLabels);
+    } catch(PermissibleSet::PermissibleSetException::FileIntegrityError &e) {
+        lib_retcode ret = monitor_repair_permissible_file(uid, filePath, installType);
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+            LogError("Repair failed: " << ret);
+            throw;
+        }
+        PermissibleSet::readLabelsFromPermissibleFile(filePath, appLabels);
+    }
+}
+
+static lib_retcode apply_relabel_list(app_labels_monitor *monitor)
 {
     std::vector<std::string> appLabels;
 
     try {
-        PermissibleSet::readLabelsFromPermissibleFile(global_label_file, appLabels);
-        PermissibleSet::readLabelsFromPermissibleFile(user_label_file, appLabels);
-        std::vector<const char*> temp;
+        readPermissibleFile(appLabels, monitor->global_label_file_path,
+            SM_APP_INSTALL_GLOBAL, TizenPlatformConfig::getUid(TZ_SYS_GLOBALAPP_USER));
+        readPermissibleFile(appLabels, monitor->user_label_file_path,
+            SM_APP_INSTALL_LOCAL, monitor->uid);
+
+        std::vector<const char *> temp;
 
         std::transform(appLabels.begin(), appLabels.end(), std::back_inserter(temp),
-                [] (std::string &label) {return label.c_str();});
+                        [](std::string &label)
+                        { return label.c_str(); });
 
         if (smack_set_relabel_self(temp.data(), temp.size()) != 0) {
             LogError("smack_set_relabel_self failed");
@@ -94,17 +165,6 @@ static lib_retcode apply_relabel_list(const std::string &global_label_file,
     return SECURITY_MANAGER_SUCCESS;
 }
 
-static lib_retcode inotify_add_watch_full(int fd, const char* pathname, uint32_t mask, int *wd)
-{
-    int inotify_fd = inotify_add_watch(fd, pathname, mask);
-    if (inotify_fd == -1) {
-        LogErrno("Inotify watch on file " << pathname);
-        return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
-    }
-    *wd = inotify_fd;
-    return SECURITY_MANAGER_SUCCESS;
-}
-
 SECURITY_MANAGER_API
 int security_manager_app_labels_monitor_init(app_labels_monitor **monitor)
 {
@@ -114,8 +174,6 @@ int security_manager_app_labels_monitor_init(app_labels_monitor **monitor)
             LogWarning("Error input param \"monitor\"");
             return SECURITY_MANAGER_ERROR_INPUT_PARAM;
         }
-        int ret;
-        lib_retcode ret_lib;
 
         *monitor = nullptr;
 
@@ -131,25 +189,15 @@ int security_manager_app_labels_monitor_init(app_labels_monitor **monitor)
         const std::string userFile =
             PermissibleSet::getPermissibleFileLocation(uid, SM_APP_INSTALL_LOCAL);
 
-
-        ret = inotify_init();
-        if (ret == -1) {
-            LogErrno("Inotify init");
-            return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
-        }
-        monitorPtr.get()->inotify = ret;
-        ret_lib = inotify_add_watch_full(monitorPtr->inotify, globalFile.c_str(),
-                IN_CLOSE_WRITE, &(monitorPtr->global_labels_file_watch));
-        if (ret_lib != SECURITY_MANAGER_SUCCESS) {
-            return ret_lib;
-        }
-        ret_lib = inotify_add_watch_full(monitorPtr->inotify, userFile.c_str(),
-                IN_CLOSE_WRITE, &(monitorPtr->user_labels_file_watch));
-        if (ret_lib != SECURITY_MANAGER_SUCCESS) {
-            return ret_lib;
-        }
+        monitorPtr->uid = uid;
         monitorPtr->user_label_file_path = userFile;
         monitorPtr->global_label_file_path = globalFile;
+
+        lib_retcode lib_ret = initialize_inotify(monitorPtr.get());
+        if (lib_ret != SECURITY_MANAGER_SUCCESS) {
+            LogErrno("Error during initializing inotify");
+            return lib_ret;
+        }
         *monitor = monitorPtr.release();
         return SECURITY_MANAGER_SUCCESS;
     });
@@ -171,14 +219,17 @@ void security_manager_app_labels_monitor_finish(app_labels_monitor *monitor)
                 if (ret == -1) {
                     LogErrno("Inotify watch removal on file " << APPS_LABELS_FILE);
                 }
+                monitorPtr->global_labels_file_watch = -1;
             }
             if (monitorPtr->user_labels_file_watch != -1) {
                 int ret = inotify_rm_watch(monitorPtr->inotify, monitorPtr->user_labels_file_watch);
                 if (ret == -1) {
                     LogErrno("Inotify watch removal on file " << monitor->user_label_file_path);
                 }
+                monitorPtr->user_labels_file_watch = -1;
             }
             close(monitorPtr->inotify);
+            monitorPtr->inotify = -1;
         }
         return 0;
     });
@@ -229,8 +280,7 @@ int security_manager_app_labels_monitor_process(app_labels_monitor *monitor)
 
         if (monitor->fresh) {
             monitor->fresh = false;
-            return apply_relabel_list(monitor->global_label_file_path,
-                   monitor->user_label_file_path);
+            return apply_relabel_list(monitor);
         }
 
         int avail;
@@ -260,12 +310,34 @@ int security_manager_app_labels_monitor_process(app_labels_monitor *monitor)
                 ((event.wd == monitor->global_labels_file_watch) ||
                  (event.wd == monitor->user_labels_file_watch))
                ){
-                lib_retcode r = apply_relabel_list(monitor->global_label_file_path,
-                                                   monitor->user_label_file_path);
+                lib_retcode r = apply_relabel_list(monitor);
                 if (r != SECURITY_MANAGER_SUCCESS)
                     return r;
                 break;
             }
+            if ((event.mask & IN_DELETE_SELF) &&
+                ((event.wd == monitor->global_labels_file_watch) ||
+                 (event.wd == monitor->user_labels_file_watch))
+               ){
+                if (event.wd == monitor->global_labels_file_watch) {
+                    lib_retcode r = inotify_add_watch_full(monitor->inotify, monitor->global_label_file_path.c_str(),
+                                    IN_CLOSE_WRITE | IN_DELETE_SELF, &(monitor->global_labels_file_watch));
+                    if (r != SECURITY_MANAGER_SUCCESS) {
+                        monitor->global_labels_file_watch = -1;
+                        return r;
+                    }
+
+                }
+                if (event.wd == monitor->user_labels_file_watch) {
+                    lib_retcode r = inotify_add_watch_full(monitor->inotify, monitor->user_label_file_path.c_str(),
+                                    IN_CLOSE_WRITE | IN_DELETE_SELF, &(monitor->user_labels_file_watch));
+                    if (r != SECURITY_MANAGER_SUCCESS) {
+                        monitor->user_labels_file_watch = -1;
+                        return r;
+                    }
+                }
+                break;
+            }
         }
         return SECURITY_MANAGER_SUCCESS;
     });
index aaa6d5b00374602a6a5bec06ab20e23f187be8dc..88588cb700299d11ebf60c76c361b4a809ff7a66 100644 (file)
@@ -34,6 +34,7 @@
 #include <vector>
 
 #include <dpl/exception.h>
+#include <privilege_db.h>
 #include <security-manager-types.h>
 
 namespace SecurityManager {
@@ -109,6 +110,16 @@ void updatePermissibleFile(uid_t uid, int installationType,
  */
 void readLabelsFromPermissibleFile(const std::string &nameFile, std::vector<std::string> &appLabels);
 
+/**
+ * Attempt to repair a possibly corrupted permissible file by reading directly from PrivilegeDb
+ * @throws FileOpenError
+ * @throws FileWriteError
+ *
+ * @param[in] uid user id
+ * @param[in] installationType type of installation (global or local)
+ */
+void repairPermissibleFile(uid_t uid, int installationType, PrivilegeDb &privilegeDb);
+
 void initializeUserPermissibleFile(uid_t uid);
 
 void removeUserPermissibleFile(uid_t uid);
index c4218330225eb05065f66dddb982467e15f6b47b..99604dc391b97a43c5db280fb113997ddcd3248a 100644 (file)
@@ -145,6 +145,7 @@ enum class SecurityModuleCall
     GET_APP_MANIFEST_POLICY,
     GET_PROCESS_LABEL,
     PREPARE_APP,
+    REPAIR_PERMISSIBLE_FILE,
     NOOP = 0x90,
 };
 
index 0cb1e7cbed7c9fad44d5e1977005bbc94a21e7dd..687f3cbbfdbc23924d902b3169ae3961d448b31f 100644 (file)
@@ -390,6 +390,16 @@ public:
             Smack::Label &label, std::string &pkgName, PrepareAppFlags &prepareAppFlags,
             std::vector<gid_t> &forbiddenGroups, std::vector<gid_t> &allowedGroups, std::vector<bool> &privPathsStatusVector);
 
+    /**
+     * Repair the possibly corrupted permissible file specified by input arguments
+     *
+     * @param[in] uid user id
+     * @param[in] installationType type of installation (global or local)
+     *
+     * @return API return code, as defined in protocols.h
+     */
+    int repairPermissibleFileForClient(uid_t uid, int installationType);
+
 private:
     int appInstallInitialChecks(const Credentials &creds,
                                 app_inst_req &req);
@@ -421,6 +431,10 @@ private:
 
     int appUninstallSmackRules(app_inst_req &req, UninstallHelper &uh);
 
+    void tryUpdatePermissibleFile(uid_t uid, int installationType,
+                                    const std::vector<std::string> &newLabels,
+                                    const std::vector<std::string> &oldLabels);
+
     bool authenticate(const Credentials &creds, const std::string &privilege);
 
     bool authCheck(const Credentials &creds,
index b8e826ef9845cb1366c00cdd95c83a0cd6c03480..8fb4a99005e7f91a0f7606a67fccd085d5d4774f 100644 (file)
 namespace SecurityManager {
 namespace PermissibleSet {
 
-static const char*  hashMarker = "-SHA-1";
-static const int    hashMarkerLength = strlen(hashMarker);
-static const int    hashLength = 40;
+static const char*   tempFileName = "temp";
+static const char*   hashMarker = "-SHA-1";
+static const int     hashMarkerLength = strlen(hashMarker);
+static constexpr int hashLength = 40;
+
+class ScopedTemporaryFile
+{
+public:
+    const std::string path = std::string(LOCAL_STATE_INSTALL_DIR) + "/" + tempFileName;
+
+    ~ScopedTemporaryFile()
+    {
+        if (unlink(path.c_str()) != 0 && errno != ENOENT)
+            LogErrno("remove temporary permissible file");
+    }
+};
 
 template <typename T>
 static inline int getFd(T &fstream)
@@ -116,6 +129,24 @@ std::string calculateHash(const std::string& content)
     return ss.str();
 }
 
+static void writeToPermissibleFile(const std::string &nameFile, std::ofstream &fstream, const std::stringstream &ss)
+{
+    auto content = ss.str();
+    auto hash = calculateHash(content);
+
+    fstream << hashMarker << " " << hash << '\n' << content;
+
+    if (fstream.bad()) {
+        LogAndThrowErrno(PermissibleSetException::FileWriteError, "write to file " << nameFile);
+    }
+    if (fstream.flush().fail()) {
+        LogAndThrowErrno(PermissibleSetException::FileWriteError, "fflush " << nameFile);
+    }
+    if (fsync(getFd(fstream)) == -1) {
+        LogAndThrowErrno(PermissibleSetException::FileWriteError, "fsync " << nameFile);
+    }
+}
+
 void verifyFileIntegrity(const std::string &nameFile, std::ifstream &fstream)
 {
     auto fileSize = std::filesystem::file_size(nameFile);
@@ -205,27 +236,15 @@ void updatePermissibleFile(uid_t uid, int installationType,
             labelsForUser.push_back(l);
     }
 
-    std::ofstream fstream;
-    openAndLockNameFile(nameFile, fstream);
-    markPermissibleFileValid(getFd(fstream), nameFile, false);
-
     std::stringstream ss;
     for (auto &label : labelsForUser) {
         ss << label << '\n';
     }
 
-    auto content = ss.str();
-    auto hash = calculateHash(content);
-
-    fstream << hashMarker << "\n" << hash << '\n' << content;
-
-    if (fstream.bad())
-            LogAndThrowErrno(PermissibleSetException::PermissibleSetException::FileWriteError,
-                    "write to file " << nameFile);
-    if (fstream.flush().fail())
-        LogAndThrowErrno(PermissibleSetException::FileWriteError, "fflush " << nameFile);
-    if (fsync(getFd(fstream)) == -1)
-        LogAndThrowErrno(PermissibleSetException::FileWriteError, "fsync " << nameFile);
+    std::ofstream fstream;
+    openAndLockNameFile(nameFile, fstream);
+    markPermissibleFileValid(getFd(fstream), nameFile, false);
+    writeToPermissibleFile(nameFile, fstream, ss);
     markPermissibleFileValid(getFd(fstream), nameFile, true);
 }
 
@@ -244,6 +263,34 @@ void readLabelsFromPermissibleFile(const std::string &nameFile, std::vector<std:
         LogAndThrowErrno(PermissibleSetException::FileReadError, "reading file " << nameFile);
 }
 
+void repairPermissibleFile(uid_t uid, int installationType, PrivilegeDb &privilegeDb)
+{
+    std::string nameFile = getPermissibleFileLocation(uid, installationType);
+    std::vector<std::string> appNames;
+    privilegeDb.GetUserApps(uid, appNames);
+
+    std::stringstream ss;
+    for (auto &appName : appNames) {
+        std::string pkgName;
+        privilegeDb.GetAppPkgName(appName, pkgName);
+        bool isPkgHybrid = privilegeDb.IsPackageHybrid(pkgName);
+
+        ss << SmackLabels::generateProcessLabel(appName, pkgName, isPkgHybrid) << '\n';
+    }
+    {
+        ScopedTemporaryFile temporaryFile;
+
+        std::ofstream fstream(temporaryFile.path);
+        if (!fstream.is_open())
+            LogAndThrowErrno(PermissibleSetException::FileOpenError, "open file " << nameFile);
+
+        writeToPermissibleFile(temporaryFile.path, fstream, ss);
+        if (rename(temporaryFile.path.c_str(), nameFile.c_str()) != 0)
+            ThrowErrno(PermissibleSetException::FileWriteError,
+            "move temporary file");
+    }
+}
+
 void initializeUserPermissibleFile(uid_t uid)
 {
     std::string nameFile = getPermissibleFileLocation(uid, SM_APP_INSTALL_LOCAL);
index b7a8e7779aa8a2920538f58ee669f94fbcd0d9f6..5aabc56c60d4d754b39be87141f57730397cd553 100644 (file)
@@ -60,6 +60,7 @@ const char * SecurityModuleCallToString(SecurityModuleCall call_num) {
         SM_CODE_DESCRIBE(SecurityModuleCall::GET_APP_MANIFEST_POLICY);
         SM_CODE_DESCRIBE(SecurityModuleCall::GET_PROCESS_LABEL);
         SM_CODE_DESCRIBE(SecurityModuleCall::PREPARE_APP);
+        SM_CODE_DESCRIBE(SecurityModuleCall::REPAIR_PERMISSIBLE_FILE);
         SM_CODE_DESCRIBE(SecurityModuleCall::NOOP);
         default: return "Code not defined";
     }
index 76a5602f79fe3bcf2e05a1a4f796a062d99d1376..fd612f4f2b4819309aa4bc061a09925795ae4b0e 100644 (file)
@@ -554,6 +554,19 @@ int ServiceImpl::appInstallSmackRules(app_inst_req &req, InstallHelper &ih)
     return SECURITY_MANAGER_SUCCESS;
 }
 
+void ServiceImpl::tryUpdatePermissibleFile(uid_t uid, int installationType,
+                                    const std::vector<std::string> &newLabels,
+                                    const std::vector<std::string> &oldLabels)
+{
+    try {
+        PermissibleSet::updatePermissibleFile(uid, installationType, newLabels, oldLabels);
+    } catch (const PermissibleSet::PermissibleSetException::FileIntegrityError &e) {
+        LogWarning("Permissible file may be corrupted, attempting repair: " << e.DumpToString());
+        PermissibleSet::repairPermissibleFile(uid, installationType, m_privilegeDb);
+        PermissibleSet::updatePermissibleFile(uid, installationType, newLabels, oldLabels);
+    }
+}
+
 int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &req)
 {
     int ret;
@@ -604,7 +617,7 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &req)
         getPkgLabels(req.pkgName, newLabels);
 
         // update permissible set
-        PermissibleSet::updatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
+        tryUpdatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
 
         // label paths
         ret = labelPaths(req.pkgPaths,
@@ -630,6 +643,9 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &req)
     } catch (const CynaraException::Base &e) {
         LogError("Error while setting Cynara rules for application: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const PermissibleSet::PermissibleSetException::FileIntegrityError &e) {
+        LogError("Error while updating permissible file - integrity error has been detected but it could not be fixed: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_FILE_INTEGRITY;
     } catch (const PermissibleSet::PermissibleSetException::Base &e) {
         LogError("Error while updating permissible file: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
@@ -718,7 +734,7 @@ int ServiceImpl::appUpdate(const Credentials &creds, app_inst_req &req)
         getPkgLabels(req.pkgName, newLabels);
 
         // update permissible set
-        PermissibleSet::updatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
+        tryUpdatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
 
         // label paths
         ret = labelPaths(req.pkgPaths,
@@ -744,6 +760,9 @@ int ServiceImpl::appUpdate(const Credentials &creds, app_inst_req &req)
     } catch (const CynaraException::Base &e) {
         LogError("Error while setting Cynara rules for application: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const PermissibleSet::PermissibleSetException::FileIntegrityError &e) {
+        LogError("Error while updating permissible file - integrity error has been detected but it could not be fixed: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_FILE_INTEGRITY;
     } catch (const PermissibleSet::PermissibleSetException::Base &e) {
         LogError("Error while updating permissible file: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
@@ -976,7 +995,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &req)
             getPkgLabels(req.pkgName, newLabels);
 
         // update permissible set
-        PermissibleSet::updatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
+        tryUpdatePermissibleFile(req.uid, req.installationType, newLabels, oldLabels);
 
         // remove and merge Smack rules for apps and pkg
         return appUninstallSmackRules(req, uh);
@@ -986,6 +1005,9 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &req)
     } catch (const PrivilegeDb::Exception::Base &e) {
         LogError("Error while removing application info from database: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const PermissibleSet::PermissibleSetException::FileIntegrityError &e) {
+        LogError("Error while updating permissible file - integrity error has been detected but it could not be fixed: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_FILE_INTEGRITY;
     } catch (const PermissibleSet::PermissibleSetException::Base &e) {
         LogError("Error while updating permissible file: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
@@ -2315,4 +2337,20 @@ int ServiceImpl::prepareApp(const Credentials &creds, const std::string &appName
     }
 }
 
+int ServiceImpl::repairPermissibleFileForClient(uid_t uid, int installationType)
+{
+    try {
+        PermissibleSet::repairPermissibleFile(uid, installationType, m_privilegeDb);
+    }
+    catch (PermissibleSet::PermissibleSetException::Base &e){
+        LogErrno("error while repairing the permissible file: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_FILE_INTEGRITY;
+    } catch (...){
+        LogErrno("other error during permissible file repair ");
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
 } /* namespace SecurityManager */
index e433f29194d64dd6fa0933d835ceaac76eb734e9..86bb407cf58421376659a4bf74b477d043ef98a4 100644 (file)
@@ -250,6 +250,13 @@ private:
      * @param creds  credentials of the requesting process
      */
     void prepareApp(MessageBuffer &buffer, const Credentials &creds);
+
+    /**
+     * Repair the requested Smack permissible file by fetching data from PrivilegeDb
+     *
+     * @param buffer Input/output message buffer
+     */
+    void processRepairPermissibleFile(MessageBuffer &buffer);
 };
 
 } // namespace SecurityManager
index c12dd6a72a68b9a8497095a437e050eb6aa06329..4545de2912ac7e3a674034ae55201b53126b0ead 100644 (file)
@@ -160,6 +160,9 @@ void Service::processEvent(Event &&msg)
             case SecurityModuleCall::PREPARE_APP:
                 prepareApp(msg.buffer, msg.creds);
                 break;
+            case SecurityModuleCall::REPAIR_PERMISSIBLE_FILE:
+                processRepairPermissibleFile(msg.buffer);
+                break;
             default:
                 LogError("Invalid call: " << call_type_int);
                 Throw(ServiceException::InvalidAction);
@@ -514,4 +517,17 @@ void Service::prepareApp(MessageBuffer &buffer, const Credentials &creds)
         Serialization::Serialize(buffer, forbiddenGroups, allowedGroups, privPathsStatusVector, label, pkgName, prepareAppFlags);
 }
 
+void Service::processRepairPermissibleFile(MessageBuffer &buffer)
+{
+    uid_t uid;
+    int installationType;
+
+    Deserialization::Deserialize(buffer, uid, installationType);
+
+    int ret = m_serviceImpl.repairPermissibleFileForClient(uid, installationType);
+
+    buffer.ModeStreaming();
+    Serialization::Serialize(buffer, ret);
+}
+
 } // namespace SecurityManager