On Fri, 2010-07-23 at 17:36 +0200, Jiri Moskovcak wrote:
On 07/23/2010 05:28 PM, Denys Vlasenko wrote:
> Old core pattern is passed to the hook as argv[6], hex encoded
> in order to preserve spaces and percents.
>
> %p %s %u %c and %% specifiers are supported.
>
> /proc/.../core_uses_pid has any effect only if old pattern is "core".
>
> Patch is run tested.
There is /disk1/tmp/core.%h.%e.%u in the bz which should be fixed by
this patch, so probably all of the options bellow should be supported:
%p - pid
%u - uid
%g - gid
%s - signal number
%t - UNIX time of dump
%h - hostname
%e - executable filename
%% - output one "%"
Here is the updated patch:
diff -x '*.po' -d -urpN abrt.2/inc/abrtlib.h abrt.3/inc/abrtlib.h
--- abrt.2/inc/abrtlib.h 2010-07-22 13:49:09.000000000 +0200
+++ abrt.3/inc/abrtlib.h 2010-07-23 16:06:40.587805661 +0200
@@ -37,10 +37,13 @@
#endif
#include <pwd.h>
#include <grp.h>
+
/* C++ bits */
-#include <string>
+#ifdef __cplusplus
+# include <string>
+# include "abrt_types.h"
+#endif
-#include "abrt_types.h"
#include "xfuncs.h"
/* Some libc's forget to declare these, do it ourself */
@@ -133,8 +136,8 @@ extern ssize_t full_write(int fd, const
enum {
COPYFD_SPARSE = 1 << 0,
};
-off_t copyfd_eof(int src_fd, int dst_fd, int flags = 0);
-off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags = 0);
+off_t copyfd_eof(int src_fd, int dst_fd, int flags);
+off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags);
void copyfd_exact_size(int src_fd, int dst_fd, off_t size);
off_t copy_file(const char *src_name, const char *dst_name, int mode);
@@ -214,6 +217,17 @@ char* xmalloc_sockaddr2dotted_noport(con
/* Random utility functions */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Emit a string of hex representation of bytes */
+char* bin2hex(char *dst, const char *str, int count);
+/* Convert "xxxxxxxx" hex string to binary, no more than COUNT bytes */
+char* hex2bin(char *dst, const char *str, int count);
+#ifdef __cplusplus
+}
+#endif
+
/* Returns command line of running program.
* Caller is responsible to free() the returned value.
* If the pid is not valid or command line can not be obtained,
@@ -228,6 +242,7 @@ int daemon_is_ok();
char *encode_base64(const void *src, int length);
/* C++ style stuff */
+#ifdef __cplusplus
double get_dirsize(const char *pPath);
double get_dirsize_find_largest_dir(
const char *pPath,
@@ -246,5 +261,6 @@ std::string to_string(T x)
void parse_args(const char *psArgs, vector_string_t& pArgs, int quote = -1);
void parse_release(const char *pRelease, char **product, char **version);
+#endif
#endif
diff -x '*.po' -d -urpN abrt.2/lib/Plugins/CCpp.cpp abrt.3/lib/Plugins/CCpp.cpp
--- abrt.2/lib/Plugins/CCpp.cpp 2010-07-22 13:49:09.000000000 +0200
+++ abrt.3/lib/Plugins/CCpp.cpp 2010-07-23 18:58:29.421806046 +0200
@@ -35,7 +35,19 @@
using namespace std;
#define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern"
-#define CORE_PATTERN "|"CCPP_HOOK_PATH"
"DEBUG_DUMPS_DIR" %p %s %u %c"
+/*
+ * %s - signal number
+ * %c - ulimit -c value
+ * %p - pid
+ * %u - uid
+ * %g - gid
+ * %t - UNIX time of dump
+ * %h - hostname
+ * %e - executable filename
+ * %% - output one "%"
+ */
+#define CORE_PATTERN "|"CCPP_HOOK_PATH"
"DEBUG_DUMPS_DIR" %s %c %p %u %g %t %h %e"
+
#define CORE_PIPE_LIMIT_IFACE "/proc/sys/kernel/core_pipe_limit"
/* core_pipe_limit specifies how many dump_helpers might run at the same time
0 - means unlimited, but the it's not guaranteed that /proc/<pid> of crashing
@@ -923,7 +935,7 @@ void CAnalyzerCCpp::Init()
}
if (m_sOldCorePattern[0] == '|')
{
- if (m_sOldCorePattern == CORE_PATTERN)
+ if (strncmp(m_sOldCorePattern.c_str(), CORE_PATTERN, strlen(CORE_PATTERN)) == 0)
{
log("warning: %s already contains %s, "
"did abrt daemon crash recently?",
@@ -947,14 +959,32 @@ void CAnalyzerCCpp::Init()
fp = fopen(CORE_PATTERN_IFACE, "w");
if (fp)
{
- fputs(CORE_PATTERN, fp);
+ if (m_sOldCorePattern[0] != '|')
+ {
+ const char *old = m_sOldCorePattern.c_str();
+ unsigned len = strchrnul(old, '\n') - old;
+ char *hex_old = (char*)xmalloc(len * 2 + 1);
+ bin2hex(hex_old, old, len)[0] = '\0';
+log("old:'%s'->'%s'", old, hex_old);
+ char *pattern = xasprintf("%s %s", CORE_PATTERN, hex_old);
+log("pattern:'%s'", pattern);
+
+ fputs(pattern, fp);
+
+ free(pattern);
+ free(hex_old);
+ }
+ else
+ {
+ fputs(CORE_PATTERN, fp);
+ }
fclose(fp);
}
/* read the core_pipe_limit and change it if it's == 0
- otherwise the abrt-hook-ccpp won't be able to read /proc/<pid>
- of the crashing process
- */
+ * otherwise the abrt-hook-ccpp won't be able to read /proc/<pid>
+ * of the crashing process
+ */
fp = fopen(CORE_PIPE_LIMIT_IFACE, "r");
if (fp)
{
diff -x '*.po' -d -urpN abrt.2/lib/Utils/binhex.c abrt.3/lib/Utils/binhex.c
--- abrt.2/lib/Utils/binhex.c 1970-01-01 01:00:00.000000000 +0100
+++ abrt.3/lib/Utils/binhex.c 2010-07-23 15:58:51.868807377 +0200
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2010 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "abrtlib.h"
+
+static const char hexdigits_locase[] = "0123456789abcdef";
+
+/* Emit a string of hex representation of bytes */
+char *bin2hex(char *dst, const char *str, int count)
+{
+ while (count) {
+ unsigned char c = *str++;
+ /* put lowercase hex digits */
+ *dst++ = hexdigits_locase[c >> 4];
+ *dst++ = hexdigits_locase[c & 0xf];
+ count--;
+ }
+ return dst;
+}
+
+/* Convert "xxxxxxxx" hex string to binary, no more than COUNT bytes */
+char *hex2bin(char *dst, const char *str, int count)
+{
+ /* Parts commented out with // allow parsing
+ * of strings like "xx:x:x:xx:xx:xx:xxxxxx"
+ * (IPv6, ethernet addresses and the like).
+ */
+ errno = EINVAL;
+ while (*str && count) {
+ uint8_t val;
+ uint8_t c;
+
+ c = *str++;
+ if (isdigit(c))
+ val = c - '0';
+ else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
+ val = (c|0x20) - ('a' - 10);
+ else
+ return NULL;
+ val <<= 4;
+ c = *str;
+ if (isdigit(c))
+ val |= c - '0';
+ else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
+ val |= (c|0x20) - ('a' - 10);
+ //else if (c == ':' || c == '\0')
+ // val >>= 4;
+ else
+ return NULL;
+
+ *dst++ = val;
+ //if (c != '\0')
+ str++;
+ //if (*str == ':')
+ // str++;
+ count--;
+ }
+ errno = (*str ? ERANGE : 0);
+ return dst;
+}
diff -x '*.po' -d -urpN abrt.2/lib/Utils/copyfd.cpp abrt.3/lib/Utils/copyfd.cpp
--- abrt.2/lib/Utils/copyfd.cpp 2010-07-22 13:49:09.000000000 +0200
+++ abrt.3/lib/Utils/copyfd.cpp 2010-07-23 16:05:53.275805964 +0200
@@ -134,7 +134,7 @@ off_t copyfd_size(int fd1, int fd2, off_
void copyfd_exact_size(int fd1, int fd2, off_t size)
{
- off_t sz = copyfd_size(fd1, fd2, size);
+ off_t sz = copyfd_size(fd1, fd2, size, /*flags:*/ 0);
if (sz == size)
return;
if (sz != -1)
@@ -164,7 +164,7 @@ off_t copy_file(const char *src_name, co
perror_msg("Can't open '%s'", dst_name);
return -1;
}
- r = copyfd_eof(src, dst);
+ r = copyfd_eof(src, dst, /*flags:*/ 0);
close(src);
close(dst);
return r;
diff -x '*.po' -d -urpN abrt.2/lib/Utils/Makefile.am abrt.3/lib/Utils/Makefile.am
--- abrt.2/lib/Utils/Makefile.am 2010-07-22 13:49:09.000000000 +0200
+++ abrt.3/lib/Utils/Makefile.am 2010-07-23 15:55:54.137806382 +0200
@@ -12,6 +12,7 @@ AM_YFLAGS = --verbose
libABRTUtils_la_SOURCES = \
xfuncs.cpp \
encbase64.cpp \
+ binhex.c \
read_write.cpp \
logging.cpp \
copyfd.cpp \
diff -x '*.po' -d -urpN abrt.2/src/Hooks/abrt-hook-ccpp.cpp
abrt.3/src/Hooks/abrt-hook-ccpp.cpp
--- abrt.2/src/Hooks/abrt-hook-ccpp.cpp 2010-07-22 13:49:09.000000000 +0200
+++ abrt.3/src/Hooks/abrt-hook-ccpp.cpp 2010-07-23 19:08:45.709807466 +0200
@@ -164,7 +164,22 @@ static char* get_cwd(pid_t pid)
return malloc_readlink(buf);
}
-static char core_basename[sizeof("core.%lu") + sizeof(long)*3] =
"core";
+/*
+ * %s - signal number
+ * %c - ulimit -c value
+ * %p - pid
+ * %u - uid
+ * %g - gid
+ * %t - UNIX time of dump
+ * %h - hostname
+ * %e - executable filename
+ * %% - output one "%"
+ */
+/* Must match CORE_PATTERN order in daemon! */
+static const char percent_specifiers[] = "%scpugthe";
+static char **percent_values;
+static unsigned percent_valcnt;
+static char *core_basename = "core";
static int open_user_core(const char *user_pwd, uid_t uid, pid_t pid)
{
@@ -182,16 +197,57 @@ static int open_user_core(const char *us
}
/* Mimic "core.PID" if requested */
- char buf[] = "0\n";
- int fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY);
- if (fd >= 0)
+ if (strcmp(core_basename, "core") == 0)
{
- read(fd, buf, sizeof(buf));
- close(fd);
+ char buf[] = "0\n";
+ int fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY);
+ if (fd >= 0)
+ {
+ read(fd, buf, sizeof(buf));
+ close(fd);
+ }
+ if (strcmp(buf, "1\n") == 0)
+ {
+ core_basename = xasprintf("%s.%lu", core_basename, (long)pid);
+ }
}
- if (strcmp(buf, "1\n") == 0)
+ else
{
- sprintf(core_basename, "core.%lu", (long)pid);
+ core_basename = xstrdup(core_basename);
+ unsigned idx = 0;
+ while (1)
+ {
+ char c = core_basename[idx];
+ if (!c)
+ break;
+ idx++;
+ if (c != '%')
+ continue;
+
+ /* We just copied % */
+ const char *val = "";
+ c = core_basename[idx];
+ unsigned specifier_num = strchrnul(percent_specifiers, c) -
percent_specifiers;
+ if (specifier_num <= percent_valcnt) /* valid %c (might be %% too) */
+ {
+log("c:'%c'", c);
+ val = "%";
+ if (specifier_num > 0)
+ val = percent_values[specifier_num - 1];
+log("val:'%s'", val);
+
+ char *old = core_basename;
+ idx--;
+ core_basename = xasprintf("%.*s%s%s", idx, core_basename, val,
core_basename + idx + 2);
+log("pos:'%*s|'", idx, "");
+log("new:'%s'", core_basename);
+log("old:'%s'", old);
+ free(old);
+
+ idx += strlen(val);
+ }
+ /* else: invalid %c, copy verbatim */
+ }
}
/* man core:
@@ -212,8 +268,7 @@ static int open_user_core(const char *us
*
* The RLIMIT_CORE or RLIMIT_FSIZE resource limits for the process
* are set to zero.
- * [shouldn't it be checked by kernel? 2.6.30.9-96 doesn't, still
- * calls us even if "ulimit -c 0"]
+ * [we check RLIMIT_CORE, but how can we check RLIMIT_FSIZE?]
*
* The binary being executed by the process does not have
* read permission enabled. [how we can check it here?]
@@ -253,29 +308,59 @@ int main(int argc, char** argv)
{
struct stat sb;
- if (argc < 5)
+ if (argc < 10)
{
- error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT",
argv[0]);
+ error_msg_and_die("Usage: %s: DUMPDIR SIGNO CORE_SIZE_LIMIT PID UID GID TIME
HOSTNAME BINARY_NAME [OLD_PATTERN]", argv[0]);
}
openlog("abrt", LOG_PID, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
+for (int ii = 0; argv[ii]; ii++)
+ log("argv[%d]='%s'", ii, argv[ii]);
+
+ /* Values corresponding to percent specifiers */
+ percent_values = &argv[2];
+ percent_valcnt = argc - 2;
errno = 0;
const char* dddir = argv[1];
- pid_t pid = xatoi_u(argv[2]);
- const char* signal_str = argv[3];
- int signal_no = xatoi_u(argv[3]);
- uid_t uid = xatoi_u(argv[4]);
- off_t ulimit_c = strtoull(argv[5], NULL, 10);
+ const char* signal_str = argv[2];
+ int signal_no = xatoi_u(signal_str);
+ off_t ulimit_c = strtoull(argv[3], NULL, 10);
if (ulimit_c < 0) /* unlimited? */
{
/* set to max possible >0 value */
ulimit_c = ~((off_t)1 << (sizeof(off_t)*8-1));
}
+ pid_t pid = xatoi_u(argv[4]);
+ uid_t uid = xatoi_u(argv[5]);
if (errno || pid <= 0)
{
- error_msg_and_die("pid '%s' or limit '%s' is bogus",
argv[2], argv[5]);
+ perror_msg_and_die("pid '%s' or limit '%s' is bogus",
argv[4], argv[3]);
+ }
+/// kernel bug: with /proc/sys/kernel/core_pattern set to:
+/// |/usr/libexec/abrt-hook-ccpp /var/spool/abrt %s %c %p %u %g %t %h %e
2f746d702f636f72652e25682e25652e2575
+/// we are getting TRUNCATED last argument!
+/// argv[0]='/usr/libexec/abrt-hook-ccpp'
+/// argv[1]='/var/spool/abrt'
+/// argv[2]='6'
+/// argv[3]='0'
+/// argv[4]='11797'
+/// argv[5]='0'
+/// argv[6]='0'
+/// argv[7]='1279904558'
+/// argv[8]='dhcp-lab-117.englab.brq.redhat.com'
+/// argv[9]='sleep'
+/// argv[10]='2f746d702f636f726'
+ if (argv[10]) /* OLD_PATTERN */
+ {
+ char *end = hex2bin(argv[10], argv[10], strlen(argv[10]));
+ if (end)
+ {
+ *end = '\0';
+ core_basename = argv[10];
+log("core_basename:'%s'", core_basename);
+ }
}
int src_fd_binary;