From: Filip Skrzeczkowski Date: Thu, 28 Sep 2023 11:19:50 +0000 (+0200) Subject: Implement a mechanism for permissible file repair X-Git-Tag: accepted/tizen/unified/20240117.163258~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4888eb34d37b6d0b2a1730c5ea5affd7dcfbb09b;p=platform%2Fcore%2Fsecurity%2Fsecurity-manager.git Implement a mechanism for permissible file repair 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 --- diff --git a/src/client/client-label-monitor.cpp b/src/client/client-label-monitor.cpp index 19583761..7050cf2c 100644 --- a/src/client/client-label-monitor.cpp +++ b/src/client/client-label-monitor.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include #include #include +#include #include 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 &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 appLabels; try { - PermissibleSet::readLabelsFromPermissibleFile(global_label_file, appLabels); - PermissibleSet::readLabelsFromPermissibleFile(user_label_file, appLabels); - std::vector 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 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; }); diff --git a/src/common/include/permissible-set.h b/src/common/include/permissible-set.h index aaa6d5b0..88588cb7 100644 --- a/src/common/include/permissible-set.h +++ b/src/common/include/permissible-set.h @@ -34,6 +34,7 @@ #include #include +#include #include namespace SecurityManager { @@ -109,6 +110,16 @@ void updatePermissibleFile(uid_t uid, int installationType, */ void readLabelsFromPermissibleFile(const std::string &nameFile, std::vector &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); diff --git a/src/common/include/protocols.h b/src/common/include/protocols.h index c4218330..99604dc3 100644 --- a/src/common/include/protocols.h +++ b/src/common/include/protocols.h @@ -145,6 +145,7 @@ enum class SecurityModuleCall GET_APP_MANIFEST_POLICY, GET_PROCESS_LABEL, PREPARE_APP, + REPAIR_PERMISSIBLE_FILE, NOOP = 0x90, }; diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index 0cb1e7cb..687f3cbb 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -390,6 +390,16 @@ public: Smack::Label &label, std::string &pkgName, PrepareAppFlags &prepareAppFlags, std::vector &forbiddenGroups, std::vector &allowedGroups, std::vector &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 &newLabels, + const std::vector &oldLabels); + bool authenticate(const Credentials &creds, const std::string &privilege); bool authCheck(const Credentials &creds, diff --git a/src/common/permissible-set.cpp b/src/common/permissible-set.cpp index b8e826ef..8fb4a990 100644 --- a/src/common/permissible-set.cpp +++ b/src/common/permissible-set.cpp @@ -64,9 +64,22 @@ 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 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 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); diff --git a/src/common/protocols.cpp b/src/common/protocols.cpp index b7a8e777..5aabc56c 100644 --- a/src/common/protocols.cpp +++ b/src/common/protocols.cpp @@ -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"; } diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 76a5602f..fd612f4f 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -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 &newLabels, + const std::vector &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 */ diff --git a/src/server/service/include/service.h b/src/server/service/include/service.h index e433f291..86bb407c 100644 --- a/src/server/service/include/service.h +++ b/src/server/service/include/service.h @@ -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 diff --git a/src/server/service/service.cpp b/src/server/service/service.cpp index c12dd6a7..4545de29 100644 --- a/src/server/service/service.cpp +++ b/src/server/service/service.cpp @@ -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