# Set required packages
INCLUDE(FindPkgConfig)
SET(AUL-1_LIB_PKG_CHECK_MODULES
- dlog
bundle
- xdgmime
- libtzplatform-config
- pkgmgr-info
capi-system-info
- vconf
- sqlite3
- iniparser
+ dlog
gio-2.0
glib-2.0
+ iniparser
+ libsmack
+ libtzplatform-config
libxml-2.0
- ttrace
+ pkgmgr-info
+ sqlite3
storage
- uuid)
+ ttrace
+ uuid
+ vconf
+ xdgmime
+ )
pkg_check_modules(libpkgs REQUIRED ${AUL-1_LIB_PKG_CHECK_MODULES})
FOREACH(flag ${libpkgs_CFLAGS})
BuildRequires: pkgconfig(pkgmgr-installer)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(uuid)
+BuildRequires: pkgconfig(libsmack)
Recommends: amd
Recommends: amd-mod-component-manager
%{_bindir}/appid2pid
%{_bindir}/launch_debug
%{_bindir}/compmgr_tool
+%{_bindir}/appsvc-db-recovery
+%{_bindir}/component-db-recovery
%{_datadir}/aul/miregex/*
%{_datadir}/aul/preexec_list.txt
%{_datadir}/appsvc/*
*/
#define _GNU_SOURCE
-#include <stdio.h>
#include <linux/limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <tzplatform_config.h>
#include "aul_db.h"
return db;
}
+sqlite3 *aul_db_create(const char *path)
+{
+ sqlite3 *db;
+ int ret;
+
+ ret = sqlite3_open_v2(path, &db,
+ SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
+ if (ret != SQLITE_OK) {
+ _E("sqlite3_open_v2() is failed. error(%d)", ret);
+ sqlite3_close_v2(db);
+ return NULL;
+ }
+
+ return db;
+}
+
void aul_db_close(sqlite3 *db)
{
sqlite3_close_v2(db);
return 0;
}
+
+static int __integrity_check(sqlite3 *db)
+{
+ const char query[] = "PRAGMA integrity_check";
+ sqlite3_stmt *stmt = NULL;
+ const char *res;
+ int ret;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("sqlite3_prepare_v2() is failed. error(%s)",
+ sqlite3_errmsg(db));
+ return -1;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW) {
+ LOGE("sqlite3_step() is failed. error(%s)", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ res = (const char *)sqlite3_column_text(stmt, 0);
+ if (!res) {
+ LOGE("Failed to check integrity db. error(%s)",
+ sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ if (strcmp(res, "ok") != 0) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+}
+
+static int __check_table(sqlite3 *db, const char **tables, int table_count)
+{
+ const char query[] = "SELECT name FROM sqlite_master "
+ "WHERE type='table' ORDER BY name ASC";
+ sqlite3_stmt *stmt = NULL;
+ const char *val;
+ int count = 0;
+
+ __PREPARE_V2(db, query, strlen(query), stmt);
+
+ while (sqlite3_step(stmt) == SQLITE_ROW && count < table_count) {
+ val = (const char *)sqlite3_column_text(stmt, 0);
+ if (val) {
+ _W("%s %s", val, tables[count]);
+ if (strcmp(tables[count], val) != 0)
+ continue;
+ count++;
+ }
+ }
+
+ sqlite3_finalize(stmt);
+
+ if (count != table_count) {
+ _E("Wrong table count(%d:%d)", count, table_count);
+ return -1;
+ }
+
+ return 0;
+}
+
+int aul_db_verify(const char *path, const char **tables, int table_count)
+{
+ sqlite3 *db;
+ int ret;
+
+ if (!path) {
+ _E("Invalid parameter");
+ return -1;
+ }
+
+ ret = access(path, F_OK);
+ if (ret != 0) {
+ _E("%s does not exists. errno(%d)", path, errno);
+ return -1;
+ }
+
+ db = aul_db_open(path, true);
+ if (!db) {
+ _E("Failed to open database(%s)", path);
+ return -1;
+ }
+
+ ret = __integrity_check(db);
+ if (ret != 0) {
+ _E("Database(%s) is corrupted", path);
+ aul_db_close(db);
+ return -1;
+ }
+
+ ret = __check_table(db, tables, table_count);
+ aul_db_close(db);
+ if (ret != 0) {
+ _E("Database(%s) is corrupted", path);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __change_permission(const char *path)
+{
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
+ char path_db_journal[PATH_MAX];
+ int ret;
+
+ ret = chmod(path, mode);
+ if (ret != 0) {
+ _E("chmod() is failed. errno(%d)", errno);
+ return -1;
+ }
+
+ snprintf(path_db_journal, sizeof(path_db_journal), "%s-journal", path);
+ ret = chmod(path_db_journal, mode);
+ if (ret != 0) {
+ _E("chmod() is failed. errno(%d)", errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __change_ownership(const char *path, uid_t uid)
+{
+#define ROOT_UID 0
+ struct passwd pwd;
+ struct passwd *result;
+ char path_db_journal[PATH_MAX];
+ char buf[PATH_MAX];
+ uid_t new_uid;
+ int ret;
+
+ ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ if (ret == 0)
+ _E("No such user(%u)", uid);
+ else
+ _E("getpwuid_r() is failed. errno(%d)", errno);
+ return -1;
+ }
+
+ if (pwd.pw_uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
+ new_uid = ROOT_UID;
+ else
+ new_uid = pwd.pw_uid;
+
+ ret = chown(path, new_uid, pwd.pw_gid);
+ if (ret != 0) {
+ _E("chown() is failed. errno(%d)", errno);
+ return -1;
+ }
+
+ snprintf(path_db_journal, sizeof(path_db_journal), "%s-journal", path);
+ ret = chown(path_db_journal, new_uid, pwd.pw_gid);
+ if (ret != 0) {
+ _E("chown() is failed. errno(%d)", errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __change_smack(const char *path)
+{
+#define DB_LABEL "User::Home"
+ char path_db_journal[PATH_MAX];
+ int ret;
+
+ ret = smack_setlabel(path, DB_LABEL, SMACK_LABEL_ACCESS);
+ if (ret != 0) {
+ _E("smack_setlabel() is failed. error(%d)", ret);
+ return -1;
+ }
+
+ snprintf(path_db_journal, sizeof(path_db_journal), "%s-journal", path);
+ ret = access(path_db_journal, F_OK);
+ if (ret == 0) {
+ ret = smack_setlabel(path_db_journal, DB_LABEL,
+ SMACK_LABEL_ACCESS);
+ if (ret != 0) {
+ _E("smack_setlabel() is failed. error(%d)", ret);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int aul_db_recovery(const char *path, const char *query, uid_t uid)
+{
+ char *errmsg = NULL;
+ sqlite3 *db;
+ int ret;
+
+ if (!path || !query) {
+ _E("Invalid parameter");
+ return -1;
+ }
+
+ ret = access(path, F_OK);
+ if (ret == 0)
+ unlink(path);
+
+ db = aul_db_create(path);
+ if (!db) {
+ _E("Failed to open database(%s)", path);
+ return -1;
+ }
+
+ ret = sqlite3_exec(db, query, NULL, NULL, &errmsg);
+ aul_db_close(db);
+ if (ret != SQLITE_OK) {
+ _E("sqlite3_exec() is failed. error(%d:%s)", ret, errmsg);
+ sqlite3_free(errmsg);
+ return -1;
+ }
+
+ ret = __change_smack(path);
+ if (ret != 0) {
+ _E("Failed to change smack label of %s", path);
+ return -1;
+ }
+
+ ret = __change_ownership(path, uid);
+ if (ret != 0) {
+ _E("Failed to change ownership of %s", path);
+ return -1;
+ }
+
+ ret = __change_permission(path);
+ if (ret != 0) {
+ _E("Failed to change permissions of %s", path);
+ return -1;
+ }
+
+ return 0;
+}
int aul_db_save_column_str(sqlite3_stmt *stmt, int idx, char **str);
+int aul_db_verify(const char *path, const char **tables, int table_count);
+
+int aul_db_recovery(const char *path, const char *query, uid_t uid);
+
#ifdef __cplusplus
}
#endif
compmgr_tool.c)
target_link_libraries(compmgr_tool aul ${pkgs_LDFLAGS} "-pie")
INSTALL(TARGETS compmgr_tool DESTINATION bin)
+
+ADD_SUBDIRECTORY(recovery)
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(aul-db-recovery C)
+
+SET(PREFIX "${CMAKE_INSTALL_PREFIX}")
+SET(EXEC_PREFIX "\${prefix}")
+SET(PROJECT_NAME "${PROJECT_NAME}")
+SET(LIBDIR ${LIB_INSTALL_DIR})
+SET(INCLUDEDIR "\${prefix}/include")
+SET(VERSION ${FULLVER})
+
+INCLUDE(FindPkgConfig)
+SET(requires "dlog sqlite3 libsmack libtzplatform-config")
+pkg_check_modules(aul-db-recovery REQUIRED ${requires})
+
+FOREACH(flag ${aul-db-recovery_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include)
+
+ADD_EXECUTABLE(appsvc-db-recovery
+ ${CMAKE_CURRENT_SOURCE_DIR}/appsvc_db_recovery.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src/aul_db.c)
+TARGET_LINK_LIBRARIES(appsvc-db-recovery ${aul-db-recovery_LDFLAGS} "-pie")
+INSTALL(TARGETS appsvc-db-recovery DESTINATION bin)
+
+ADD_EXECUTABLE(component-db-recovery
+ ${CMAKE_CURRENT_SOURCE_DIR}/component_db_recovery.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src/aul_db.c)
+TARGET_LINK_LIBRARIES(component-db-recovery ${aul-db-recovery_LDFLAGS} "-pie")
+INSTALL(TARGETS component-db-recovery DESTINATION bin)
+
--- /dev/null
+/*
+ * Copyright (c) 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <tzplatform_config.h>
+
+#include "aul_db.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#define ROOT_UID 0
+
+#define QUERY_CREATE_APPSVC \
+ "PRAGMA journal_mode = PERSIST;\n" \
+ "CREATE TABLE IF NOT EXISTS appsvc (\n" \
+ " operation TEXT,\n" \
+ " mime_type TEXT DEFAULT 'NULL',\n" \
+ " uri TEXT DEFAULT 'NULL',\n" \
+ " pkg_name TEXT,\n" \
+ " PRIMARY KEY (operation,mime_type,uri)\n" \
+ ");\n" \
+ "CREATE TABLE IF NOT EXISTS alias_info (\n" \
+ " alias_appid TEXT NOT NULL,\n" \
+ " appid TEXT NOT NULL,\n" \
+ " enable TEXT NOT NULL DEFAULT 'true',\n" \
+ " PRIMARY KEY (alias_appid)\n" \
+ ");\n" \
+ "CREATE TABLE IF NOT EXISTS alias_info_for_uid (\n" \
+ " appid TEXT NOT NULL,\n" \
+ " uid INTEGER NOT NULL,\n" \
+ " is_enabled TEXT NOT NULL DEFAULT 'false',\n" \
+ " PRIMARY KEY (appid, uid)\n" \
+ " FOREIGN KEY (appid)\n" \
+ " REFERENCES alias_info(appid)\n" \
+ " ON DELETE CASCADE\n" \
+ ");\n" \
+ "CREATE TRIGGER IF NOT EXISTS update_alias_info_for_uid\n" \
+ " AFTER UPDATE ON alias_info_for_uid\n" \
+ " BEGIN\n" \
+ " DELETE FROM alias_info_for_uid\n" \
+ " WHERE is_enabled='true';\n" \
+ " END;\n" \
+ "CREATE TABLE IF NOT EXISTS allowed_info (\n" \
+ " appid TEXT NOT NULL,\n" \
+ " allowed_appid TEXT NOT NULL,\n" \
+ " PRIMARY KEY (appid, allowed_appid)\n" \
+ ");"
+
+static int __check_db_integrity(uid_t uid)
+{
+ static const char *tables[] = {
+ "alias_info",
+ "alias_info_for_uid",
+ "allowed_info",
+ "appsvc",
+ };
+ char *db_path;
+ int ret;
+
+ db_path = aul_db_get_path(".appsvc.db", uid);
+ if (!db_path) {
+ _E("Failed to get db path");
+ return -1;
+ }
+
+ ret = aul_db_verify(db_path, tables, ARRAY_SIZE(tables));
+ if (ret == 0) {
+ free(db_path);
+ return 0;
+ }
+
+ ret = aul_db_recovery(db_path, QUERY_CREATE_APPSVC, uid);
+ if (ret != 0) {
+ printf("Failed to recovery %s\n", db_path);
+ free(db_path);
+ return -1;
+ }
+ free(db_path);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ if (getuid() != ROOT_UID) {
+ fprintf(stderr, "Only root user can run this tool\n");
+ return -1;
+ }
+
+ ret = __check_db_integrity(tzplatform_getuid(TZ_SYS_GLOBALAPP_USER));
+ if (ret != 0)
+ return -1;
+
+ ret = __check_db_integrity(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+ if (ret != 0)
+ return -1;
+
+ printf("appsvc DB recovery process done\n");
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <tzplatform_config.h>
+
+#include "aul_db.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#define ROOT_UID 0
+
+#define QUERY_CREATE_COMPONENT \
+ "PRAGMA journal_mode = PERSIST;\n" \
+ "CREATE TABLE IF NOT EXISTS component_info (\n" \
+ " package TEXT NOT NULL,\n" \
+ " app_id TEXT NOT NULL,\n" \
+ " component_id TEXT NOT NULL,\n" \
+ " component_type TEXT NOT NULL,\n" \
+ " component_launch_mode TEXT NOT NULL,\n" \
+ " component_main TEXT NOT NULL,\n" \
+ " component_icon_display NOT NULL,\n" \
+ " component_taskmanage NOT NULL,\n" \
+ " PRIMARY KEY (component_id)\n" \
+ ");\n" \
+ "CREATE TABLE IF NOT EXISTS component_localized_info (\n" \
+ " component_id TEXT NOT NULL,\n" \
+ " component_locale TEXT NOT NULL DEFAULT 'No Locale',\n" \
+ " component_label TEXT,\n" \
+ " component_icon TEXT,\n" \
+ " PRIMARY KEY (component_id, component_locale)\n" \
+ " FOREIGN KEY (component_id)\n" \
+ " REFERENCES component_info(component_id) ON DELETE CASCADE\n" \
+ ");"
+
+static int __check_db_integrity(uid_t uid)
+{
+ static const char *tables[] = {
+ "component_info",
+ "component_localized_info",
+ };
+ char *db_path;
+ int ret;
+
+ db_path = aul_db_get_path(".component.db", uid);
+ if (!db_path) {
+ _E("Failed to get db path");
+ return -1;
+ }
+
+ ret = aul_db_verify(db_path, tables, ARRAY_SIZE(tables));
+ if (ret == 0) {
+ free(db_path);
+ return 0;
+ }
+
+ ret = aul_db_recovery(db_path, QUERY_CREATE_COMPONENT, uid);
+ if (ret != 0) {
+ printf("Failed to recovery %s\n", db_path);
+ free(db_path);
+ return -1;
+ }
+
+ free(db_path);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ if (getuid() != ROOT_UID) {
+ fprintf(stderr, "Only root user can run this tool\n");
+ return -1;
+ }
+
+ ret = __check_db_integrity(tzplatform_getuid(TZ_SYS_GLOBALAPP_USER));
+ if (ret != 0)
+ return -1;
+
+ ret = __check_db_integrity(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+ if (ret != 0)
+ return -1;
+
+ printf("component DB recovery process done\n");
+
+ return 0;
+}