summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2010-01-18 13:19:54 +0100
committerKarel Klic <kklic@redhat.com>2010-01-18 13:19:54 +0100
commit4267cbcc29781ddcac00e259dfe05f3a26fbc2ec (patch)
tree213e47138967f1e7af4ee9ff9a3f2ed861cb5815 /lib
parentb2d1bd9e4f387c5a014d3002d741f25421c37aac (diff)
parentb41833ed61f7b579d2a46b26d261616c21a6ae32 (diff)
downloadabrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.tar.gz
abrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.tar.xz
abrt-4267cbcc29781ddcac00e259dfe05f3a26fbc2ec.zip
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/Bugzilla.cpp141
-rw-r--r--lib/Plugins/CCpp.conf1
-rw-r--r--lib/Plugins/CCpp.cpp147
-rw-r--r--lib/Plugins/CCpp_sha1.cpp214
-rw-r--r--lib/Plugins/CCpp_sha1.h32
-rw-r--r--lib/Plugins/Catcut.conf2
-rw-r--r--lib/Plugins/Catcut.cpp59
-rw-r--r--lib/Plugins/FileTransfer.conf1
-rw-r--r--lib/Plugins/FileTransfer.cpp31
-rw-r--r--lib/Plugins/Firefox.cpp15
-rw-r--r--lib/Plugins/Kerneloops.conf1
-rw-r--r--lib/Plugins/KerneloopsScanner.cpp21
-rw-r--r--lib/Plugins/Logger.conf3
-rw-r--r--lib/Plugins/Mailx.conf1
-rw-r--r--lib/Plugins/Mailx.cpp33
-rw-r--r--lib/Plugins/Makefile.am12
-rw-r--r--lib/Plugins/Python.conf1
-rw-r--r--lib/Plugins/RunApp.cpp36
-rw-r--r--lib/Plugins/SOSreport.cpp7
-rw-r--r--lib/Plugins/SQLite3.conf1
-rw-r--r--lib/Plugins/SQLite3.cpp66
-rw-r--r--lib/Plugins/TicketUploader.cpp34
-rw-r--r--lib/Plugins/TicketUploader.h5
-rw-r--r--lib/Utils/CommLayerInner.cpp6
-rw-r--r--lib/Utils/DebugDump.cpp101
-rw-r--r--lib/Utils/DebugDump.h4
-rw-r--r--lib/Utils/Makefile.am2
-rw-r--r--lib/Utils/Polkit.cpp14
-rw-r--r--lib/Utils/abrt_dbus.h3
-rw-r--r--lib/Utils/abrt_xmlrpc.cpp16
-rw-r--r--lib/Utils/abrt_xmlrpc.h2
-rw-r--r--lib/Utils/copyfd.cpp4
-rw-r--r--lib/Utils/daemon.cpp4
-rw-r--r--lib/Utils/popen_and_save_output.cpp30
-rw-r--r--lib/Utils/spawn.cpp136
-rw-r--r--lib/Utils/xatonum.cpp4
-rw-r--r--lib/Utils/xfuncs.cpp14
37 files changed, 903 insertions, 301 deletions
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp
index 2d065f6..6f0f8d7 100644
--- a/lib/Plugins/Bugzilla.cpp
+++ b/lib/Plugins/Bugzilla.cpp
@@ -13,6 +13,9 @@
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
+/*
+ * TODO: npajkovs: better deallocation of xmlrpc value
+ */
/*
* Static namespace for xmlrpc stuff.
@@ -39,7 +42,8 @@ void ctx::login(const char* login, const char* passwd)
xmlrpc_env_init(&env);
xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s})", "login", login, "password", passwd);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.login", param, &result);
@@ -62,14 +66,16 @@ void ctx::logout()
xmlrpc_env_init(&env);
xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", "");
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.logout", param, &result);
xmlrpc_DECREF(param);
if (result)
xmlrpc_DECREF(result);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
}
bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
@@ -77,23 +83,36 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
xmlrpc_env env;
xmlrpc_env_init(&env);
+ // fails only when you write query. when it's done it never fails.
xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", to_string(bug_id).c_str());
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.getBug", param, &result);
- throw_if_xml_fault_occurred(&env);
+ // we don't need anymore xml structure for calling xmlrpc query(calls only once)
xmlrpc_DECREF(param);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* reporter_member = NULL;
xmlrpc_struct_find_value(&env, result, "reporter", &reporter_member);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ throw_xml_fault(&env);
+ }
if (reporter_member)
{
const char* reporter = NULL;
xmlrpc_read_string(&env, reporter_member, &reporter);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(reporter_member);
+ throw_xml_fault(&env);
+ }
bool eq = (strcmp(reporter, login) == 0);
free((void*)reporter);
@@ -107,7 +126,11 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
xmlrpc_value* cc_member = NULL;
xmlrpc_struct_find_value(&env, result, "cc", &cc_member);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ throw_xml_fault(&env);
+ }
if (cc_member)
{
@@ -117,11 +140,22 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
{
xmlrpc_value* item = NULL;
xmlrpc_array_read_item(&env, cc_member, i, &item); // Correct
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(cc_member);
+ throw_xml_fault(&env);
+ }
const char* cc = NULL;
xmlrpc_read_string(&env, item, &cc);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(cc_member);
+ xmlrpc_DECREF(item);
+ throw_xml_fault(&env);
+ }
bool eq = (strcmp(cc, login) == 0);
free((void*)cc);
@@ -145,15 +179,19 @@ void ctx::add_plus_one_cc(uint32_t bug_id, const char* login)
xmlrpc_env env;
xmlrpc_env_init(&env);
- xmlrpc_value* param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login);
- throw_if_xml_fault_occurred(&env);
+ // fails only when you write query. when it's done it never fails.
+ xmlrpc_value* param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.update", param, &result);
- throw_if_xml_fault_occurred(&env);
+ // we don't need anymore xml structure for calling xmlrpc query(calls only once)
+ xmlrpc_DECREF(param);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_DECREF(result);
- xmlrpc_DECREF(param);
}
int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID)
@@ -163,36 +201,61 @@ int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID)
std::string query = ssprintf("ALL component:\"%s\" statuswhiteboard:\"%s\"", component, UUID);
+ // fails only when you write query. when it's done it never fails.
xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s})", "quicksearch", query.c_str());
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.search", param, &result);
- throw_if_xml_fault_occurred(&env);
+ // we don't need anymore xml structure for calling xmlrpc query(calls only once)
xmlrpc_DECREF(param);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* bugs_member = NULL;
xmlrpc_struct_find_value(&env, result, "bugs", &bugs_member);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ throw_xml_fault(&env);
+ }
if (bugs_member)
{
// when array size is equal 0 that means no bug reported
uint32_t array_size = xmlrpc_array_size(&env, bugs_member);
- throw_if_xml_fault_occurred(&env);
- if (array_size == 0)
+ if (env.fault_occurred)
{
+ xmlrpc_DECREF(result);
xmlrpc_DECREF(bugs_member);
+ throw_xml_fault(&env);
+ }
+ else if (array_size == 0)
+ {
xmlrpc_DECREF(result);
+ xmlrpc_DECREF(bugs_member);
return -1;
}
xmlrpc_value* item = NULL;
xmlrpc_array_read_item(&env, bugs_member, 0, &item); // Correct
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(bugs_member);
+ throw_xml_fault(&env);
+ }
+
xmlrpc_value* bug = NULL;
xmlrpc_struct_find_value(&env, item, "bug_id", &bug);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(bugs_member);
+ xmlrpc_DECREF(item);
+ throw_xml_fault(&env);
+ }
if (bug)
{
@@ -236,6 +299,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport)
std::string version;
parse_release(release.c_str(), product, version);
+ // fails only when you write query. when it's done it never fails.
xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})",
"product", product.c_str(),
"component", component.c_str(),
@@ -245,27 +309,39 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport)
"status_whiteboard", status_whiteboard.c_str(),
"platform", arch.c_str()
);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.create", param, &result);
- throw_if_xml_fault_occurred(&env);
+ // we don't need anymore xml structure for calling xmlrpc query(calls only once)
+ xmlrpc_DECREF(param);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* id;
xmlrpc_struct_find_value(&env, result, "id", &id);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ throw_xml_fault(&env);
+ }
xmlrpc_int bug_id = -1;
if (id)
{
xmlrpc_read_int(&env, id, &bug_id);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(id);
+ throw_xml_fault(&env);
+ }
log("New bug id: %i", bug_id);
update_client(_("New bug id: %i"), bug_id);
}
xmlrpc_DECREF(result);
- xmlrpc_DECREF(param);
xmlrpc_DECREF(id);
return bug_id;
}
@@ -287,6 +363,7 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra
if (type == CD_ATT)
{
char *encoded64 = encode_base64(content.c_str(), content.length());
+ // fails only when you write query. when it's done it never fails.
xmlrpc_value* param = xmlrpc_build_value(&env, "(s{s:s,s:s,s:s,s:s})",
bug_id_str,
"description", ("File: " + filename).c_str(),
@@ -295,12 +372,18 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra
"data", encoded64
);
free(encoded64);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.addAttachment", param, &result);
- throw_if_xml_fault_occurred(&env);
- xmlrpc_DECREF(result);
+ // we don't need anymore xml structure for calling xmlrpc query(calls only once)
xmlrpc_DECREF(param);
+ if (env.fault_occurred)
+ {
+ xmlrpc_DECREF(result);
+ throw_xml_fault(&env);
+ }
+ xmlrpc_DECREF(result);
}
}
}
diff --git a/lib/Plugins/CCpp.conf b/lib/Plugins/CCpp.conf
index dfdbec8..153efb9 100644
--- a/lib/Plugins/CCpp.conf
+++ b/lib/Plugins/CCpp.conf
@@ -1,4 +1,5 @@
# Configuration file for CCpp hook and plugin
+Enabled = yes
# If you also want to dump file named "core"
# in crashed process' current dir, set to "yes"
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 1a01c01..e0db9cf 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -24,9 +24,8 @@
#include <sstream>
#include <set>
#include <iomanip>
-#include <nss.h>
-#include <sechash.h>
-#include <sysexits.h>
+//#include <nss.h>
+//#include <sechash.h>
#include "abrtlib.h"
#include "CCpp.h"
#include "ABRTException.h"
@@ -34,6 +33,8 @@
#include "CommLayerInner.h"
#include "Polkit.h"
+#include "CCpp_sha1.h"
+
using namespace std;
#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
@@ -54,11 +55,13 @@ CAnalyzerCCpp::CAnalyzerCCpp() :
static string CreateHash(const char *pInput)
{
- string ret;
- HASHContext* hc;
- unsigned char hash[SHA1_LENGTH];
unsigned int len;
+#if 0
+{
+ char hash_str[SHA1_LENGTH*2 + 1];
+ unsigned char hash[SHA1_LENGTH];
+ HASHContext *hc;
hc = HASH_Create(HASH_AlgSHA1);
if (!hc)
{
@@ -69,7 +72,6 @@ static string CreateHash(const char *pInput)
HASH_End(hc, hash, &len, sizeof(hash));
HASH_Destroy(hc);
- char hash_str[SHA1_LENGTH*2 + 1];
char *d = hash_str;
unsigned char *s = hash;
while (len)
@@ -80,6 +82,29 @@ static string CreateHash(const char *pInput)
len--;
}
*d = '\0';
+//log("hash1:%s str:'%s'", hash_str, pInput);
+}
+#endif
+
+ char hash_str[SHA1_RESULT_LEN*2 + 1];
+ unsigned char hash2[SHA1_RESULT_LEN];
+ sha1_ctx_t sha1ctx;
+ sha1_begin(&sha1ctx);
+ sha1_hash(pInput, strlen(pInput), &sha1ctx);
+ sha1_end(hash2, &sha1ctx);
+ len = SHA1_RESULT_LEN;
+
+ char *d = hash_str;
+ unsigned char *s = hash2;
+ while (len)
+ {
+ *d++ = "0123456789abcdef"[*s >> 4];
+ *d++ = "0123456789abcdef"[*s & 0xf];
+ s++;
+ len--;
+ }
+ *d = '\0';
+//log("hash2:%s str:'%s'", hash_str, pInput);
return hash_str;
}
@@ -99,54 +124,28 @@ static string concat_str_vector(char **strings)
/* Returns status. See `man 2 wait` for status information. */
static int ExecVP(char **pArgs, uid_t uid, int redirect_stderr, string& pOutput)
{
- int pipeout[2];
- pid_t child;
-
- xpipe(pipeout);
- child = fork();
- if (child == -1)
- {
- perror_msg_and_die("fork");
- }
- if (child == 0)
- {
- VERB1 log("Executing: %s", concat_str_vector(pArgs).c_str());
- close(pipeout[0]); /* read side of the pipe */
- xmove_fd(pipeout[1], STDOUT_FILENO);
- /* Make sure stdin is safely open to nothing */
- xmove_fd(xopen("/dev/null", O_RDONLY), STDIN_FILENO);
-
- struct passwd* pw = getpwuid(uid);
- gid_t gid = pw ? pw->pw_gid : uid;
- setgroups(1, &gid);
- xsetregid(gid, gid);
- xsetreuid(uid, uid);
- setsid();
-
- /* Nuke everything which may make setlocale() switch to non-POSIX locale:
- * we need to avoid having gdb output in some obscure language.
- */
- unsetenv("LANG");
- unsetenv("LC_ALL");
- unsetenv("LC_COLLATE");
- unsetenv("LC_CTYPE");
- unsetenv("LC_MESSAGES");
- unsetenv("LC_MONETARY");
- unsetenv("LC_NUMERIC");
- unsetenv("LC_TIME");
-
- if (redirect_stderr)
- {
- /* We want parent to see errors in the same stream */
- xdup2(STDOUT_FILENO, STDERR_FILENO);
- }
- execvp(pArgs[0], pArgs);
- /* VERB1 since sometimes we expect errors here */
- VERB1 perror_msg("Can't execute '%s'", pArgs[0]);
- exit(1);
- }
+ /* Nuke everything which may make setlocale() switch to non-POSIX locale:
+ * we need to avoid having gdb output in some obscure language.
+ */
+ static const char *const unsetenv_vec[] = {
+ "LANG",
+ "LC_ALL",
+ "LC_COLLATE",
+ "LC_CTYPE",
+ "LC_MESSAGES",
+ "LC_MONETARY",
+ "LC_NUMERIC",
+ "LC_TIME",
+ NULL
+ };
+
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID | EXECFLG_QUIET;
+ if (redirect_stderr)
+ flags |= EXECFLG_ERR2OUT;
+ VERB1 flags &= ~EXECFLG_QUIET;
- close(pipeout[1]); /* write side of the pipe */
+ int pipeout[2];
+ pid_t child = fork_execv_on_steroids(flags, pArgs, pipeout, (char**)unsetenv_vec, /*dir:*/ NULL, uid);
int r;
char buff[1024];
@@ -155,8 +154,8 @@ static int ExecVP(char **pArgs, uid_t uid, int redirect_stderr, string& pOutput)
buff[r] = '\0';
pOutput += buff;
}
-
close(pipeout[0]);
+
int status;
waitpid(child, &status, 0); /* prevent having zombie child process */
@@ -379,6 +378,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir,
int pipeout[2]; //TODO: can we use ExecVP?
xpipe(pipeout);
+ fflush(NULL);
pid_t child = fork();
if (child < 0)
{
@@ -394,7 +394,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir,
char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir);
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
- char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL));
+ char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu", (long)getpid(), (long)time(NULL));
/* log() goes to stderr/syslog, it's ok to use it here */
VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs);
/* We want parent to see errors in the same stream */
@@ -545,6 +545,8 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
{
log(_("Getting global universal unique identification..."));
+//TODO: convert to fork_execv_on_steroids(), nuke static concat_str_vector
+
string backtrace_path = concat_path_file(pDebugDumpDir, FILENAME_BACKTRACE);
string executable;
string package;
@@ -574,6 +576,8 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
int pipeout[2];
xpipe(pipeout); /* stdout of abrt-backtrace */
+
+ fflush(NULL);
pid_t child = fork();
if (child == -1)
perror_msg_and_die("fork");
@@ -617,13 +621,29 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
{
perror_msg("abrt-backtrace not executed properly, "
"status: %x signal: %d", status, WIFSIGNALED(status));
- } else
+ }
+ else
{
int exit_status = WEXITSTATUS(status);
- if (exit_status != 0)
+ if (exit_status == 79) /* EX_PARSINGFAILED */
{
+ /* abrt-backtrace returns alternative backtrace
+ representation in this case, so everything will work
+ as expected except worse duplication detection */
+ log_msg("abrt-backtrace failed to parse the backtrace");
+ }
+ else if (exit_status == 80) /* EX_THREADDETECTIONFAILED */
+ {
+ /* abrt-backtrace returns backtrace with all threads
+ in this case, so everything will work as expected
+ except worse duplication detection */
+ log_msg("abrt-backtrace failed to determine crash frame");
+ }
+ else if (exit_status != 0)
+ {
+ /* this is unexpected problem and it should be investigated */
error_msg("abrt-backtrace run failed, exit value: %d",
- exit_status);
+ exit_status);
}
}
@@ -635,8 +655,9 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
return CreateHash(hash_base.c_str());
}
-static bool DebuginfoCheckPolkit(int uid)
+static bool DebuginfoCheckPolkit(uid_t uid)
{
+ fflush(NULL);
int child_pid = fork();
if (child_pid < 0)
{
@@ -653,8 +674,10 @@ static bool DebuginfoCheckPolkit(int uid)
//parent
int status;
- if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0)
- {
+ if (waitpid(child_pid, &status, 0) > 0
+ && WIFEXITED(status)
+ && WEXITSTATUS(status) == 0
+ ) {
return true; //authorization OK
}
log("UID %d is not authorized to install debuginfos", uid);
diff --git a/lib/Plugins/CCpp_sha1.cpp b/lib/Plugins/CCpp_sha1.cpp
new file mode 100644
index 0000000..86a9e83
--- /dev/null
+++ b/lib/Plugins/CCpp_sha1.cpp
@@ -0,0 +1,214 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Based on shasum from http://www.netsw.org/crypto/hash/
+ * Majorly hacked up to use Dr Brian Gladman's sha1 code
+ *
+ * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ * Copyright (C) 2003 Glenn L. McGrath
+ * Copyright (C) 2003 Erik Andersen
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * ---------------------------------------------------------------------------
+ * Issue Date: 10/11/2002
+ *
+ * This is a byte oriented version of SHA1 that operates on arrays of bytes
+ * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
+ *
+ * ---------------------------------------------------------------------------
+ */
+#include "abrtlib.h"
+#include "CCpp_sha1.h"
+
+#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__
+# define SHA1_BIG_ENDIAN 1
+# define SHA1_LITTLE_ENDIAN 0
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define SHA1_BIG_ENDIAN 1
+# define SHA1_LITTLE_ENDIAN 0
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define SHA1_BIG_ENDIAN 0
+# define SHA1_LITTLE_ENDIAN 1
+#else
+# error "Can't determine endianness"
+#endif
+
+
+#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
+/* for sha512: */
+#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n))))
+#if SHA1_LITTLE_ENDIAN
+static inline uint64_t hton64(uint64_t v)
+{
+ return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32);
+}
+#else
+#define hton64(v) (v)
+#endif
+#define ntoh64(v) hton64(v)
+
+/* To check alignment gcc has an appropriate operator. Other
+ compilers don't. */
+#if defined(__GNUC__) && __GNUC__ >= 2
+# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0)
+#else
+# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0)
+#endif
+
+
+/* Some arch headers have conflicting defines */
+#undef ch
+#undef parity
+#undef maj
+#undef rnd
+
+static void sha1_process_block64(sha1_ctx_t *ctx)
+{
+ unsigned t;
+ uint32_t W[80], a, b, c, d, e;
+ const uint32_t *words = (uint32_t*) ctx->wbuffer;
+
+ for (t = 0; t < 16; ++t) {
+ W[t] = ntohl(*words);
+ words++;
+ }
+
+ for (/*t = 16*/; t < 80; ++t) {
+ uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
+ W[t] = rotl32(T, 1);
+ }
+
+ a = ctx->hash[0];
+ b = ctx->hash[1];
+ c = ctx->hash[2];
+ d = ctx->hash[3];
+ e = ctx->hash[4];
+
+/* Reverse byte order in 32-bit words */
+#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define parity(x,y,z) ((x) ^ (y) ^ (z))
+#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
+/* A normal version as set out in the FIPS. This version uses */
+/* partial loop unrolling and is optimised for the Pentium 4 */
+#define rnd(f,k) \
+ do { \
+ uint32_t T = a; \
+ a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \
+ e = d; \
+ d = c; \
+ c = rotl32(b, 30); \
+ b = T; \
+ } while (0)
+
+ for (t = 0; t < 20; ++t)
+ rnd(ch, 0x5a827999);
+
+ for (/*t = 20*/; t < 40; ++t)
+ rnd(parity, 0x6ed9eba1);
+
+ for (/*t = 40*/; t < 60; ++t)
+ rnd(maj, 0x8f1bbcdc);
+
+ for (/*t = 60*/; t < 80; ++t)
+ rnd(parity, 0xca62c1d6);
+#undef ch
+#undef parity
+#undef maj
+#undef rnd
+
+ ctx->hash[0] += a;
+ ctx->hash[1] += b;
+ ctx->hash[2] += c;
+ ctx->hash[3] += d;
+ ctx->hash[4] += e;
+}
+
+void sha1_begin(sha1_ctx_t *ctx)
+{
+ ctx->hash[0] = 0x67452301;
+ ctx->hash[1] = 0xefcdab89;
+ ctx->hash[2] = 0x98badcfe;
+ ctx->hash[3] = 0x10325476;
+ ctx->hash[4] = 0xc3d2e1f0;
+ ctx->total64 = 0;
+ ctx->process_block = sha1_process_block64;
+}
+
+static const uint32_t init256[] = {
+ 0x6a09e667,
+ 0xbb67ae85,
+ 0x3c6ef372,
+ 0xa54ff53a,
+ 0x510e527f,
+ 0x9b05688c,
+ 0x1f83d9ab,
+ 0x5be0cd19
+};
+static const uint32_t init512_lo[] = {
+ 0xf3bcc908,
+ 0x84caa73b,
+ 0xfe94f82b,
+ 0x5f1d36f1,
+ 0xade682d1,
+ 0x2b3e6c1f,
+ 0xfb41bd6b,
+ 0x137e2179
+};
+
+/* Used also for sha256 */
+void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx)
+{
+ unsigned in_buf = ctx->total64 & 63;
+ unsigned add = 64 - in_buf;
+
+ ctx->total64 += len;
+
+ while (len >= add) { /* transfer whole blocks while possible */
+ memcpy(ctx->wbuffer + in_buf, buffer, add);
+ buffer = (const char *)buffer + add;
+ len -= add;
+ add = 64;
+ in_buf = 0;
+ ctx->process_block(ctx);
+ }
+
+ memcpy(ctx->wbuffer + in_buf, buffer, len);
+}
+
+/* Used also for sha256 */
+void sha1_end(void *resbuf, sha1_ctx_t *ctx)
+{
+ unsigned pad, in_buf;
+
+ in_buf = ctx->total64 & 63;
+ /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
+ ctx->wbuffer[in_buf++] = 0x80;
+
+ /* This loop iterates either once or twice, no more, no less */
+ while (1) {
+ pad = 64 - in_buf;
+ memset(ctx->wbuffer + in_buf, 0, pad);
+ in_buf = 0;
+ /* Do we have enough space for the length count? */
+ if (pad >= 8) {
+ /* Store the 64-bit counter of bits in the buffer in BE format */
+ uint64_t t = ctx->total64 << 3;
+ t = hton64(t);
+ /* wbuffer is suitably aligned for this */
+ *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
+ }
+ ctx->process_block(ctx);
+ if (pad >= 8)
+ break;
+ }
+
+ in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8;
+ /* This way we do not impose alignment constraints on resbuf: */
+ if (SHA1_LITTLE_ENDIAN) {
+ unsigned i;
+ for (i = 0; i < in_buf; ++i)
+ ctx->hash[i] = htonl(ctx->hash[i]);
+ }
+ memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf);
+}
diff --git a/lib/Plugins/CCpp_sha1.h b/lib/Plugins/CCpp_sha1.h
new file mode 100644
index 0000000..abadfd9
--- /dev/null
+++ b/lib/Plugins/CCpp_sha1.h
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Based on shasum from http://www.netsw.org/crypto/hash/
+ * Majorly hacked up to use Dr Brian Gladman's sha1 code
+ *
+ * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ * Copyright (C) 2003 Glenn L. McGrath
+ * Copyright (C) 2003 Erik Andersen
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * ---------------------------------------------------------------------------
+ * Issue Date: 10/11/2002
+ *
+ * This is a byte oriented version of SHA1 that operates on arrays of bytes
+ * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+#define SHA1_RESULT_LEN (5 * 4)
+
+typedef struct sha1_ctx_t {
+ uint32_t hash[8]; /* 5, +3 elements for sha256 */
+ uint64_t total64;
+ uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
+ void (*process_block)(struct sha1_ctx_t*);
+} sha1_ctx_t;
+
+void sha1_begin(sha1_ctx_t *ctx);
+void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx);
+void sha1_end(void *resbuf, sha1_ctx_t *ctx);
diff --git a/lib/Plugins/Catcut.conf b/lib/Plugins/Catcut.conf
index 456d7f8..a0249fd 100644
--- a/lib/Plugins/Catcut.conf
+++ b/lib/Plugins/Catcut.conf
@@ -1,3 +1,4 @@
+Enabled=1
# Catcut URL
CatcutURL = http://127.0.0.1:8080/catcut/xmlrpc
# yes means that ssl certificates will not be checked
@@ -6,3 +7,4 @@ NoSSLVerify = no
Login = gavin
# your password
Password = junk
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp
index a56015d..27b868d 100644
--- a/lib/Plugins/Catcut.cpp
+++ b/lib/Plugins/Catcut.cpp
@@ -13,7 +13,7 @@ using namespace std;
static int
-put_stream(const char *pURL, FILE* f, size_t content_length)
+put_stream(const char *pURL, FILE* f, off_t content_length)
{
CURL* curl = xcurl_easy_init();
/* enable uploading */
@@ -22,8 +22,8 @@ put_stream(const char *pURL, FILE* f, size_t content_length)
curl_easy_setopt(curl, CURLOPT_URL, pURL);
/* file handle: passed to the default callback, it will fread() it */
curl_easy_setopt(curl, CURLOPT_READDATA, f);
- /* get file size */
- curl_easy_setopt(curl, CURLOPT_INFILESIZE, content_length);
+ /* file size */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)content_length);
/* everything is done here; result 0 means success */
int result = curl_easy_perform(curl);
/* goodbye */
@@ -43,9 +43,9 @@ send_string(const char *pURL,
return;
}
+ size_t content_length = strlen(pContent);
while (1)
{
- int content_length = strlen(pContent);
FILE* f = fmemopen((void*)pContent, content_length, "r");
if (!f)
{
@@ -53,7 +53,7 @@ send_string(const char *pURL,
}
int result = put_stream(pURL, f, content_length);
fclose(f);
- if (!result)
+ if (result == 0)
return;
update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result));
if (--retryCount <= 0)
@@ -88,10 +88,9 @@ send_file(const char *pURL,
}
struct stat buf;
fstat(fileno(f), &buf); /* can't fail */
- int content_length = buf.st_size;
- int result = put_stream(pURL, f, content_length);
+ int result = put_stream(pURL, f, buf.st_size);
fclose(f);
- if (!result)
+ if (result == 0)
return;
update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result));
if (--retryCount <= 0)
@@ -122,6 +121,7 @@ resolve_relative_url(const char *url, const char *base)
}
const char *end_of_protocol = strchr(base, ':');
+//TODO: why is this safe?!!
string protocol(base, end_of_protocol - base);
end_of_protocol += 3; /* skip "://" */
@@ -167,11 +167,14 @@ struct_find_int(xmlrpc_env* env, xmlrpc_value* result,
{
xmlrpc_value* an_xmlrpc_value;
xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value);
- throw_if_xml_fault_occurred(env);
+ if (env->fault_occurred)
+ throw_xml_fault(env);
+
if (an_xmlrpc_value)
{
xmlrpc_read_int(env, an_xmlrpc_value, &value);
- throw_if_xml_fault_occurred(env);
+ if (env->fault_occurred)
+ throw_xml_fault(env);
xmlrpc_DECREF(an_xmlrpc_value);
return true;
}
@@ -184,12 +187,14 @@ struct_find_string(xmlrpc_env* env, xmlrpc_value* result,
{
xmlrpc_value* an_xmlrpc_value;
xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value);
- throw_if_xml_fault_occurred(env);
+ if (env->fault_occurred)
+ throw_xml_fault(env);
if (an_xmlrpc_value)
{
const char* value_s;
xmlrpc_read_string(env, an_xmlrpc_value, &value_s);
- throw_if_xml_fault_occurred(env);
+ if (env->fault_occurred)
+ throw_xml_fault(env);
value = value_s;
xmlrpc_DECREF(an_xmlrpc_value);
free((void*)value_s);
@@ -228,20 +233,24 @@ ctx::login(const char* login, const char* passwd)
xmlrpc_env_init(&env);
xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.auth", param, &result);
xmlrpc_DECREF(param);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value *cookie_xml;
const char *cookie;
string cookie_str;
xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_read_string(&env, cookie_xml, &cookie);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
cookie_str = cookie;
/* xmlrpc_read_string returns *malloc'ed ptr*.
* doc is not very clear on it, but I looked in xmlrpc sources. */
@@ -284,20 +293,24 @@ ctx::new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport)
"status_whiteboard", status_whiteboard.c_str(),
"platform", arch.c_str()
);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value *result;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.createTicket", param, &result);
xmlrpc_DECREF(param);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value *bug_id_xml;
const char *bug_id;
string bug_id_str;
xmlrpc_struct_find_value(&env, result, "ticket", &bug_id_xml);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_read_string(&env, bug_id_xml, &bug_id);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
bug_id_str = bug_id;
log("New bug id: %s", bug_id);
update_client(_("New bug id: %s"), bug_id);
@@ -321,12 +334,14 @@ ctx::request_upload(const char* auth_cookie, const char* pTicketName,
pTicketName,
fileName,
description);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
xmlrpc_value* result = NULL;
xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.requestUpload", param, &result);
xmlrpc_DECREF(param);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
string URL;
bool has_URL = struct_find_string(&env, result, "uri", URL);
diff --git a/lib/Plugins/FileTransfer.conf b/lib/Plugins/FileTransfer.conf
index 75e5671..c92eaee 100644
--- a/lib/Plugins/FileTransfer.conf
+++ b/lib/Plugins/FileTransfer.conf
@@ -17,3 +17,4 @@ RetryCount = 3
#how long we wait between we retry the upload (in seconds)
RetryDelay = 20
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp
index 60e1e66..b08ecd5 100644
--- a/lib/Plugins/FileTransfer.cpp
+++ b/lib/Plugins/FileTransfer.cpp
@@ -80,11 +80,7 @@ void CFileTransfer::SendFile(const char *pURL, const char *pFilename)
{
throw CABRTException(EXCEP_PLUGIN, "Can't open archive file '%s'", pFilename);
}
- if (fstat(fileno(f), &buf) == -1)
- {
- fclose(f);
- throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename);
- }
+ fstat(fileno(f), &buf); /* never fails */
curl = xcurl_easy_init();
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
@@ -92,7 +88,7 @@ void CFileTransfer::SendFile(const char *pURL, const char *pFilename)
curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str());
/* FILE handle: passed to the default callback, it will fread() it */
curl_easy_setopt(curl, CURLOPT_READDATA, f);
- curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size);
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)buf.st_size);
/* everything is done here; result 0 means success */
int result = curl_easy_perform(curl);
curl_easy_cleanup(curl);
@@ -110,13 +106,11 @@ parameter "something" to each filename,
now used in create_zip, but can be useful for some future
archivers as well
*/
-static void traverse_directory(const char * directory, void * something,
- void (*func)(void *, const char *) )
+static void traverse_directory(const char *directory, void *something,
+ void (*func)(void *, const char *))
{
- DIR * dp;
- struct dirent * dirp;
- char complete_name[BUFSIZ];
- char * end;
+ DIR *dp;
+ struct dirent *dirp;
dp = opendir(directory);
if (dp == NULL)
@@ -127,14 +121,8 @@ static void traverse_directory(const char * directory, void * something,
{
if (is_regular_file(dirp, directory))
{
- end = stpcpy(complete_name, directory);
- if (end[-1] != '/')
- {
- *end++ = '/';
- }
- end = stpcpy(end, dirp->d_name);
-
- func(something, complete_name);
+ string complete_name = concat_path_file(directory, dirp->d_name);
+ func(something, complete_name.c_str());
}
}
closedir(dp);
@@ -189,6 +177,7 @@ static void create_targz(const char * archive_name, const char * directory)
f = fopen(name_without_gz, "r");
if (f == NULL)
{
+//TODO: we leak uncompressed tar file on disk??
free(name_without_gz);
return;
}
@@ -234,6 +223,7 @@ static void create_tarbz2(const char * archive_name, const char * directory)
f = fopen(archive_name, "w");
if (f == NULL)
{
+//TODO: we leak uncompressed tar file on disk??
close(tarFD);
free(name_without_bz2);
return;
@@ -320,6 +310,7 @@ void CFileTransfer::Run(const char *pActionDir, const char *pArgs)
else if (strcmp(pArgs, "one") == 0)
{
/* just send one archive */
+//TODO: where are we creating it??!! In cwd, which may well be / ??!!!
string archivename = ssprintf("%s-%s%s", hostname, DirBase(pActionDir).c_str(), m_sArchiveType.c_str());
try
{
diff --git a/lib/Plugins/Firefox.cpp b/lib/Plugins/Firefox.cpp
index 92ef4e5..d980755 100644
--- a/lib/Plugins/Firefox.cpp
+++ b/lib/Plugins/Firefox.cpp
@@ -99,6 +99,8 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
pid_t child;
xpipe(pipeout);
+
+ fflush(NULL);
child = fork();
if (child == -1)
{
@@ -549,6 +551,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
xpipe(pipein);
xpipe(pipeout);
+ fflush(NULL);
pid_t child = fork();
if (child < 0)
{
@@ -673,6 +676,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
int pipeout[2]; //TODO: can we use ExecVP?
xpipe(pipeout);
+ fflush(NULL);
pid_t child = fork();
if (child < 0)
{
@@ -692,7 +696,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids)
char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir);
/* SELinux guys are not happy with /tmp, using /var/run/abrt */
- char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL));
+ char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu", (long)getpid(), (long)time(NULL));
/* log() goes to stderr/syslog, it's ok to use it here */
VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR);
execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR, NULL);
@@ -839,8 +843,9 @@ std::string CAnalyzerFirefox::GetGlobalUUID(const char *pDebugDumpDir)
return CreateHash(package + executable + independentBacktrace);
}
-static bool DebuginfoCheckPolkit(int uid)
+static bool DebuginfoCheckPolkit(uid_t uid)
{
+ fflush(NULL);
int child_pid = fork();
if (child_pid < 0)
{
@@ -857,8 +862,10 @@ static bool DebuginfoCheckPolkit(int uid)
//parent
int status;
- if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0)
- {
+ if (waitpid(child_pid, &status, 0) > 0
+ && WIFEXITED(status)
+ && WEXITSTATUS(status) == 0
+ ) {
return true; //authorization OK
}
log("UID %d is not authorized to install debuginfos", uid);
diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/Kerneloops.conf
index 5623596..1db2436 100644
--- a/lib/Plugins/Kerneloops.conf
+++ b/lib/Plugins/Kerneloops.conf
@@ -15,3 +15,4 @@ SysLogFile = /var/log/messages
# KerneloopsReporter configuration
##################################
SubmitURL = http://submit.kerneloops.org/submitoops.php
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp
index 128e083..1bb45ab 100644
--- a/lib/Plugins/KerneloopsScanner.cpp
+++ b/lib/Plugins/KerneloopsScanner.cpp
@@ -99,13 +99,14 @@ void CKerneloopsScanner::SaveOopsToDebugDump()
*second_line++ = '\0';
try
{
- CDebugDump debugDump;
- debugDump.Create(path, 0);
- debugDump.SaveText(FILENAME_ANALYZER, "Kerneloops");
- debugDump.SaveText(FILENAME_EXECUTABLE, "kernel");
- debugDump.SaveText(FILENAME_KERNEL, first_line);
- debugDump.SaveText(FILENAME_PACKAGE, "not_applicable");
- debugDump.SaveText(FILENAME_KERNELOOPS, second_line);
+ CDebugDump dd;
+ dd.Create(path, 0);
+ dd.SaveText(FILENAME_ANALYZER, "Kerneloops");
+ dd.SaveText(FILENAME_EXECUTABLE, "kernel");
+ dd.SaveText(FILENAME_KERNEL, first_line);
+ dd.SaveText(FILENAME_PACKAGE, "not_applicable");
+ dd.SaveText(FILENAME_CMDLINE, "not_applicable");
+ dd.SaveText(FILENAME_KERNELOOPS, second_line);
}
catch (CABRTException& e)
{
@@ -121,7 +122,7 @@ int CKerneloopsScanner::ScanDmesg()
int cnt_FoundOopses;
char *buffer;
- int pagesz = getpagesize();
+ long pagesz = sysconf(_SC_PAGESIZE);
buffer = (char*)xzalloc(pagesz + 1);
@@ -147,8 +148,10 @@ int CKerneloopsScanner::ScanSysLogFile(const char *filename)
if (fd < 0)
return 0;
statb.st_size = 0; /* paranoia */
- if (fstat(fd, &statb) != 0 || statb.st_size < 1)
+ if (fstat(fd, &statb) != 0 || statb.st_size < 1) {
+ close(fd);
return 0;
+ }
/*
* in theory there's a race here, since someone could spew
diff --git a/lib/Plugins/Logger.conf b/lib/Plugins/Logger.conf
index 901b3cf..39ba47e 100644
--- a/lib/Plugins/Logger.conf
+++ b/lib/Plugins/Logger.conf
@@ -2,4 +2,5 @@
LogPath = /var/log/abrt-logger
-AppendLogs = yes \ No newline at end of file
+AppendLogs = yes
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/Mailx.conf b/lib/Plugins/Mailx.conf
index 44c1d18..de19709 100644
--- a/lib/Plugins/Mailx.conf
+++ b/lib/Plugins/Mailx.conf
@@ -13,3 +13,4 @@ EmailTo = root@localhost
# Warning! enabling this may cause sending a lot of MB via email
SendBinaryData = no
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp
index 70eddb8..df33e84 100644
--- a/lib/Plugins/Mailx.cpp
+++ b/lib/Plugins/Mailx.cpp
@@ -39,33 +39,16 @@ CMailx::CMailx() :
static void exec_and_feed_input(uid_t uid, const char* pText, char **pArgs)
{
int pipein[2];
- pid_t child;
- xpipe(pipein);
- child = fork();
- if (child == -1)
- {
- close(pipein[0]);
- close(pipein[1]);
- throw CABRTException(EXCEP_PLUGIN, "Can't fork");
- }
- if (child == 0)
- {
- close(pipein[1]);
- xmove_fd(pipein[0], STDIN_FILENO);
-
- struct passwd* pw = getpwuid(uid);
- gid_t gid = pw ? pw->pw_gid : uid;
- setgroups(1, &gid);
- xsetregid(gid, gid);
- xsetreuid(uid, uid);
-
- execvp(pArgs[0], pArgs);
- exit(1); /* exec failed */
- }
+ pid_t child = fork_execv_on_steroids(
+ EXECFLG_INPUT | EXECFLG_QUIET | EXECFLG_SETGUID,
+ pArgs,
+ pipein,
+ /*unsetenv_vec:*/ NULL,
+ /*dir:*/ NULL,
+ uid);
- close(pipein[0]);
- safe_write(pipein[1], pText, strlen(pText));
+ full_write(pipein[1], pText, strlen(pText));
close(pipein[1]);
waitpid(child, NULL, 0); /* wait for command completion */
diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am
index 2e5ee38..df35416 100644
--- a/lib/Plugins/Makefile.am
+++ b/lib/Plugins/Makefile.am
@@ -32,7 +32,8 @@ dist_pluginsconf_DATA = \
Bugzilla.conf \
Catcut.conf \
TicketUploader.conf \
- FileTransfer.conf
+ FileTransfer.conf \
+ Python.conf
man_MANS = abrt-FileTransfer.7 abrt-Bugzilla.7 abrt-KerneloopsReporter.7 \
abrt-KerneloopsScanner.7 abrt-Logger.7 abrt-Mailx.7 abrt-plugins.7 \
@@ -51,14 +52,13 @@ install-data-hook: $(DESTDIR)/$(DEBUG_INFO_DIR)
$(DESTDIR)$(sysconfdir)/abrt/plugins/Logger.conf
# CCpp
-libCCpp_la_SOURCES = CCpp.cpp CCpp.h
+libCCpp_la_SOURCES = CCpp.cpp CCpp.h CCpp_sha1.cpp CCpp_sha1.h
libCCpp_la_LDFLAGS = -avoid-version
-libCCpp_la_LIBADD = $(NSS_LIBS)
+#libCCpp_la_LIBADD =
libCCpp_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils \
-DCCPP_HOOK_PATH=\"${libexecdir}/abrt-hook-ccpp\" \
-DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
- -DLOCALSTATEDIR='"$(localstatedir)"' \
- $(NSS_CFLAGS)
+ -DLOCALSTATEDIR='"$(localstatedir)"'
# Firefox - disabled for now
@@ -133,7 +133,7 @@ libTicketUploader_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils $(CUR
libPython_la_SOURCES = Python.h Python.cpp
#libPython_la_LIBADD = $(NSS_LIBS)
libPython_la_LDFLAGS = -avoid-version
-libPython_la_CPPFLAGS = $(NSS_CFLAGS) -I$(srcdir)/../../inc -I$(srcdir)/../Utils
+libPython_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils
# FileTrasfer
libFileTransfer_la_SOURCES = FileTransfer.cpp FileTransfer.h
diff --git a/lib/Plugins/Python.conf b/lib/Plugins/Python.conf
new file mode 100644
index 0000000..75d2229
--- /dev/null
+++ b/lib/Plugins/Python.conf
@@ -0,0 +1 @@
+Enabled = yes \ No newline at end of file
diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp
index f7cbc01..e2147e2 100644
--- a/lib/Plugins/RunApp.cpp
+++ b/lib/Plugins/RunApp.cpp
@@ -33,50 +33,38 @@ using namespace std;
void CActionRunApp::Run(const char *pActionDir, const char *pArgs)
{
- /* Don't update_client() - actions run at crash time */
+ /* Don't update_client() - actions run at crash time, there is no client
+ * to talk to at that point */
log("RunApp('%s','%s')", pActionDir, pArgs);
vector_string_t args;
parse_args(pArgs, args, '"');
+ if (args.size() <= COMMAND)
+ {
+ return;
+ }
const char *cmd = args[COMMAND].c_str();
if (!cmd[0])
{
return;
}
-//FIXME: need to be able to escape " in .conf
- /* Chdir to the dump dir. Command can analyze component and such.
+ /* NB: we chdir to the dump dir. Command can analyze component and such.
* Example:
* test x"`cat component`" = x"xorg-x11-apps" && cp /var/log/Xorg.0.log .
*/
-//Can do it using chdir() in child if we'd open-code popen
- string cd_and_cmd = ssprintf("cd '%s'; %s", pActionDir, cmd);
- VERB1 log("RunApp: executing '%s'", cd_and_cmd.c_str());
- FILE *fp = popen(cd_and_cmd.c_str(), "r");
- if (fp == NULL)
- {
- /* Happens only on resource starvation (fork fails or out-of-mem) */
- return;
- }
-
-//FIXME: RunApp("gzip -9 </var/log/Xorg.0.log", "Xorg.0.log.gz") fails
-//since we mangle NULs.
- string output;
- char line[1024];
- while (fgets(line, 1024, fp) != NULL)
- {
- if (args.size() > FILENAME)
- output += line;
- }
- pclose(fp);
+ size_t cmd_out_size;
+ char *cmd_out = run_in_shell_and_save_output(/*flags:*/ 0, cmd, pActionDir, &cmd_out_size);
if (args.size() > FILENAME)
{
CDebugDump dd;
dd.Open(pActionDir);
- dd.SaveText(args[FILENAME].c_str(), output.c_str());
+ dd.SaveBinary(args[FILENAME].c_str(), cmd_out, cmd_out_size);
}
+
+ free(cmd_out);
}
PLUGIN_INFO(ACTION,
diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp
index 6f23165..2576910 100644
--- a/lib/Plugins/SOSreport.cpp
+++ b/lib/Plugins/SOSreport.cpp
@@ -91,7 +91,9 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs)
update_client(_("running sosreport: %s"), command.c_str());
std::string output = command;
output += '\n';
- output += popen_and_save_output(command.c_str());
+ char *command_out = run_in_shell_and_save_output(/*flags:*/ 0, command.c_str(), /*dir:*/ NULL, /*size_p:*/ NULL);
+ output += command_out;
+ free(command_out);
update_client(_("done running sosreport"));
std::string sosreport_filename = ParseFilename(output);
@@ -101,8 +103,9 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs)
dd.Open(pActionDir);
//Not useful
//dd.SaveText("sosreportoutput", output);
- if (copy_file(sosreport_filename.c_str(), sosreport_dd_filename.c_str()) < 0)
+ if (copy_file(sosreport_filename.c_str(), sosreport_dd_filename.c_str(), 0644) < 0)
{
+ dd.Close();
throw CABRTException(EXCEP_PLUGIN,
"Can't copy '%s' to '%s'",
sosreport_filename.c_str(),
diff --git a/lib/Plugins/SQLite3.conf b/lib/Plugins/SQLite3.conf
index 3773c8f..2053642 100644
--- a/lib/Plugins/SQLite3.conf
+++ b/lib/Plugins/SQLite3.conf
@@ -1,3 +1,4 @@
# Configuration file for database plugin SQLite3
+
# DB path
DBPath = /var/cache/abrt/abrt-db
diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp
index 1979f24..ffcf05f 100644
--- a/lib/Plugins/SQLite3.cpp
+++ b/lib/Plugins/SQLite3.cpp
@@ -90,6 +90,26 @@ static const char *const upate_sql_commands[][ABRT_TABLE_VERSION + 1] = {
},
};
+
+/* Is this string safe wrt SQL injection?
+ * PHP's mysql_real_escape_string() treats \, ', ", \x00, \n, \r, and \x1a as special.
+ * We are a bit more paranoid and disallow any control chars.
+ */
+static bool is_string_safe(const char *str)
+{
+ const char *p = str;
+ while (*p)
+ {
+ if ((unsigned char)(*p) < ' ' || strchr("\\\"\'", *p))
+ {
+ error_msg("Probable SQL injection: '%s'", str);
+ return false;
+ }
+ p++;
+ }
+ return true;
+}
+
static void get_table(vector_database_rows_t& pTable,
sqlite3 *db, const char *fmt, ...)
{
@@ -308,6 +328,14 @@ void CSQLite3::Insert_or_Update(const char *pUUID,
const char *pDebugDumpPath,
const char *pTime)
{
+ if (!is_string_safe(pUUID)
+ || !is_string_safe(pUID)
+ || !is_string_safe(pDebugDumpPath)
+ || !is_string_safe(pTime)
+ ) {
+ return;
+ }
+
if (!exists_uuid_uid(m_pDB, pUUID, pUID))
{
execute_sql(m_pDB,
@@ -336,20 +364,26 @@ void CSQLite3::Insert_or_Update(const char *pUUID,
void CSQLite3::DeleteRow(const char *pUUID, const char *pUID)
{
+ if (!is_string_safe(pUUID)
+ || !is_string_safe(pUID)
+ ) {
+ return;
+ }
+
if (pUID[0] == '0' && !pUID[1])
{
execute_sql(m_pDB,
"DELETE FROM "ABRT_TABLE" "
"WHERE "COL_UUID" = '%s';",
- pUUID, pUID
+ pUUID
);
}
else if (exists_uuid_uid(m_pDB, pUUID, pUID))
{
execute_sql(m_pDB, "DELETE FROM "ABRT_TABLE" "
- "WHERE "COL_UUID" = '%s' "
- "AND ("COL_UID" = '%s' OR "COL_UID" = '-1');",
- pUUID, pUID
+ "WHERE "COL_UUID" = '%s' "
+ "AND ("COL_UID" = '%s' OR "COL_UID" = '-1');",
+ pUUID, pUID
);
}
else
@@ -360,6 +394,11 @@ void CSQLite3::DeleteRow(const char *pUUID, const char *pUID)
void CSQLite3::DeleteRows_by_dir(const char *dump_dir)
{
+ if (!is_string_safe(dump_dir))
+ {
+ return;
+ }
+
execute_sql(m_pDB,
"DELETE FROM "ABRT_TABLE" "
"WHERE "COL_DEBUG_DUMP_PATH" = '%s'",
@@ -369,6 +408,13 @@ void CSQLite3::DeleteRows_by_dir(const char *dump_dir)
void CSQLite3::SetReported(const char *pUUID, const char *pUID, const char *pMessage)
{
+ if (!is_string_safe(pUUID)
+ || !is_string_safe(pUID)
+ || !is_string_safe(pMessage)
+ ) {
+ return;
+ }
+
if (pUID[0] == '0' && !pUID[1])
{
execute_sql(m_pDB,
@@ -409,6 +455,12 @@ void CSQLite3::SetReported(const char *pUUID, const char *pUID, const char *pMes
vector_database_rows_t CSQLite3::GetUIDData(const char *pUID)
{
vector_database_rows_t table;
+
+ if (!is_string_safe(pUID))
+ {
+ return table;
+ }
+
if (pUID[0] == '0' && !pUID[1])
{
get_table(table, m_pDB, "SELECT * FROM "ABRT_TABLE";");
@@ -426,6 +478,12 @@ vector_database_rows_t CSQLite3::GetUIDData(const char *pUID)
database_row_t CSQLite3::GetRow(const char *pUUID, const char *pUID)
{
+ if (!is_string_safe(pUUID)
+ || !is_string_safe(pUID)
+ ) {
+ return database_row_t();
+ }
+
vector_database_rows_t table;
if (pUID[0] == '0' && !pUID[1])
diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp
index a4fe0e8..608ee40 100644
--- a/lib/Plugins/TicketUploader.cpp
+++ b/lib/Plugins/TicketUploader.cpp
@@ -120,17 +120,14 @@ void CTicketUploader::SendFile(const char *pURL, const char *pFilename)
throw CABRTException(EXCEP_PLUGIN, "Can't open archive file '%s'", pFilename);
}
struct stat buf;
- if (fstat(fileno(f), &buf) == -1) /* TODO: never fails */
- {
- throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename);
- }
+ fstat(fileno(f), &buf); /* never fails */
CURL* curl = xcurl_easy_init();
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target */
curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str());
curl_easy_setopt(curl, CURLOPT_READDATA, f);
- curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size);
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)buf.st_size);
/* everything is done here; result 0 means success */
result = curl_easy_perform(curl);
/* goodbye */
@@ -221,7 +218,7 @@ string CTicketUploader::Report(const map_crash_report_t& pCrashReport,
else if (it->second[CD_TYPE] == CD_BIN)
{
string ofile_name = concat_path_file(tmptar_name.c_str(), it->first.c_str());
- if (copy_file(it->second[CD_CONTENT].c_str(), ofile_name.c_str()) < 0)
+ if (copy_file(it->second[CD_CONTENT].c_str(), ofile_name.c_str(), 0644) < 0)
{
throw CABRTException(EXCEP_PLUGIN,
"Can't copy '%s' to '%s'",
@@ -399,19 +396,18 @@ void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings)
}
}
-//ok to delete?
-//const map_plugin_settings_t& CTicketUploader::GetSettings()
-//{
-// m_pSettings["Customer"] = m_sCustomer;
-// m_pSettings["Ticket"] = m_sTicket;
-// m_pSettings["URL"] = m_sURL;
-// m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no";
-// m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no";
-// m_pSettings["RetryCount"] = to_string(m_nRetryCount);
-// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
-//
-// return m_pSettings;
-//}
+const map_plugin_settings_t& CTicketUploader::GetSettings()
+{
+ m_pSettings["Customer"] = m_sCustomer;
+ m_pSettings["Ticket"] = m_sTicket;
+ m_pSettings["URL"] = m_sURL;
+ m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no";
+ m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no";
+ m_pSettings["RetryCount"] = to_string(m_nRetryCount);
+ m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
+
+ return m_pSettings;
+}
PLUGIN_INFO(REPORTER,
CTicketUploader,
diff --git a/lib/Plugins/TicketUploader.h b/lib/Plugins/TicketUploader.h
index e00596f..1bc8f6b 100644
--- a/lib/Plugins/TicketUploader.h
+++ b/lib/Plugins/TicketUploader.h
@@ -27,7 +27,7 @@
#include "Plugin.h"
#include "Reporter.h"
-#include "CrashTypes.h"
+//#include "CrashTypes.h"
class CTicketUploader : public CReporter
{
@@ -45,8 +45,7 @@ class CTicketUploader : public CReporter
public:
CTicketUploader();
virtual ~CTicketUploader();
-//ok to delete?
-// virtual const map_plugin_settings_t& GetSettings();
+ virtual const map_plugin_settings_t& GetSettings();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
virtual std::string Report(const map_crash_report_t& pCrashReport,
diff --git a/lib/Utils/CommLayerInner.cpp b/lib/Utils/CommLayerInner.cpp
index 133e97d..4a3b80a 100644
--- a/lib/Utils/CommLayerInner.cpp
+++ b/lib/Utils/CommLayerInner.cpp
@@ -68,11 +68,9 @@ void update_client(const char *fmt, ...)
va_list p;
va_start(p, fmt);
- char *msg;
- int used = vasprintf(&msg, fmt, p);
+ char *msg = xvasprintf(fmt, p);
va_end(p);
- if (used < 0)
- return;
s_pObs->Status(msg, peer, key);
+ free(msg);
}
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp
index b4c3ee4..a0a52ab 100644
--- a/lib/Utils/DebugDump.cpp
+++ b/lib/Utils/DebugDump.cpp
@@ -65,7 +65,9 @@ CDebugDump::CDebugDump() :
m_sDebugDumpDir(""),
m_pGetNextFileDir(NULL),
m_bOpened(false),
- m_bLocked(false)
+ m_bLocked(false),
+ m_uid(0),
+ m_gid(0)
{}
CDebugDump::~CDebugDump()
@@ -97,6 +99,15 @@ void CDebugDump::Open(const char *pDir)
}
Lock();
m_bOpened = true;
+ /* In case caller would want to create more files, he'll need uid:gid */
+ m_uid = 0;
+ m_gid = 0;
+ struct stat stat_buf;
+ if (stat(m_sDebugDumpDir.c_str(), &stat_buf) == 0)
+ {
+ m_uid = stat_buf.st_uid;
+ m_gid = stat_buf.st_gid;
+ }
}
bool CDebugDump::Exist(const char* pPath)
@@ -115,7 +126,15 @@ static bool GetAndSetLock(const char* pLockFile, const char* pPID)
char pid_buf[sizeof(pid_t)*3 + 4];
ssize_t r = readlink(pLockFile, pid_buf, sizeof(pid_buf) - 1);
if (r < 0)
+ {
+ if (errno == ENOENT)
+ {
+ /* Looks like pLockFile was deleted */
+ usleep(10 * 1000); /* avoid CPU eating loop */
+ continue;
+ }
perror_msg_and_die("Can't read lock file '%s'", pLockFile);
+ }
pid_buf[r] = '\0';
if (strcmp(pid_buf, pPID) == 0)
@@ -209,8 +228,8 @@ void CDebugDump::Lock()
error_msg_and_die("Locking bug on '%s'", m_sDebugDumpDir.c_str());
std::string lockFile = m_sDebugDumpDir + ".lock";
- char pid_buf[sizeof(int)*3 + 2];
- sprintf(pid_buf, "%u", (unsigned)getpid());
+ char pid_buf[sizeof(long)*3 + 2];
+ sprintf(pid_buf, "%lu", (long)getpid());
while ((m_bLocked = GetAndSetLock(lockFile.c_str(), pid_buf)) != true)
{
sleep(1); /* was 0.5 seconds */
@@ -228,7 +247,26 @@ void CDebugDump::UnLock()
}
}
-void CDebugDump::Create(const char *pDir, int64_t uid)
+/* Create a fresh empty debug dump dir.
+ *
+ * Security: we should not allow users to write new files or write
+ * into existing ones, but they should be able to read them.
+ *
+ * @param uid
+ * Crashed application's User Id
+ *
+ * We currently have only three callers:
+ * kernel oops hook: uid=0
+ * this hook runs under 0:0
+ * ccpp hook: uid=uid of crashed user's binary
+ * this hook runs under 0:0
+ * python hook: uid=uid of crashed user's script
+ * this hook runs under abrt:gid
+ *
+ * Currently, we set dir's gid to passwd(uid)->pw_gid parameter, and we set uid to
+ * abrt's user id. We do not allow write access to group.
+ */
+void CDebugDump::Create(const char *pDir, uid_t uid)
{
if (m_bOpened)
{
@@ -244,25 +282,45 @@ void CDebugDump::Create(const char *pDir, int64_t uid)
Lock();
m_bOpened = true;
- if (mkdir(m_sDebugDumpDir.c_str(), 0700) == -1)
+ /* Was creating it with mode 0700 and user as the owner, but this allows
+ * the user to replace any file in the directory, changing security-sensitive data
+ * (e.g. "uid", "analyzer", "executable")
+ */
+ if (mkdir(m_sDebugDumpDir.c_str(), 0750) == -1)
{
UnLock();
m_bOpened = false;
throw CABRTException(EXCEP_DD_OPEN, "Can't create dir '%s'", pDir);
}
- if (chmod(m_sDebugDumpDir.c_str(), 0700) == -1)
+
+ /* mkdir's mode (above) can be affected by umask, fix it */
+ if (chmod(m_sDebugDumpDir.c_str(), 0750) == -1)
{
UnLock();
m_bOpened = false;
throw CABRTException(EXCEP_DD_OPEN, "Can't change mode of '%s'", pDir);
}
- struct passwd* pw = getpwuid(uid);
- gid_t gid = pw ? pw->pw_gid : uid;
- if (chown(m_sDebugDumpDir.c_str(), uid, gid) == -1)
+
+ /* Get ABRT's user id */
+ m_uid = 0;
+ struct passwd *pw = getpwnam("abrt");
+ if (pw)
+ m_uid = pw->pw_uid;
+ else
+ error_msg("User 'abrt' does not exist, using uid 0");
+
+ /* Get crashed application's group id */
+ m_gid = 0;
+ pw = getpwuid(uid);
+ if (pw)
+ m_gid = pw->pw_gid;
+ else
+ error_msg("User %lu does not exist, using gid 0", (long)uid);
+
+ if (chown(m_sDebugDumpDir.c_str(), m_uid, m_gid) == -1)
{
- /* if /var/cache/abrt is writable by all, _aborting_ here is not useful */
- /* let's just warn */
- perror_msg("can't change '%s' ownership to %u:%u", m_sDebugDumpDir.c_str(), (int)uid, (int)gid);
+ perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(),
+ (long)m_uid, (long)m_gid);
}
SaveText(FILENAME_UID, to_string(uid).c_str());
@@ -294,7 +352,7 @@ static void DeleteFileDir(const char *pDir)
}
}
closedir(dir);
- if (remove(pDir) == -1)
+ if (rmdir(pDir) == -1)
{
throw CABRTException(EXCEP_DD_DELETE, "Can't remove dir %s", pDir);
}
@@ -359,12 +417,18 @@ static void LoadTextFile(const char *pPath, std::string& pData)
fclose(fp);
}
-static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize)
+static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize, uid_t uid, gid_t gid)
{
- int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ /* "Why 0640?!" See ::Create() for security analysis */
+ unlink(pPath);
+ int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0640);
if (fd < 0)
{
- throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s'", pPath);
+ throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s': %s", pPath, errno ? strerror(errno) : "errno == 0");
+ }
+ if (fchown(fd, uid, gid) == -1)
+ {
+ perror_msg("can't change '%s' ownership to %lu:%lu", pPath, (long)uid, (long)gid);
}
unsigned r = full_write(fd, pData, pSize);
close(fd);
@@ -391,8 +455,9 @@ void CDebugDump::SaveText(const char* pName, const char* pData)
throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened");
}
std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName);
- SaveBinaryFile(fullPath.c_str(), pData, strlen(pData));
+ SaveBinaryFile(fullPath.c_str(), pData, strlen(pData), m_uid, m_gid);
}
+
void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize)
{
if (!m_bOpened)
@@ -400,7 +465,7 @@ void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize
throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened");
}
std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName);
- SaveBinaryFile(fullPath.c_str(), pData, pSize);
+ SaveBinaryFile(fullPath.c_str(), pData, pSize, m_uid, m_gid);
}
void CDebugDump::InitGetNextFile()
diff --git a/lib/Utils/DebugDump.h b/lib/Utils/DebugDump.h
index c59552e..d3eebb4 100644
--- a/lib/Utils/DebugDump.h
+++ b/lib/Utils/DebugDump.h
@@ -51,6 +51,8 @@ class CDebugDump
DIR* m_pGetNextFileDir;
bool m_bOpened;
bool m_bLocked;
+ uid_t m_uid;
+ gid_t m_gid;
void SaveKernelArchitectureRelease();
@@ -62,7 +64,7 @@ class CDebugDump
~CDebugDump();
void Open(const char *pDir);
- void Create(const char *pDir, int64_t uid);
+ void Create(const char *pDir, uid_t uid);
void Delete();
void Close();
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index d5e9d98..a944d97 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -16,7 +16,7 @@ libABRTUtils_la_SOURCES = \
daemon.cpp \
skip_whitespace.cpp \
xatonum.cpp \
- popen_and_save_output.cpp \
+ spawn.cpp \
stringops.cpp \
dirsize.cpp \
DebugDump.h DebugDump.cpp \
diff --git a/lib/Utils/Polkit.cpp b/lib/Utils/Polkit.cpp
index c868e1a..a7e4a5d 100644
--- a/lib/Utils/Polkit.cpp
+++ b/lib/Utils/Polkit.cpp
@@ -46,14 +46,12 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id)
GCancellable * cancellable;
authority = polkit_authority_get();
-
cancellable = g_cancellable_new();
- g_timeout_add(POLKIT_TIMEOUT * 1000,
+ guint cancel_timeout = g_timeout_add(POLKIT_TIMEOUT * 1000,
(GSourceFunc) do_cancel,
cancellable);
-
result = polkit_authority_check_authorization_sync(authority,
subject,
action_id,
@@ -61,7 +59,8 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id)
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
cancellable,
&error);
-
+ g_object_unref(authority);
+ g_source_remove(cancel_timeout);
if (error)
{
g_error_free(error);
@@ -71,11 +70,18 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id)
if (result)
{
if (polkit_authorization_result_get_is_challenge(result))
+ {
/* Can't happen (happens only with
* POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */
+ g_object_unref(result);
return PolkitChallenge;
+ }
if (polkit_authorization_result_get_is_authorized(result))
+ {
+ g_object_unref(result);
return PolkitYes;
+ }
+ g_object_unref(result);
return PolkitNo;
}
diff --git a/lib/Utils/abrt_dbus.h b/lib/Utils/abrt_dbus.h
index bc9889a..25e099e 100644
--- a/lib/Utils/abrt_dbus.h
+++ b/lib/Utils/abrt_dbus.h
@@ -154,6 +154,9 @@ enum {
ABRT_DBUS_ERROR = -1,
ABRT_DBUS_LAST_FIELD = 0,
ABRT_DBUS_MORE_FIELDS = 1,
+ /* note that dbus_message_iter_next() returns FALSE on last field
+ * and TRUE if there are more fields.
+ * It maps exactly on the above constants. */
};
/* Checks type, loads data, advances to the next arg.
* Returns TRUE if next arg exists.
diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp
index ae1d098..e3a4648 100644
--- a/lib/Utils/abrt_xmlrpc.cpp
+++ b/lib/Utils/abrt_xmlrpc.cpp
@@ -15,6 +15,16 @@ CURL* xcurl_easy_init()
return curl;
}
+#if 1
+void throw_xml_fault(xmlrpc_env *env)
+{
+ std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code);
+ xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred
+ xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env
+ error_msg("%s", errmsg.c_str()); // show error in daemon log
+ throw CABRTException(EXCEP_PLUGIN, errmsg.c_str());
+}
+#else
void throw_if_xml_fault_occurred(xmlrpc_env *env)
{
if (env->fault_occurred)
@@ -26,6 +36,7 @@ void throw_if_xml_fault_occurred(xmlrpc_env *env)
throw CABRTException(EXCEP_PLUGIN, errmsg.c_str());
}
}
+#endif
void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify)
{
@@ -60,15 +71,16 @@ void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify)
PACKAGE_NAME, VERSION,
&clientParms, XMLRPC_CPSIZE(transportparm_size),
&m_pClient);
- throw_if_xml_fault_occurred(&env);
+ if (env.fault_occurred)
+ throw_xml_fault(&env);
m_pServer_info = xmlrpc_server_info_new(&env, url);
if (env.fault_occurred)
{
xmlrpc_client_destroy(m_pClient);
m_pClient = NULL;
+ throw_xml_fault(&env);
}
- throw_if_xml_fault_occurred(&env);
}
void abrt_xmlrpc_conn::destroy_xmlrpc_client()
diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h
index 352e80c..a8bd2cc 100644
--- a/lib/Utils/abrt_xmlrpc.h
+++ b/lib/Utils/abrt_xmlrpc.h
@@ -24,7 +24,7 @@ struct abrt_xmlrpc_conn {
};
/* Utility functions */
-void throw_if_xml_fault_occurred(xmlrpc_env *env);
+void throw_xml_fault(xmlrpc_env *env);
CURL* xcurl_easy_init();
#endif
diff --git a/lib/Utils/copyfd.cpp b/lib/Utils/copyfd.cpp
index 9abe752..fdc568a 100644
--- a/lib/Utils/copyfd.cpp
+++ b/lib/Utils/copyfd.cpp
@@ -106,7 +106,7 @@ off_t copyfd_eof(int fd1, int fd2)
return full_fd_action(fd1, fd2, 0);
}
-off_t copy_file(const char *src_name, const char *dst_name)
+off_t copy_file(const char *src_name, const char *dst_name, int mode)
{
off_t r;
int src = open(src_name, O_RDONLY);
@@ -115,7 +115,7 @@ off_t copy_file(const char *src_name, const char *dst_name)
perror_msg("Can't open '%s'", src_name);
return -1;
}
- int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, mode);
if (dst < 0)
{
close(src);
diff --git a/lib/Utils/daemon.cpp b/lib/Utils/daemon.cpp
index 7aa891c..0527062 100644
--- a/lib/Utils/daemon.cpp
+++ b/lib/Utils/daemon.cpp
@@ -78,12 +78,12 @@ static char *append_escaped(char *start, const char *s)
#define COMMAND_LINE_SIZE 2048
char* get_cmdline(pid_t pid)
{
- char path[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
+ char path[sizeof("/proc/%lu/cmdline") + sizeof(long)*3];
char cmdline[COMMAND_LINE_SIZE];
char escaped_cmdline[COMMAND_LINE_SIZE*4 + 4];
escaped_cmdline[1] = '\0';
- sprintf(path, "/proc/%u/cmdline", (int)pid);
+ sprintf(path, "/proc/%lu/cmdline", (long)pid);
int fd = open(path, O_RDONLY);
if (fd >= 0)
{
diff --git a/lib/Utils/popen_and_save_output.cpp b/lib/Utils/popen_and_save_output.cpp
deleted file mode 100644
index 4bcbcac..0000000
--- a/lib/Utils/popen_and_save_output.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Utility routines.
- *
- * Licensed under GPLv2 or later, see file COPYING in this tarball for details.
- */
-#include "abrtlib.h"
-
-using namespace std;
-
-string popen_and_save_output(const char *cmd)
-{
- string result;
-
- FILE *fp = popen(cmd, "r");
- if (fp == NULL) /* fork or pipe failed; or out-of-mem */
- {
- return result;
- }
-
- size_t sz;
- char buf[BUFSIZ + 1];
- while ((sz = fread(buf, 1, sizeof(buf)-1, fp)) > 0)
- {
- buf[sz] = '\0';
- result += buf;
- }
- pclose(fp);
-
- return result;
-}
diff --git a/lib/Utils/spawn.cpp b/lib/Utils/spawn.cpp
new file mode 100644
index 0000000..d3e6ac6
--- /dev/null
+++ b/lib/Utils/spawn.cpp
@@ -0,0 +1,136 @@
+/*
+ * Utility routines.
+ *
+ * Licensed under GPLv2, see file COPYING in this tarball for details.
+ */
+#include "abrtlib.h"
+
+using namespace std;
+
+static string concat_str_vector(char **strings)
+{
+ string result;
+ while (*strings) {
+ result += *strings++;
+ if (*strings)
+ result += ' ';
+ }
+ return result;
+}
+
+/* Returns pid */
+pid_t fork_execv_on_steroids(int flags,
+ char **argv,
+ int *pipefds,
+ char **unsetenv_vec,
+ const char *dir,
+ uid_t uid)
+{
+ pid_t child;
+ /* Reminder: [0] is read end, [1] is write end */
+ int pipe_to_child[2];
+ int pipe_fm_child[2];
+
+ /* Sanitize flags */
+ if (!pipefds)
+ flags &= ~(EXECFLG_INPUT | EXECFLG_OUTPUT);
+
+ if (flags & EXECFLG_INPUT)
+ xpipe(pipe_to_child);
+ if (flags & EXECFLG_OUTPUT)
+ xpipe(pipe_fm_child);
+
+ fflush(NULL);
+ child = fork();
+ if (child == -1) {
+ perror_msg_and_die("fork");
+ }
+ if (child == 0) {
+ /* Child */
+
+ /* Play with stdio descriptors */
+ if (flags & EXECFLG_INPUT) {
+ xmove_fd(pipe_to_child[0], STDIN_FILENO);
+ } else if (flags & EXECFLG_INPUT_NUL) {
+ xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO);
+ }
+ if (flags & EXECFLG_OUTPUT) {
+ xmove_fd(pipe_fm_child[1], STDOUT_FILENO);
+ } else if (flags & EXECFLG_OUTPUT_NUL) {
+ xmove_fd(xopen("/dev/null", O_RDWR), STDOUT_FILENO);
+ }
+ if (flags & EXECFLG_ERR2OUT) {
+ /* Want parent to see errors in the same stream */
+ xdup2(STDOUT_FILENO, STDERR_FILENO);
+ } else if (flags & EXECFLG_ERR_NUL) {
+ xmove_fd(xopen("/dev/null", O_RDWR), STDERR_FILENO);
+ }
+
+ if (flags & EXECFLG_SETGUID) {
+ struct passwd* pw = getpwuid(uid);
+ gid_t gid = pw ? pw->pw_gid : uid;
+ setgroups(1, &gid);
+ xsetregid(gid, gid);
+ xsetreuid(uid, uid);
+ }
+ if (flags & EXECFLG_SETSID)
+ setsid();
+
+ if (unsetenv_vec) {
+ while (*unsetenv_vec)
+ unsetenv(*unsetenv_vec++);
+ }
+
+ if (dir)
+ xchdir(dir);
+
+ VERB1 log("Executing: %s", concat_str_vector(argv).c_str());
+ execvp(argv[0], argv);
+ if (!(flags & EXECFLG_QUIET))
+ perror_msg("Can't execute '%s'", argv[0]);
+ exit(127); /* shell uses this exitcode in this case */
+ }
+
+ if (flags & EXECFLG_INPUT) {
+ close(pipe_to_child[0]);
+ pipefds[1] = pipe_to_child[1];
+ }
+ if (flags & EXECFLG_OUTPUT) {
+ close(pipe_fm_child[1]);
+ pipefds[0] = pipe_fm_child[0];
+ }
+
+ return child;
+}
+
+char *run_in_shell_and_save_output(int flags,
+ const char *cmd,
+ const char *dir,
+ size_t *size_p)
+{
+ flags |= EXECFLG_OUTPUT;
+ flags &= ~EXECFLG_INPUT;
+
+ const char *argv[] = { "/bin/sh", "sh", "-c", cmd, NULL };
+ int pipeout[2];
+ pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout,
+ /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0);
+
+ size_t pos = 0;
+ char *result = NULL;
+ while (1) {
+ result = (char*) xrealloc(result, pos + 4*1024 + 1);
+ size_t sz = safe_read(pipeout[0], result + pos, 4*1024);
+ if (sz <= 0) {
+ break;
+ }
+ pos += sz;
+ }
+ result[pos] = '\0';
+ if (size_p)
+ *size_p = pos;
+ close(pipeout[0]);
+ waitpid(child, NULL, 0);
+
+ return result;
+}
diff --git a/lib/Utils/xatonum.cpp b/lib/Utils/xatonum.cpp
index b096ca8..8314629 100644
--- a/lib/Utils/xatonum.cpp
+++ b/lib/Utils/xatonum.cpp
@@ -9,7 +9,7 @@
unsigned xatou(const char *numstr)
{
- unsigned r;
+ unsigned long r;
int old_errno;
char *e;
@@ -19,7 +19,7 @@ unsigned xatou(const char *numstr)
old_errno = errno;
errno = 0;
r = strtoul(numstr, &e, 10);
- if (errno || numstr == e || *e != '\0')
+ if (errno || numstr == e || *e != '\0' || r > UINT_MAX)
goto inval; /* error / no digits / illegal trailing chars */
errno = old_errno; /* Ok. So restore errno. */
return r;
diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp
index 8621b5f..f360d33 100644
--- a/lib/Utils/xfuncs.cpp
+++ b/lib/Utils/xfuncs.cpp
@@ -141,6 +141,12 @@ off_t xlseek(int fd, off_t offset, int whence)
return off;
}
+void xchdir(const char *path)
+{
+ if (chdir(path))
+ perror_msg_and_die("chdir(%s)", path);
+}
+
char* xvasprintf(const char *format, va_list p)
{
int r;
@@ -152,8 +158,8 @@ char* xvasprintf(const char *format, va_list p)
#else
// Bloat for systems that haven't got the GNU extension.
va_list p2;
- r = vsnprintf(NULL, 0, format, p);
va_copy(p2, p);
+ r = vsnprintf(NULL, 0, format, p);
string_ptr = xmalloc(r+1);
r = vsnprintf(string_ptr, r+1, format, p2);
va_end(p2);
@@ -365,13 +371,13 @@ bool string_to_bool(const char *s)
void xsetreuid(uid_t ruid, uid_t euid)
{
if (setreuid(ruid, euid) != 0)
- perror_msg_and_die("can't set %cid %d", 'u', (int)ruid);
+ perror_msg_and_die("can't set %cid %lu", 'u', (long)ruid);
}
-void xsetregid(gid_t rgid, uid_t egid)
+void xsetregid(gid_t rgid, gid_t egid)
{
if (setregid(rgid, egid) != 0)
- perror_msg_and_die("can't set %cid %d", 'g', (int)rgid);
+ perror_msg_and_die("can't set %cid %lu", 'g', (long)rgid);
}
uid_t getuidbyname(const char* login)