Initialize database and restart service in policy-reload 72/187472/10
authorKonrad Lipinski <k.lipinski2@partner.samsung.com>
Thu, 23 Aug 2018 11:57:03 +0000 (13:57 +0200)
committerKonrad Lipinski <k.lipinski2@partner.samsung.com>
Fri, 24 Aug 2018 13:13:18 +0000 (15:13 +0200)
Added the security-manager-cmd --init-db option that replicates manager
startup database bringup semantics.

Amended security-manager-policy-reload.in to:
* stop the service before inserting into the database to avoid
  concurrent modification
* call security-manager-cmd --init-db to make sure the database exists
  and is coherent prior to modifying it
* perform the database transaction
* start the service so that it reads the modified database

Rationale: prior to the patch, the manager would work on stale data as
the service was already running during policy-reload invocation.

While at it, homogenized systemctl {start,stop} invocations.

Said invocations are now of the form:
systemctl {start,stop} security-manager.service security-manager.socket

Rationale:
* strive for code uniformity
* leverage systemd's automatic dependency resolution
* speed up a bit

Change-Id: I21b254345abaa617b6a389dfd060fb4a4799a148

packaging/security-manager.spec
policy/security-manager-policy-reload.in
src/cmd/CMakeLists.txt
src/cmd/security-manager-cmd.cpp
src/common/include/privilege_db.h
src/common/privilege_db.cpp

index 473098d3fe1f698bcb5e53168da5d72e9211f935..699d19f33ed981f27d0af39cdac56149507d6cba 100644 (file)
@@ -160,16 +160,15 @@ rm -rf %{buildroot}
 systemctl daemon-reload
 if [ $1 = 1 ]; then
     # installation
-    systemctl start security-manager.socket
-    systemctl start security-manager.service
+    security-manager-cmd --init-db
+    systemctl start security-manager.service security-manager.socket
 fi
 
 if [ $1 = 2 ]; then
     # update
-    systemctl stop security-manager.socket
-    systemctl stop security-manager.service
-    systemctl start security-manager.socket
-    systemctl start security-manager.service
+    systemctl stop security-manager.service security-manager.socket
+    security-manager-cmd --init-db
+    systemctl start security-manager.service security-manager.socket
 fi
 
 chsmack -a System %{TZ_SYS_DB}/.security-manager.db
index 412011555291943159595ff690264185da33c2cd..575607f23b791ca4ba1b81e2c9eb4e737e4cd0a9 100755 (executable)
@@ -70,6 +70,10 @@ cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="User::Shell" --user="0" --
 # @(kernel thread) can get access to internet privilege
 cyad --set-policy --bucket=MANIFESTS_GLOBAL --client="@" --user=* --privilege="http://tizen.org/privilege/internet" --type=ALLOW
 
+# Stop the service to prevent concurrent db access
+systemctl stop security-manager.service security-manager.socket \
+    || echo Failed to stop security-manager systemd service, continuing regardless
+
 # Load privilege-group mappings
 (
 echo "BEGIN;"
@@ -81,3 +85,7 @@ do
 done
 echo "COMMIT;"
 ) | sqlite3 "$DB_FILE"
+
+# Start the service with the modified database
+systemctl start security-manager.service security-manager.socket \
+    || echo Failed to start security-manager systemd service, continuing regardless
index f1ae65012b2b13fe14f050a8ead6ac39e403365d..1fe731d44a19f68d7edf72c81515243bde1fd4f9 100644 (file)
@@ -8,6 +8,7 @@ INCLUDE_DIRECTORIES(
     ${INCLUDE_PATH}
     ${COMMON_PATH}/include
     ${DPL_PATH}/core/include
+    ${DPL_PATH}/db/include
     ${DPL_PATH}/log/include
     )
 
index 120bf0593d6204f62856d9adbe9ba27c0d2d9723..50c29fe85d4fa94e5af46fe3bc61b2039c89cae0 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <config.h>
 #include <filesystem.h>
+#include <privilege_db.h>
 
 namespace po = boost::program_options;
 
@@ -75,6 +76,7 @@ static po::options_description getGenericOptions()
          ("manage-users,m", po::value<std::string>(), "add or remove user, parameter is either a/add or r/remove")
          ("manage-privilege,o", po::value<std::string>(), "allow or deny privilege, parameter is either a/allow or d/deny")
          ("backup,b", "make a backup of the database file")
+         ("init-db,d", "initialize the security-manager database as when running the manager")
          ;
     return opts;
 }
@@ -482,6 +484,9 @@ int main(int argc, char *argv[])
         } else if (vm.count("backup")) {
             if (SECURITY_MANAGER_SUCCESS == FS::overwriteFile(Config::privilegeDbPath, Config::privilegeDbFallbackPath))
                 return EXIT_SUCCESS;
+        } else if (vm.count("init-db")) {
+            SecurityManager::initDb();
+            return EXIT_SUCCESS;
         } else {
             std::cout << "No command argument was given." << std::endl;
             usage(std::string(argv[0]));
index eac2d7d4c280416149628adf4da42d256e99f4af..e8e26ac30e733d8b8dd12a16e6d19744c01d0a7a 100644 (file)
@@ -40,7 +40,7 @@
 #include <string>
 #include <vector>
 
-#include "dpl/db/sql_connection.h"
+#include <dpl/db/sql_connection.h>
 #include "security-manager-types.h"
 
 #include "pkg-info.h"
@@ -48,6 +48,7 @@
 namespace SecurityManager {
 
 std::string genJournalPath(const std::string &dbPath);
+void initDb();
 
 enum class StmtType : uint8_t {
     EAddApplication,
index eef3a761aa35eefebc1f1d4de103f3fed07ca6e0..81d53c3a04c5111cb7ac0a106bc5c8b60b11dad3 100644 (file)
@@ -213,17 +213,38 @@ void tryCatchDbInit(F &&f) {
 
 void applyFallbackDb(DB::SqlConnection &conn, const std::string &dbPath, const std::string &roFallbackPath) {
     if (SECURITY_MANAGER_SUCCESS != FS::overwriteFile(roFallbackPath, dbPath))
-        throwDbInitEx("Error overwriting database with fallback: " + roFallbackPath);
+        throwDbInitEx("Error overwriting database " + dbPath +  " with fallback: " + roFallbackPath);
     if (SECURITY_MANAGER_SUCCESS != FS::truncateFile(genJournalPath(dbPath)))
         throwDbInitEx("Error truncating journal");
     tryCatchDbInit([&]{ connectMigrateVerify(conn, dbPath); });
 }
+
+void initDb(DB::SqlConnection &conn, const std::string &path, const std::string &roFallbackPath) {
+    removeBrokenFlagFile(path);
+    if (!FS::fileStatus(path)) {
+        createBrokenFlagFile(path);
+        LogError("Database file " + path + " missing, attempting fallback");
+        applyFallbackDb(conn, path, roFallbackPath);
+    } else try {
+        connectMigrateVerify(conn, path);
+    } catch (DB::SqlConnection::Exception::Base &e) {
+        createBrokenFlagFile(path);
+        LogError("Database initialization error (" << e.DumpToString() << "), attempting fallback");
+        tryCatchDbInit([&]{ conn.Disconnect(); });
+        applyFallbackDb(conn, path, roFallbackPath);
+    }
+}
 } //namespace
 
 std::string genJournalPath(const std::string &dbPath) {
     return dbPath + "-journal";
 }
 
+void initDb() {
+    DB::SqlConnection conn;
+    initDb(conn, Config::privilegeDbPath, Config::privilegeDbFallbackPath);
+}
+
 PrivilegeDb::PrivilegeDb()
     : PrivilegeDb(Config::privilegeDbPath, Config::privilegeDbFallbackPath)
 {
@@ -231,19 +252,7 @@ PrivilegeDb::PrivilegeDb()
 
 PrivilegeDb::PrivilegeDb(const std::string &path, const std::string &roFallbackPath)
 {
-    removeBrokenFlagFile(path);
-    if (!FS::fileStatus(path)) {
-        createBrokenFlagFile(path);
-        LogError("Database file missing, attempting fallback");
-        applyFallbackDb(mSqlConnection, path, roFallbackPath);
-    } else try {
-        connectMigrateVerify(mSqlConnection, path);
-    } catch (DB::SqlConnection::Exception::Base &e) {
-        createBrokenFlagFile(path);
-        LogError("Database initialization error (" << e.DumpToString() << "), attempting fallback");
-        tryCatchDbInit([&]{ mSqlConnection.Disconnect(); });
-        applyFallbackDb(mSqlConnection, path, roFallbackPath);
-    }
+    initDb(mSqlConnection, path, roFallbackPath);
     tryCatchDbInit([&]{ initDataCommands(); });
 }