Apply db fallback is present and the db is an empty file 76/197476/1
authorKonrad Lipinski <k.lipinski2@partner.samsung.com>
Wed, 9 Jan 2019 12:33:23 +0000 (13:33 +0100)
committerKonrad Lipinski <k.lipinski2@partner.samsung.com>
Fri, 11 Jan 2019 10:50:29 +0000 (11:50 +0100)
Change-Id: Idfa81003639c5452ae85e79257aa5425547d42ea

src/server/rules-loader/security-manager-rules-loader.cpp
test/test_privilege_db_migration.cpp

index df5cc3f755fb49ee892e40ddb6dc4014a6661741..3a6dc32388987afeea9dbf6ecd1d73e65e2c58fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2018-2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -458,6 +458,19 @@ size_t sharedROPkgIndex = ~size_t(0);
 // temporary buffer for decimal author_id stringification (not \0-terminated)
 char authorBuf[std::numeric_limits<sqlite3_int64>::digits10 + 1];
 
+// fallback database path if not null
+char const *cachedFallbackPath;
+char const *getFallbackPath() {
+    if (likely(!cachedFallbackPath)) {
+        cachedFallbackPath = testLoader
+            ? TEST_PRIVILEGE_FALLBACK_DB_PATH
+            : tzplatform_mkpath3(TZ_SYS_RO_SHARE, "security-manager", ".security-manager.db");
+        if (unlikely(!cachedFallbackPath))
+            fail("tzplatform_mkpath(fallback) failed");
+    }
+    return cachedFallbackPath;
+}
+
 
 // rule template code generated by sh$ policy/generate-rule-code policy/*.smack
 // included in anonymous namespace at this particular point to:
@@ -526,9 +539,11 @@ inl bool fileEmpty(const char *filePath) {
     return !lstat(filePath, &st) && !st.st_size;
 }
 
+enum class CheckFallback : bool { no, yes };
+
 // open dbPath, potentially migrating to newer version and applying schema, then checking integrity
 // return true iff successful
-bool dbUp() {
+bool dbUp(CheckFallback checkFallback) {
     if (unlikely(SQLITE_OK != sqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_NOMUTEX|SQLITE_OPEN_PRIVATECACHE, nullptr))) {
         toStderr("db open (%s) failed", dbPath);
         return false;
@@ -583,10 +598,13 @@ bool dbUp() {
                     return false;
                 }
             } while (++version < dbVersion);
+        } else if (likely(underlying(checkFallback)) && likely(!access(getFallbackPath(), F_OK))) {
+            toStderr("empty db with fallback present - will apply the fallback");
+            return false;
         }
 
         // apply schema
-        if (!dbExec(dbSchema)) {
+        if (unlikely(!dbExec(dbSchema))) {
             toStderr("db schema failed");
             return false;
         }
@@ -918,11 +936,7 @@ inl void overwriteDbFileWithFallback(size_t dbPathLen) {
 
     // retrieve fallback database file path
     // WARNING: dbPath memory has been made invalid (will restore later) due to tzplatform_mkpath* using a shared scratch buffer
-    char const *fallbackPath = testLoader
-        ? TEST_PRIVILEGE_FALLBACK_DB_PATH
-        : tzplatform_mkpath3(TZ_SYS_RO_SHARE, "security-manager", ".security-manager.db");
-    if (unlikely(!fallbackPath))
-        fail("tzplatform_mkpath(fallback) failed");
+    char const *fallbackPath = getFallbackPath();
 
     // open the fallback database regular file and get its size
     const int fallbackfd = open(fallbackPath, O_RDONLY);
@@ -1035,7 +1049,7 @@ int main(int argc, char *argv[]) {
     // try to bring up the main database if fallback-only was not requested, otherwise remove tmpfs marker to avoid ambiguity
     bool mainDbUp = false;
     if (likely(!fallbackOnly))
-        mainDbUp = dbUp();
+        mainDbUp = dbUp(CheckFallback::yes);
     else if (unlikely(!unlinkIfExists(dbOkMarker)))
         fail("unlink(dbOkMarker) failed");
 
@@ -1049,7 +1063,7 @@ int main(int argc, char *argv[]) {
         overwriteDbFileWithFallback(dbPathLen);
 
         // try to bring up the restored database
-        if (unlikely(!dbUp()))
+        if (unlikely(!dbUp(CheckFallback::no)))
             fail("fallback db bringup failed");
 
         // create the "database successfully recovered" marker file
index b06b0fd8eb61b9bb059e3a62185cabb1ff195a6f..e045eb4bd2d48a8c9c03c612b0cc612150e1da44 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2018-2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ struct PrivilegeV0DBFixture : PrivilegeDBFixture {
     PrivilegeV0DBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EXAMPLE_V0) {}
 };
 struct PrivilegeEmptyDBFixture : PrivilegeDBFixture {
-    PrivilegeEmptyDBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EMPTY) {}
+    PrivilegeEmptyDBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EMPTY, {}) {}
 };
 } //namespace
 
@@ -107,6 +107,8 @@ BOOST_AUTO_TEST_CASE(T1570_fallback_canonicity) {
     };
     go({},                        Marker::fallback, false);
     go({},                        Marker::fallback, true);
+    go(PRIVILEGE_DB_EMPTY,        Marker::fallback, false);
+    go(PRIVILEGE_DB_EMPTY,        Marker::fallback, true);
     go(PRIVILEGE_DB_CORRUPTED,    Marker::fallback, false);
     go(PRIVILEGE_DB_CORRUPTED,    Marker::fallback, true);
     go(PRIVILEGE_DB_WRONG_SCHEMA, Marker::standard, false);
@@ -141,6 +143,9 @@ BOOST_AUTO_TEST_CASE(T1590_fallback_migration_failure) {
     go({}, {}, Marker::none);
     go({}, PRIVILEGE_DB_CORRUPTED, Marker::none);
     go({}, PRIVILEGE_DB_WRONG_SCHEMA, Marker::fallback);
+    // NOTE: PRIVILEGE_DB_EMPTY, {} is missing on purpose - in this case fallback is not attempted but db is schema-seeded instead
+    go(PRIVILEGE_DB_EMPTY, PRIVILEGE_DB_CORRUPTED, Marker::none);
+    go(PRIVILEGE_DB_EMPTY, PRIVILEGE_DB_WRONG_SCHEMA, Marker::fallback);
     go(PRIVILEGE_DB_CORRUPTED, {}, Marker::none);
     go(PRIVILEGE_DB_CORRUPTED, PRIVILEGE_DB_CORRUPTED, Marker::none);
     go(PRIVILEGE_DB_CORRUPTED, PRIVILEGE_DB_WRONG_SCHEMA, Marker::fallback);