#include <gio/gio.h>
#include <iniparser.h>
#include <tzplatform_config.h>
+#include <pkgmgr-info.h>
#include "crash-manager.h"
#include "so-info.h"
#include "shared/log.h"
#include "shared/util.h"
+#include "dbus_notify.h"
#undef LOG_TAG
#define LOG_TAG "CRASH_MANAGER"
#define MAX_CRASH_DUMP 0
#define ALLOW_ZIP true
+#define APPID_MAX 128
+#define PKGNAME_MAX 128
+
#define CRASH_CHECK_DISK_PATH "/opt/usr"
#define WAIT_FOR_OPT_TIMEOUT_SEC 60
char info_path[PATH_MAX];
char core_path[PATH_MAX];
char log_path[PATH_MAX];
+ char appid[APPID_MAX];
+ char pkgid[PKGNAME_MAX];
#ifdef SYS_ASSERT
char sysassert_cs_path[PATH_MAX];
bool have_sysassert_report;
int prstatus_fd;
} crash_info;
+/* pkgmgrinfo filter list function for getting application ID */
+static int appinfo_get_appid_func(pkgmgrinfo_appinfo_h handle,
+ void *user_data)
+{
+ char *str = NULL;
+ int ret = PMINFO_R_ERROR;
+
+ pkgmgrinfo_appinfo_get_appid(handle, &str);
+ if (str) {
+ (*(char **)user_data) = strdup(str);
+ ret = PMINFO_R_OK;
+ }
+ return ret;
+}
+
+/* get application ID by pkgmgrinfo filter */
+static int get_appid(char *exepath, char *appid, int len)
+{
+ pkgmgrinfo_appinfo_filter_h handle = NULL;
+ int count, ret;
+ char *aid = NULL;
+
+ ret = pkgmgrinfo_appinfo_filter_create(&handle);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_EXEC, exepath);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out_free;
+ }
+
+ ret = pkgmgrinfo_appinfo_filter_count(handle, &count);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out_free;
+ }
+
+ if (count < 1) {
+ ret = -1;
+ goto out_free;
+ }
+
+ ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appinfo_get_appid_func, &aid);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out_free;
+ }
+ if (aid) {
+ snprintf(appid, len, "%s", aid);
+ ret = 0;
+ free(aid);
+ }
+
+out_free:
+ pkgmgrinfo_appinfo_filter_destroy(handle);
+out:
+ return ret;
+}
+
+/* get package ID by appid */
+static int get_pkgid(char *appid, char *pkgid, int len)
+{
+ pkgmgrinfo_appinfo_h handle = NULL;
+ int ret;
+ char *pkid = NULL;
+
+ ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out;
+ }
+ ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkid);
+ if (ret != PMINFO_R_OK) {
+ ret = -1;
+ goto out_free;
+ }
+ snprintf(pkgid, len, "%s", pkid);
+
+out_free:
+ pkgmgrinfo_appinfo_destroy_appinfo(handle);
+out:
+ return ret;
+}
+
static void get_config(void)
{
dictionary *ini = NULL;
if (set_prstatus() < 0)
goto rm_temp;
+ if (get_appid(crash_info.cmd_line, crash_info.appid, sizeof(crash_info.appid)) < 0) {
+ snprintf(crash_info.appid, sizeof(crash_info.appid), "%s", basename(crash_info.cmd_line));
+ snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", basename(crash_info.cmd_line));
+ } else {
+ if (get_pkgid(crash_info.appid, crash_info.pkgid, sizeof(crash_info.pkgid)) < 0)
+ snprintf(crash_info.pkgid, sizeof(crash_info.pkgid), "%s", crash_info.appid);
+ }
+
return 0;
rm_temp:
launch_crash_popup();
#endif
+ struct NotifyParams notify_params = {
+ .prstatus_fd = crash_info.prstatus_fd,
+ .pid = strtol(crash_info.pid_info, NULL, 10),
+ .tid = strtol(crash_info.tid_info, NULL, 10),
+ .cmd_name = basename(crash_info.cmd_line),
+ .cmd_path = crash_info.cmd_path,
+ .report_path = crash_info.result_path,
+ .appid = crash_info.appid,
+ .pkgid = crash_info.pkgid
+ };
+
+ send_notify(¬ify_params);
+
close(crash_info.prstatus_fd);
return 0;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ * Author: Mateusz Moscicki <m.moscicki2@partner.samsung.com>
+ */
+
+#define _GNU_SOURCE
+#include <gio/gio.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/procfs.h>
+#include "shared/log.h"
+#include "dbus_notify.h"
+
+#define KERNEL_DEFINED_TASK_COMM_LEN 16 // from include/linux/sched.h
+
+#define ARM_REG_LR 14
+#define ARM_REG_PC 15
+#define AARCH64_REG_LR 30
+
+static int _get_important_registers(int fd, struct RegInfo **reg_info)
+{
+ int count = -1;
+
+ if (reg_info == NULL) {
+ _E("reg_info is NULL\n");
+ return -1;
+ }
+
+ *reg_info = NULL;
+ struct elf_prstatus *prstatus = mmap(NULL, sizeof(struct elf_prstatus),
+ PROT_READ, MAP_SHARED, fd, 0);
+ if (prstatus == MAP_FAILED) {
+ _E("mmap error: %m\n");
+ return -1;
+ }
+
+#if (defined __i386__) || (defined __x86_64__)
+ count = 1;
+#elif (defined __arm__) || (defined __aarch64__)
+ count = 2;
+#endif
+
+ *reg_info = (struct RegInfo*)malloc(sizeof(struct RegInfo)*count);
+ struct RegInfo *reginfo = *reg_info;
+
+ if (*reg_info == NULL) {
+ _E("malloc for reg_info error: %m");
+ goto out;
+ }
+
+#if (defined __i386__) || (defined __x86_64__)
+ struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg;
+
+#if defined(__i386__)
+ reginfo[0].name = strdup("x86.eip");
+ reginfo[0].value = (long long int)g_registers->eip;
+#else
+ reginfo[0].name = strdup("x86_64.rip");
+ reginfo[0].value = (long long int)g_registers->rip;
+#endif // defined(__i386__)
+
+ if (reginfo[0].name == NULL)
+ goto strdup_error;
+
+#elif defined(__arm__)
+
+ struct user_regs *g_registers;
+ g_registers = (struct user_regs*)prstatus->pr_reg;
+
+ if ((reginfo[0].name = strdup("arm.pc")) == NULL)
+ goto strdup_error;
+ reginfo[0].value = (long long int)g_registers->uregs[ARM_REG_PC];
+ if ((reginfo[1].name = strdup("arm.lr")) == NULL)
+ goto strdup_error;
+ reginfo[1].value = (long long int)g_registers->uregs[ARM_REG_LR];
+
+#elif defined(__aarch64__)
+
+ struct user_regs_struct *g_registers = (struct user_regs_struct*)prstatus->pr_reg;
+
+ if ((reginfo[0].name = strdup("aarch64.pc")) == NULL)
+ goto strdup_error;
+ reginfo[0].value = (long long int)g_registers->pc;
+ if ((reginfo[1].name = strdup("aarch64.lr")) == NULL)
+ goto strdup_error;
+ reginfo[1].value = (long long int)g_registers->regs[AARCH64_REG_LR];
+
+#endif // (defined __i386__) || (defined __x86_64__)
+
+out:
+ if (count <= 0) {
+ free(*reg_info);
+ *reg_info = NULL;
+ }
+
+ munmap(prstatus, sizeof(*prstatus));
+ return count;
+
+strdup_error:
+ _E("strdup error: %m\n");
+ count = -1;
+ goto out;
+}
+
+static GVariant* build_message_data(const struct NotifyParams *notify_params)
+{
+ if (notify_params == NULL)
+ return NULL;
+
+ GVariantBuilder md_builder;
+ g_variant_builder_init(&md_builder, G_VARIANT_TYPE("(sssssiia{sv})"));
+
+ g_variant_builder_add(&md_builder, "s", notify_params->cmd_name);
+ g_variant_builder_add(&md_builder, "s", notify_params->cmd_path);
+ g_variant_builder_add(&md_builder, "s", notify_params->appid);
+ g_variant_builder_add(&md_builder, "s", notify_params->pkgid);
+ g_variant_builder_add(&md_builder, "s", notify_params->report_path);
+ g_variant_builder_add(&md_builder, "i", notify_params->pid);
+ g_variant_builder_add(&md_builder, "i", notify_params->tid);
+
+ g_variant_builder_open(&md_builder, G_VARIANT_TYPE("a{sv}"));
+
+ struct RegInfo *reg_info;
+ int regs_count = _get_important_registers(notify_params->prstatus_fd, ®_info);
+
+ /* registers */
+ for (int i = 0; i < regs_count; i++) {
+ g_variant_builder_open(&md_builder, G_VARIANT_TYPE("{sv}"));
+
+ g_variant_builder_add(&md_builder, "s", reg_info[i].name);
+#if (defined __x86_64__) || (defined __aarch64__)
+ g_variant_builder_add(&md_builder, "v", g_variant_new_uint64(reg_info[i].value));
+#else
+ g_variant_builder_add(&md_builder, "v", g_variant_new_uint32(reg_info[i].value));
+#endif
+
+ free(reg_info[i].name);
+ g_variant_builder_close(&md_builder);
+ }
+ free(reg_info);
+
+ g_variant_builder_close(&md_builder);
+
+ return g_variant_builder_end(&md_builder);
+}
+
+int send_notify(const struct NotifyParams *notify_params)
+{
+ int result = 1;
+
+ GDBusConnection *conn = NULL;
+ GError *error = NULL;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (error) {
+ _E("g_bus_get_sync error: %s\n", error->message);
+ g_error_free(error);
+ result = 0;
+ goto end;
+ }
+
+ GVariant *data = build_message_data(notify_params);
+
+ if (data == NULL) {
+ _E("build_message error\n");
+ result = 0;
+ goto end;
+ }
+
+ g_dbus_connection_emit_signal(conn,
+ NULL,
+ CRASH_PATH_CRASH,
+ CRASH_INTERFACE_CRASH,
+ PROCESS_CRASHED,
+ data,
+ &error);
+
+ if (error) {
+ _E("g_dbus_connection_emit_signal error: %s\n", error->message);
+ g_error_free(error);
+ result = 0;
+ goto end;
+ }
+
+ g_dbus_connection_flush_sync(conn, NULL, &error);
+ if (error) {
+ _E("g_dbus_connection_flush_sync error: %s\n", error->message);
+ g_error_free(error);
+ }
+end:
+ if (conn != NULL)
+ g_object_unref(conn);
+
+ return result;
+}
--- /dev/null
+/*
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ * Author: Mateusz Moscicki <m.moscicki2@partner.samsung.com>
+ */
+
+#define CRASH_BUS_NAME "org.tizen.system.crash"
+#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash"
+#define CRASH_INTERFACE_NAME CRASH_BUS_NAME
+#define CRASH_PATH_CRASH CRASH_OBJECT_PATH"/Crash"
+#define CRASH_INTERFACE_CRASH CRASH_INTERFACE_NAME".Crash"
+#define PROCESS_CRASHED "ProcessCrashed"
+
+struct RegInfo {
+ char *name;
+ long long int value;
+};
+
+struct NotifyParams {
+ int prstatus_fd;
+ pid_t pid;
+ pid_t tid;
+ char *cmd_name;
+ char *cmd_path;
+ char *report_path;
+ char *appid;
+ char *pkgid;
+};
+
+int send_notify(const struct NotifyParams *notify_params);