/*
- * 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.
// 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:
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;
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;
}
// 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);
// 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");
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
/*
- * 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.
PrivilegeV0DBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EXAMPLE_V0) {}
};
struct PrivilegeEmptyDBFixture : PrivilegeDBFixture {
- PrivilegeEmptyDBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EMPTY) {}
+ PrivilegeEmptyDBFixture() : PrivilegeDBFixture(PRIVILEGE_DB_EMPTY, {}) {}
};
} //namespace
};
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);
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);