static void save_bt_to_dump_dir(const char *bt, const char *exe, const char *reason) { time_t t = time(NULL); const char *iso_date = iso_date_string(&t); pid_t my_pid = getpid(); char base[sizeof("xorg-YYYY-MM-DD-hh:mm:ss-%lu-%lu") + 2 * sizeof(long)*3]; sprintf(base, "xorg-%s-%lu-%u", iso_date, (long)my_pid, g_bt_count); char *path = concat_path_file(debug_dumps_dir, base); struct dump_dir *dd = dd_create(path, /*fs owner*/0, DEFAULT_DUMP_DIR_MODE); if (dd) { dd_create_basic_files(dd, /*no uid*/(uid_t)-1L, NULL); dd_save_text(dd, FILENAME_ABRT_VERSION, VERSION); dd_save_text(dd, FILENAME_ANALYZER, "abrt-xorg"); dd_save_text(dd, FILENAME_TYPE, "xorg"); dd_save_text(dd, FILENAME_REASON, reason); dd_save_text(dd, FILENAME_BACKTRACE, bt); /* * Reporters usually need component name to file a bug. * It is usually derived from executable. * We _guess_ X server's executable name as a last resort. * Better ideas? */ if (!exe) { exe = "/usr/bin/X"; if (access("/usr/bin/Xorg", X_OK) == 0) exe = "/usr/bin/Xorg"; } dd_save_text(dd, FILENAME_EXECUTABLE, exe); if (!(g_opts & OPT_x)) dd_set_no_owner(dd); dd_close(dd); notify_new_path(path); } free(path); }
/* returns number of errors */ unsigned abrt_oops_create_dump_dirs(GList *oops_list, const char *dump_location, const char *analyzer, int flags) { const int oops_cnt = g_list_length(oops_list); unsigned countdown = ABRT_OOPS_MAX_DUMPED_COUNT; /* do not report hundreds of oopses */ log_notice("Saving %u oopses as problem dirs", oops_cnt >= countdown ? countdown : oops_cnt); char *cmdline_str = xmalloc_fopen_fgetline_fclose("/proc/cmdline"); char *fips_enabled = xmalloc_fopen_fgetline_fclose("/proc/sys/crypto/fips_enabled"); char *proc_modules = xmalloc_open_read_close("/proc/modules", /*maxsize:*/ NULL); char *suspend_stats = xmalloc_open_read_close("/sys/kernel/debug/suspend_stats", /*maxsize:*/ NULL); time_t t = time(NULL); const char *iso_date = iso_date_string(&t); /* dump should be readable by all if we're run with -x */ uid_t my_euid = (uid_t)-1L; mode_t mode = DEFAULT_DUMP_DIR_MODE | S_IROTH; /* and readable only for the owner otherwise */ if (!(flags & ABRT_OOPS_WORLD_READABLE)) { mode = DEFAULT_DUMP_DIR_MODE; my_euid = geteuid(); } pid_t my_pid = getpid(); unsigned idx = 0; unsigned errors = 0; while (idx < oops_cnt) { char base[sizeof("oops-YYYY-MM-DD-hh:mm:ss-%lu-%lu") + 2 * sizeof(long)*3]; sprintf(base, "oops-%s-%lu-%lu", iso_date, (long)my_pid, (long)idx); char *path = concat_path_file(dump_location, base); struct dump_dir *dd = dd_create(path, /*uid:*/ my_euid, mode); if (dd) { dd_create_basic_files(dd, /*uid:*/ my_euid, NULL); abrt_oops_save_data_in_dump_dir(dd, (char*)g_list_nth_data(oops_list, idx++), proc_modules); dd_save_text(dd, FILENAME_ABRT_VERSION, VERSION); dd_save_text(dd, FILENAME_ANALYZER, "abrt-oops"); dd_save_text(dd, FILENAME_TYPE, "Kerneloops"); if (cmdline_str) dd_save_text(dd, FILENAME_CMDLINE, cmdline_str); if (proc_modules) dd_save_text(dd, "proc_modules", proc_modules); if (fips_enabled && strcmp(fips_enabled, "0") != 0) dd_save_text(dd, "fips_enabled", fips_enabled); if (suspend_stats) dd_save_text(dd, "suspend_stats", suspend_stats); dd_close(dd); notify_new_path(path); } else errors++; free(path); if (--countdown == 0) break; if (dd && (flags & ABRT_OOPS_THROTTLE_CREATION)) if (abrt_oops_signaled_sleep(1) > 0) break; } free(cmdline_str); free(proc_modules); free(fips_enabled); free(suspend_stats); return errors; }