mirror of
https://github.com/clearlinux/telemetrics-client.git
synced 2026-09-01 11:15:51 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d3a9d2834 | ||
|
|
0af684e94e | ||
|
|
51374db118 | ||
|
|
dfb40babaa | ||
|
|
b7619e1a1c | ||
|
|
3be37cebb5 | ||
|
|
15a32b6346 | ||
|
|
e0e2aae341 | ||
|
|
4d1f6de3b5 | ||
|
|
f3a641b161 | ||
|
|
9018362ffb | ||
|
|
eedcb88cb7 | ||
|
|
2deeef65ad | ||
|
|
dab667eeea | ||
|
|
787102c4fb | ||
|
|
12d1c82650 | ||
|
|
46d88d6315 | ||
|
|
089183c9e0 | ||
|
|
f354078d3d | ||
|
|
db85aa9a18 | ||
|
|
f5899c7ba6 | ||
|
|
657c8792d5 | ||
|
|
365cfeee9a | ||
|
|
4957452f66 | ||
|
|
e02e22f192 | ||
|
|
60bbe963cb | ||
|
|
1ffc3a00c2 | ||
|
|
60edcdb165 | ||
|
|
bc12e6d5f7 | ||
|
|
e9d29a4e7b | ||
|
|
6295f0f4dc | ||
|
|
4cf3c7e8ac | ||
|
|
d9d957e532 | ||
|
|
f88d646ae1 | ||
|
|
e0619807c9 | ||
|
|
f07c9b168c | ||
|
|
7333bc7968 | ||
|
|
aa4f9e3058 | ||
|
|
6c36253351 | ||
|
|
e78ca8b66f | ||
|
|
a449e6cec1 | ||
|
|
5963f983cd | ||
|
|
c65e58f696 | ||
|
|
1d5b2d0669 | ||
|
|
356be6738f | ||
|
|
e73870b916 | ||
|
|
c7e783f2b1 | ||
|
|
3bb04aff3f | ||
|
|
26fc7b69bb | ||
|
|
e3ede3cd88 | ||
|
|
dd44e91d4a | ||
|
|
a403d884bc | ||
|
|
e699fd34e2 | ||
|
|
266039a4e5 | ||
|
|
3d24527096 | ||
|
|
9b435f39e5 | ||
|
|
20c051fe59 | ||
|
|
96c1cd5547 | ||
|
|
e375fe6825 | ||
|
|
160a4d01bf | ||
|
|
3f7b839cd8 | ||
|
|
07595885c4 | ||
|
|
625eea615e | ||
|
|
8a69b22895 | ||
|
|
b4a0989d0e | ||
|
|
41f53507d1 | ||
|
|
3aeb31ee3d | ||
|
|
4ce8ff9990 | ||
|
|
b671e770c9 | ||
|
|
2409452740 | ||
|
|
ecc60b6a3c | ||
|
|
579e7a8674 | ||
|
|
003928f52e | ||
|
|
c54bdab485 | ||
|
|
2af1d7e742 | ||
|
|
278c27f9a3 | ||
|
|
3e4360e2cb | ||
|
|
cb622a0eb0 | ||
|
|
44e0d4d3c5 | ||
|
|
36f4854967 | ||
|
|
524d5d2345 |
+36
@@ -0,0 +1,36 @@
|
||||
dist: trusty
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
before_script:
|
||||
./autogen.sh
|
||||
|
||||
language: c
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libglib2.0-dev
|
||||
- libcurl4-gnutls-dev
|
||||
- valgrind
|
||||
- autoconf
|
||||
- automake
|
||||
- check
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
|
||||
install:
|
||||
- wget http://downloads.sourceforge.net/project/check/check/0.10.0/check-0.10.0.tar.gz
|
||||
- tar -xvf check-0.10.0.tar.gz
|
||||
- pushd check-0.10.0 && ./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu && make -j48 && sudo make install && popd
|
||||
|
||||
script:
|
||||
- ./configure && make && make check
|
||||
|
||||
after_failure: cat test-suite.log
|
||||
+1
-1
@@ -62,7 +62,7 @@ Coding Style
|
||||
- To make type casts stand out more, include no space between the cast and the
|
||||
variable, etc. to cast:
|
||||
|
||||
GString **foo = (GString **)bar;
|
||||
nc_string **foo = (nc_string **)bar;
|
||||
|
||||
- Whenever arithmetic operators are used, always include one space before and
|
||||
after each operator:
|
||||
|
||||
@@ -14,9 +14,11 @@ DISTCHECK_CONFIGURE_FLAGS = \
|
||||
|
||||
include $(top_srcdir)/build-aux/make/cflags.make
|
||||
include $(top_srcdir)/build-aux/make/ldflags.make
|
||||
include $(top_srcdir)/docs/local.mk
|
||||
include $(top_srcdir)/scripts/local.mk
|
||||
include $(top_srcdir)/src/local.mk
|
||||
include $(top_srcdir)/src/data/local.mk
|
||||
include $(top_srcdir)/src/nica/local.mk
|
||||
include $(top_srcdir)/src/probes/local.mk
|
||||
include $(top_srcdir)/tests/local.mk
|
||||
|
||||
|
||||
@@ -30,9 +30,3 @@ Build dependencies
|
||||
- (optional) libsystemd, for syslog-style logging to the systemd journal, and
|
||||
socket/path activation of telemd by systemd.
|
||||
|
||||
|
||||
Generating HTML documentation
|
||||
=============================
|
||||
|
||||
At toplevel, run 'doxygen docs/Doxyfile'. The documentation is generated in
|
||||
the docs/html/ directory.
|
||||
|
||||
@@ -2,7 +2,6 @@ AM_CFLAGS = \
|
||||
-std=gnu99 \
|
||||
-pedantic \
|
||||
-Wall \
|
||||
-fstack-protector \
|
||||
-Wformat \
|
||||
-Wformat-security \
|
||||
-Wimplicit-function-declaration \
|
||||
@@ -12,7 +11,6 @@ AM_CFLAGS = \
|
||||
-Wconversion \
|
||||
-Wunreachable-code \
|
||||
-funsigned-char \
|
||||
-fstack-protector-strong \
|
||||
-fPIE \
|
||||
-fPIC
|
||||
|
||||
|
||||
+27
-1
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([telemetrics-client], [1.9.0], [https://clearlinux.org/])
|
||||
AC_INIT([telemetrics-client], [1.12.0], [https://clearlinux.org/])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([1.14 -Wall -Werror -Wno-extra-portability foreign subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
@@ -21,6 +21,8 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# check >= 0.9.12 is required for TAP output
|
||||
PKG_CHECK_MODULES([CHECK], [check >= 0.9.12])
|
||||
PKG_CHECK_MODULES([CURL], [libcurl])
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0])
|
||||
@@ -137,3 +139,27 @@ AC_CONFIG_COMMANDS([config dir],[mkdir -p src/data; touch src/data/.dirstamp])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_REQUIRE_AUX_FILE([tap-driver.sh])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE([
|
||||
|
||||
telemetrics-client $VERSION
|
||||
===========================
|
||||
|
||||
prefix: $prefix
|
||||
exec_prefix: $exec_prefix
|
||||
libdir: $libdir
|
||||
bindir: $bindir
|
||||
datarootdir: $datarootdir
|
||||
|
||||
compiler: $CC
|
||||
cflags: $CFLAGS
|
||||
ldflags: $LDFLAGS
|
||||
|
||||
unitdir: $unitpath
|
||||
tmpfilesdir: $tmpfilespath
|
||||
sysctldir: $sysctlpath
|
||||
systemconfdir: $confpath
|
||||
socketdir: $socketpath
|
||||
loglevel: $loglevel
|
||||
logtype: $logtype
|
||||
])
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
## Notes on manual pages
|
||||
|
||||
The manual pages are generated using `ronn(1)`. To recreate them,
|
||||
run `make manpages` in the toplevel folder. If you want to edit
|
||||
the documentation for upstream changes, make sure to edit the `*.md`
|
||||
files and not the shipped nroff output files.
|
||||
|
||||
|
||||
## Generating HTML documentation
|
||||
|
||||
At toplevel, run 'doxygen docs/Doxyfile'. The documentation is
|
||||
generated in the docs/html/ directory.
|
||||
@@ -0,0 +1,23 @@
|
||||
MANPAGES = \
|
||||
docs/man/telemctl.1 \
|
||||
docs/man/telemd.1 \
|
||||
docs/man/telem-record-gen.1 \
|
||||
docs/man/telemetry.3 \
|
||||
docs/man/telemetrics.conf.5
|
||||
|
||||
MANLINKS = \
|
||||
docs/man/tm_create_record.3 \
|
||||
docs/man/tm_send_record.3 \
|
||||
docs/man/tm_set_config_file.3 \
|
||||
docs/man/tm_set_payload.3
|
||||
|
||||
manpages:
|
||||
for MANPAGE in $(MANPAGES); do \
|
||||
rst2man.py $${MANPAGE}.rst > $${MANPAGE}; \
|
||||
rst2html.py $${MANPAGE}.rst > $${MANPAGE}.html; \
|
||||
done
|
||||
|
||||
dist_man_MANS = \
|
||||
$(MANPAGES) $(MANLINKS)
|
||||
|
||||
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
|
||||
@@ -0,0 +1 @@
|
||||
*.html
|
||||
@@ -0,0 +1,98 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH TELEM-RECORD-GEN 1 "" "" ""
|
||||
.SH NAME
|
||||
telem-record-gen \- Create custom telemetry record
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBtelem\-record\-gen\fP <options>
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Generate and attempt to send a telemetry record to \fBtelemd\fP(1). This
|
||||
program can be used to create a telemetry record from a shell script
|
||||
or from another program using e.g. \fBsystem()\fP\&. The program connects
|
||||
to a local \fBtelemd\fP(1) daemon to spool the record for delivery to
|
||||
the actual collection service.
|
||||
.sp
|
||||
The payload can be provided as standard input, as a file with the
|
||||
\fB\-\-payload\-file\fP option, or as a string argument with the \fB\-\-payload\fP
|
||||
option. If neither the \fB\-\-payload\fP or \fB\-\-payload\-file\fP is provided,
|
||||
the payload is assumed to be on <stdin>.
|
||||
.sp
|
||||
Each record is expected to have a class identifier, a record version
|
||||
number, and a severity level. A class identifier is required to be
|
||||
provided.
|
||||
.SH OPTIONS
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fB\-h\fP, \fB\-\-help\fP:
|
||||
Show help options.
|
||||
.IP \(bu 2
|
||||
\fB\-V\fP, \fB\-\-version\fP:
|
||||
Print the program version.
|
||||
.IP \(bu 2
|
||||
\fB\-f\fP, \fB\-\-config\-file\fP <file>:
|
||||
Path to configuration file (not implemented yet).
|
||||
.IP \(bu 2
|
||||
\fB\-s\fP, \fB\-\-severity\fP:
|
||||
Severity level (1\-4) \- (default 1).
|
||||
.IP \(bu 2
|
||||
\fB\-c\fP, \fB\-\-class\fP:
|
||||
Classification \fBlevel_1\fP/\fBlevel_2\fP/\fBlevel_3\fP\&.
|
||||
.IP \(bu 2
|
||||
\fB\-p\fP, \fB\-\-payload\fP <payload>:
|
||||
Record body (max size = 8k).
|
||||
.IP \(bu 2
|
||||
\fB\-P\fP, \fB\-\-payload\-file\fP <file>:
|
||||
File to read payload from.
|
||||
.IP \(bu 2
|
||||
\fB\-R\fP, \fB\-\-record\-version\fP <version>:
|
||||
Version number for format of payload (default 1).
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
0 on success. A non\-zero exit code indicates a failure occurred.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBtelemd\fP(1)
|
||||
.IP \(bu 2
|
||||
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
|
||||
.IP \(bu 2
|
||||
\fI\%https://clearlinux.org/documentation/\fP
|
||||
.UNINDENT
|
||||
.SH COPYRIGHT
|
||||
(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
@@ -0,0 +1,78 @@
|
||||
================
|
||||
telem-record-gen
|
||||
================
|
||||
|
||||
------------------------------
|
||||
Create custom telemetry record
|
||||
------------------------------
|
||||
|
||||
:Copyright: \(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
:Manual section: 1
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``telem-record-gen`` <options>
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
Generate and attempt to send a telemetry record to ``telemd``\(1). This
|
||||
program can be used to create a telemetry record from a shell script
|
||||
or from another program using e.g. ``system()``. The program connects
|
||||
to a local ``telemd``\(1) daemon to spool the record for delivery to
|
||||
the actual collection service.
|
||||
|
||||
The payload can be provided as standard input, as a file with the
|
||||
``--payload-file`` option, or as a string argument with the ``--payload``
|
||||
option. If neither the ``--payload`` or ``--payload-file`` is provided,
|
||||
the payload is assumed to be on <stdin>.
|
||||
|
||||
Each record is expected to have a class identifier, a record version
|
||||
number, and a severity level. A class identifier is required to be
|
||||
provided.
|
||||
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
* ``-h``, ``--help``:
|
||||
Show help options.
|
||||
|
||||
* ``-V``, ``--version``:
|
||||
Print the program version.
|
||||
|
||||
* ``-f``, ``--config-file`` <file>:
|
||||
Path to configuration file (not implemented yet).
|
||||
|
||||
* ``-s``, ``--severity``:
|
||||
Severity level (1-4) - (default 1).
|
||||
|
||||
* ``-c``, ``--class``:
|
||||
Classification ``level_1``/``level_2``/``level_3``.
|
||||
|
||||
* ``-p``, ``--payload`` <payload>:
|
||||
Record body (max size = 8k).
|
||||
|
||||
* ``-P``, ``--payload-file`` <file>:
|
||||
File to read payload from.
|
||||
|
||||
* ``-R``, ``--record-version`` <version>:
|
||||
Version number for format of payload (default 1).
|
||||
|
||||
|
||||
RETURN VALUES
|
||||
=============
|
||||
|
||||
0 on success. A non-zero exit code indicates a failure occurred.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* ``telemd``\(1)
|
||||
* https://github.com/clearlinux/telemetrics-client
|
||||
* https://clearlinux.org/documentation/
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH TELEMCTL 1 "" "" ""
|
||||
.SH NAME
|
||||
telemctl \- Telemetry service administration tool
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBtelemctl\fP
|
||||
.sp
|
||||
\fB/etc/telemetrics/opt\-out\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Control actions for telemetry services. The command can be used to start,
|
||||
restart, or stop \fBtelemd\fP(1), or to opt\-in or opt\-out of telemetry delivery
|
||||
of records to a central telemetry service.
|
||||
.SH OPTIONS
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBstart\(ga\(ga|\(ga\(gastop\(ga\(ga|\(ga\(garestart\fP:
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
.IP \(bu 2
|
||||
\fBopt\-in\fP:
|
||||
Opts in to telemetry, and starts telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is removed.
|
||||
.IP \(bu 2
|
||||
\fBopt\-out\fP:
|
||||
Opts out of telemetry, and stops telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is created.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
0 on success. A non\-zero exit code indicates a failure occurred.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBtelemd\fP(1)
|
||||
.IP \(bu 2
|
||||
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
|
||||
.IP \(bu 2
|
||||
\fI\%https://clearlinux.org/documentation/\fP
|
||||
.UNINDENT
|
||||
.SH COPYRIGHT
|
||||
(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
@@ -0,0 +1,56 @@
|
||||
========
|
||||
telemctl
|
||||
========
|
||||
|
||||
-------------------------------------
|
||||
Telemetry service administration tool
|
||||
-------------------------------------
|
||||
|
||||
:Copyright: \(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
:Manual section: 1
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``telemctl``
|
||||
|
||||
``/etc/telemetrics/opt-out``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
Control actions for telemetry services. The command can be used to start,
|
||||
restart, or stop ``telemd``\(1), or to opt-in or opt-out of telemetry delivery
|
||||
of records to a central telemetry service.
|
||||
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
* ``start``|``stop``|``restart``:
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
|
||||
* ``opt-in``:
|
||||
Opts in to telemetry, and starts telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is removed.
|
||||
|
||||
* ``opt-out``:
|
||||
Opts out of telemetry, and stops telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is created.
|
||||
|
||||
|
||||
RETURN VALUES
|
||||
=============
|
||||
|
||||
0 on success. A non-zero exit code indicates a failure occurred.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* ``telemd``\(1)
|
||||
* https://github.com/clearlinux/telemetrics-client
|
||||
* https://clearlinux.org/documentation/
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH TELEMD 1 "" "" ""
|
||||
.SH NAME
|
||||
telemd \- Telemetry client service
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBtelemd\fP <flags>
|
||||
.sp
|
||||
\fB/etc/telemetrics/telemetrics.conf\fP
|
||||
.sp
|
||||
\fB/usr/share/defaults/telemetrics/telemetrics.conf\fP
|
||||
.sp
|
||||
\fB/etc/telemetrics/opt\-in\-static\-machine\-id\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
The \fBtelemd\fP program delivers locally generated telemetry records to a remote
|
||||
telemetry service. Telemetry data can be in any format, and is relayed as\-is.
|
||||
.SH OPTIONS
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fB\-f\fP, \fB\-\-config_file\fP [<file>]:
|
||||
Configuration file. This overides the other parameters.
|
||||
.IP \(bu 2
|
||||
\fB\-h\fP, \fB\-\-help\fP:
|
||||
Display this help message.
|
||||
.IP \(bu 2
|
||||
\fB\-V\fP, \fB\-\-version\fP:
|
||||
Print the program version.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH FILES
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fB/usr/share/defaults/telemetrics/telemetrics.conf\fP
|
||||
.INDENT 2.0
|
||||
.INDENT 3.5
|
||||
If no custom configuration file is found, \fBtelemd\fP uses the
|
||||
settings in this file.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.IP \(bu 2
|
||||
\fB/etc/telemetrics/telemetrics.conf\fP
|
||||
.INDENT 2.0
|
||||
.INDENT 3.5
|
||||
Custom configuration file that \fBtelemd\fP reads. See \fBtelemetrics.conf\fP(5).
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.IP \(bu 2
|
||||
\fB/etc/telemetrics/opt\-in\-static\-machine\-id\fP
|
||||
.INDENT 2.0
|
||||
.INDENT 3.5
|
||||
If this file exists, the first line of this file will be sent to
|
||||
the server as the machine ID. Otherwise, the machine ID will be
|
||||
random and changed regularly.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH EXIT STATUS
|
||||
.sp
|
||||
0 when no errors occurred. A non\-zero exit status indicates a failure occurred.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBtelemetry\fP(3)
|
||||
.IP \(bu 2
|
||||
\fBtelemetrics.conf\fP(5)
|
||||
.IP \(bu 2
|
||||
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
|
||||
.IP \(bu 2
|
||||
\fI\%https://clearlinux.org/documentation/\fP
|
||||
.UNINDENT
|
||||
.SH COPYRIGHT
|
||||
(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
@@ -0,0 +1,78 @@
|
||||
======
|
||||
telemd
|
||||
======
|
||||
|
||||
------------------------
|
||||
Telemetry client service
|
||||
------------------------
|
||||
|
||||
:Copyright: \(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
:Manual section: 1
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``telemd`` \<flags\>
|
||||
|
||||
``/etc/telemetrics/telemetrics.conf``
|
||||
|
||||
``/usr/share/defaults/telemetrics/telemetrics.conf``
|
||||
|
||||
``/etc/telemetrics/opt-in-static-machine-id``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
The ``telemd`` program delivers locally generated telemetry records to a remote
|
||||
telemetry service. Telemetry data can be in any format, and is relayed as-is.
|
||||
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
* ``-f``, ``--config_file`` \[\<file\>\]:
|
||||
Configuration file. This overides the other parameters.
|
||||
|
||||
* ``-h``, ``--help``:
|
||||
Display this help message.
|
||||
|
||||
* ``-V``, ``--version``:
|
||||
Print the program version.
|
||||
|
||||
|
||||
FILES
|
||||
=====
|
||||
|
||||
* ``/usr/share/defaults/telemetrics/telemetrics.conf``
|
||||
|
||||
If no custom configuration file is found, ``telemd`` uses the
|
||||
settings in this file.
|
||||
|
||||
* ``/etc/telemetrics/telemetrics.conf``
|
||||
|
||||
Custom configuration file that ``telemd`` reads. See ``telemetrics.conf``\(5).
|
||||
|
||||
|
||||
* ``/etc/telemetrics/opt-in-static-machine-id``
|
||||
|
||||
If this file exists, the first line of this file will be sent to
|
||||
the server as the machine ID. Otherwise, the machine ID will be
|
||||
random and changed regularly.
|
||||
|
||||
|
||||
EXIT STATUS
|
||||
===========
|
||||
|
||||
0 when no errors occurred. A non-zero exit status indicates a failure occurred.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* ``telemetry``\(3)
|
||||
* ``telemetrics.conf``\(5)
|
||||
* https://github.com/clearlinux/telemetrics-client
|
||||
* https://clearlinux.org/documentation/
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH TELEMETRICS.CONF 5 "" "" ""
|
||||
.SH NAME
|
||||
telemetrics.conf \- Telemetry service configuration file
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fB/etc/telemetrics/telemetrics.conf\fP
|
||||
.sp
|
||||
\fB/usr/share/defaults/telemetrics/telemetrics.conf\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
This file contains configuration parameters for the \fBtelemd\fP(1) telemetry
|
||||
service daemon. The daemon reads this file at startup if it exists.
|
||||
.SH SYNTAX
|
||||
.sp
|
||||
The configuration file contains \fBkey=value\fP pairs, formatted as plain
|
||||
text, one option per line. Comments can be added by preceding them with the
|
||||
\fB#\fP character. All configuration options should be in a section marked
|
||||
with \fB[settings]\fP\&.
|
||||
.SH OPTIONS
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBserver=<url>\fP
|
||||
.sp
|
||||
Server URL including protocol designator.
|
||||
.IP \(bu 2
|
||||
\fBsocket_path=<path>\fP
|
||||
.sp
|
||||
Path to the socket that \fItelemd\fP will listen on.
|
||||
.IP \(bu 2
|
||||
\fBcainfo=<path>\fP
|
||||
.sp
|
||||
Certificate file to use for validation of SSL endpoint.
|
||||
.IP \(bu 2
|
||||
\fBtidheader=<header>\fP
|
||||
.sp
|
||||
Telemetry ID in header format, usually \fBtidheader=X\-Telemetry\-TID:<uuid>\fP
|
||||
post header used to group records in ingestion service, which may be
|
||||
ingesting for more than one set of clients. Can be set to any string.
|
||||
.IP \(bu 2
|
||||
\fBrecord_expiry=<minutes>\fP
|
||||
.sp
|
||||
Record expiry time in minutes.
|
||||
.IP \(bu 2
|
||||
\fBspool_dir=<dir>\fP
|
||||
.sp
|
||||
Local spool directory used to store records being processed.
|
||||
.IP \(bu 2
|
||||
\fBspool_max_size=<kB>\fP
|
||||
.sp
|
||||
maximum size of the spool directory in kB. A value of \fB\-1\fP indicates
|
||||
no limit. The block size of the files in this directory is considered,
|
||||
and not the actual size of the record itself.
|
||||
.IP \(bu 2
|
||||
\fBspool_process_time=<seconds>\fP
|
||||
.sp
|
||||
Time in seconds for processing spool. Valid range: 120..3600. Values
|
||||
outside this range are clamped.
|
||||
.IP \(bu 2
|
||||
\fBrate_limit_enabled=<true|false>\fP
|
||||
.sp
|
||||
Enable rate limiting. If this is set to false then all rate\-limiting
|
||||
disabled. It is possible to disable each rate\-limit individually below.
|
||||
.IP \(bu 2
|
||||
\fBrecord_burst_limit=<limit>\fP
|
||||
.sp
|
||||
Rate limiting record burst limit. Valid Range: 0..\(ga\(gaINT_MAX\(ga\(ga, \-1 = disabled.
|
||||
.IP \(bu 2
|
||||
\fBrecord_window_length=<minutes>\fP
|
||||
.sp
|
||||
Rate limiting record window length in minutes. Valid Range: 0..59.
|
||||
.IP \(bu 2
|
||||
\fBbyte_burst_limit=<limit>\fP
|
||||
.sp
|
||||
Rate limiting byte burst limit. Valid Range: 0..\(gaINT_MAX\(ga, \-1 = disabled.
|
||||
.IP \(bu 2
|
||||
\fBbyte_window_length=<minutes>\fP
|
||||
.sp
|
||||
Rate limiting byte window length in minutes. Valid Range: 0..59.
|
||||
.IP \(bu 2
|
||||
\fBrate_limit_strategy=<strategy>\fP
|
||||
.sp
|
||||
Rate limit strategy \- what to do with record if rate\-limiting prevents
|
||||
delivery over network. Valid stategies: \fBspool\fP, \fBdrop\fP\&.
|
||||
.UNINDENT
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBtelemd\fP(1)
|
||||
.IP \(bu 2
|
||||
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
|
||||
.IP \(bu 2
|
||||
\fI\%https://clearlinux.org/documentation/\fP
|
||||
.UNINDENT
|
||||
.SH COPYRIGHT
|
||||
(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
@@ -0,0 +1,110 @@
|
||||
================
|
||||
telemetrics.conf
|
||||
================
|
||||
|
||||
------------------------------------
|
||||
Telemetry service configuration file
|
||||
------------------------------------
|
||||
|
||||
:Copyright: \(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
:Manual section: 5
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``/etc/telemetrics/telemetrics.conf``
|
||||
|
||||
``/usr/share/defaults/telemetrics/telemetrics.conf``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
This file contains configuration parameters for the ``telemd``\(1) telemetry
|
||||
service daemon. The daemon reads this file at startup if it exists.
|
||||
|
||||
|
||||
SYNTAX
|
||||
======
|
||||
|
||||
The configuration file contains ``key=value`` pairs, formatted as plain
|
||||
text, one option per line. Comments can be added by preceding them with the
|
||||
``#`` character. All configuration options should be in a section marked
|
||||
with ``[settings]``.
|
||||
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
- ``server=<url>``
|
||||
|
||||
Server URL including protocol designator.
|
||||
|
||||
- ``socket_path=<path>``
|
||||
|
||||
Path to the socket that `telemd` will listen on.
|
||||
|
||||
- ``cainfo=<path>``
|
||||
|
||||
Certificate file to use for validation of SSL endpoint.
|
||||
|
||||
- ``tidheader=<header>``
|
||||
|
||||
Telemetry ID in header format, usually ``tidheader=X-Telemetry-TID:<uuid>``
|
||||
post header used to group records in ingestion service, which may be
|
||||
ingesting for more than one set of clients. Can be set to any string.
|
||||
|
||||
- ``record_expiry=<minutes>``
|
||||
|
||||
Record expiry time in minutes.
|
||||
|
||||
- ``spool_dir=<dir>``
|
||||
|
||||
Local spool directory used to store records being processed.
|
||||
|
||||
- ``spool_max_size=<kB>``
|
||||
|
||||
maximum size of the spool directory in kB. A value of ``-1`` indicates
|
||||
no limit. The block size of the files in this directory is considered,
|
||||
and not the actual size of the record itself.
|
||||
|
||||
- ``spool_process_time=<seconds>``
|
||||
|
||||
Time in seconds for processing spool. Valid range: 120..3600. Values
|
||||
outside this range are clamped.
|
||||
|
||||
- ``rate_limit_enabled=<true|false>``
|
||||
|
||||
Enable rate limiting. If this is set to false then all rate-limiting
|
||||
disabled. It is possible to disable each rate-limit individually below.
|
||||
|
||||
- ``record_burst_limit=<limit>``
|
||||
|
||||
Rate limiting record burst limit. Valid Range: 0..``INT_MAX``, -1 = disabled.
|
||||
|
||||
- ``record_window_length=<minutes>``
|
||||
|
||||
Rate limiting record window length in minutes. Valid Range: 0..59.
|
||||
|
||||
- ``byte_burst_limit=<limit>``
|
||||
|
||||
Rate limiting byte burst limit. Valid Range: 0..`INT_MAX`, -1 = disabled.
|
||||
|
||||
- ``byte_window_length=<minutes>``
|
||||
|
||||
Rate limiting byte window length in minutes. Valid Range: 0..59.
|
||||
|
||||
- ``rate_limit_strategy=<strategy>``
|
||||
|
||||
Rate limit strategy - what to do with record if rate-limiting prevents
|
||||
delivery over network. Valid stategies: ``spool``, ``drop``.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* ``telemd``\(1)
|
||||
* https://github.com/clearlinux/telemetrics-client
|
||||
* https://clearlinux.org/documentation/
|
||||
|
||||
+81
-12
@@ -1,15 +1,84 @@
|
||||
.TH TELEMETRY 3 "April 2015" Telemetrics
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH TELEMETRY 3 "" "" ""
|
||||
.SH NAME
|
||||
telemetry \- Telemetry record creation and sending
|
||||
telemetry \- C programming interface for telemetrics-client
|
||||
.
|
||||
.nr rst2man-indent-level 0
|
||||
.
|
||||
.de1 rstReportMargin
|
||||
\\$1 \\n[an-margin]
|
||||
level \\n[rst2man-indent-level]
|
||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
-
|
||||
\\n[rst2man-indent0]
|
||||
\\n[rst2man-indent1]
|
||||
\\n[rst2man-indent2]
|
||||
..
|
||||
.de1 INDENT
|
||||
.\" .rstReportMargin pre:
|
||||
. RS \\$1
|
||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
||||
. nr rst2man-indent-level +1
|
||||
.\" .rstReportMargin post:
|
||||
..
|
||||
.de UNINDENT
|
||||
. RE
|
||||
.\" indent \\n[an-margin]
|
||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.nr rst2man-indent-level -1
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.SH SYNOPSIS
|
||||
#include <telemetry.h>
|
||||
.sp
|
||||
tm_create_record()
|
||||
.br
|
||||
tm_set_payload()
|
||||
.br
|
||||
tm_send_record()
|
||||
.br
|
||||
tm_set_config_File()
|
||||
|
||||
|
||||
\fB#include "telemetry.h"\fP
|
||||
.sp
|
||||
\fBstruct telem_ref { struct telem_record *record; };\fP
|
||||
.sp
|
||||
\fBint tm_create_record(struct telem_ref **t_ref, uint32_t severity, char *classification, uint32_t payload_version)\fP
|
||||
.sp
|
||||
\fBint tm_set_payload(struct telem_ref *t_ref, char *payload)\fP
|
||||
.sp
|
||||
\fBint tm_send_record(struct telem_ref *t_ref)\fP
|
||||
.sp
|
||||
\fBvoid tm_free_record(struct telem_ref *t_ref)\fP
|
||||
.sp
|
||||
\fBvoid tm_set_config_file(char *c_file)\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
The functions in the telemetry library facilitate the delivery of
|
||||
telemetry data to the \fBtelemd\fP(1) service.
|
||||
.sp
|
||||
The function \fBtm_create_record()\fP initializes a telemetry record and
|
||||
sets the severity and classification of that record, as well as the
|
||||
payload version number. The memory needed to store the telemetry record
|
||||
is allocated and should be freed with \fBtm_free_record()\fP when no longer
|
||||
needed.
|
||||
.sp
|
||||
The function \fBtm_set_payload()\fP attaches the provided telemetry record
|
||||
data to the telemetry record. The current maximum payload size is 8192b.
|
||||
.sp
|
||||
The function \fBtm_send_record()\fP delivers the record to the local
|
||||
\fBtelemd\fP(1) service.
|
||||
.sp
|
||||
The function \fBtm_set_config_file()\fP can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
All these functions return \fB0\fP on success, or a non\-zero return value
|
||||
if an error occurred. The functions \fBtm_free_record()\fP and \fBtm_set_config_file()\fP
|
||||
do not return any values.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
\fBtelemd\fP(1)
|
||||
.IP \(bu 2
|
||||
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
|
||||
.IP \(bu 2
|
||||
\fI\%https://clearlinux.org/documentation/\fP
|
||||
.UNINDENT
|
||||
.SH COPYRIGHT
|
||||
(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
=========
|
||||
telemetry
|
||||
=========
|
||||
|
||||
----------------------------------------------
|
||||
C programming interface for telemetrics-client
|
||||
----------------------------------------------
|
||||
|
||||
:Copyright: \(C) 2017 Intel Corporation, CC-BY-SA-3.0
|
||||
:Manual section: 3
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
``#include "telemetry.h"``
|
||||
|
||||
``struct telem_ref { struct telem_record *record; };``
|
||||
|
||||
``int tm_create_record(struct telem_ref **t_ref, uint32_t severity, char *classification, uint32_t payload_version)``
|
||||
|
||||
``int tm_set_payload(struct telem_ref *t_ref, char *payload)``
|
||||
|
||||
``int tm_send_record(struct telem_ref *t_ref)``
|
||||
|
||||
``void tm_free_record(struct telem_ref *t_ref)``
|
||||
|
||||
``void tm_set_config_file(char *c_file)``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
The functions in the telemetry library facilitate the delivery of
|
||||
telemetry data to the ``telemd``\(1) service.
|
||||
|
||||
The function ``tm_create_record()`` initializes a telemetry record and
|
||||
sets the severity and classification of that record, as well as the
|
||||
payload version number. The memory needed to store the telemetry record
|
||||
is allocated and should be freed with ``tm_free_record()`` when no longer
|
||||
needed.
|
||||
|
||||
The function ``tm_set_payload()`` attaches the provided telemetry record
|
||||
data to the telemetry record. The current maximum payload size is 8192b.
|
||||
|
||||
The function ``tm_send_record()`` delivers the record to the local
|
||||
``telemd``\(1) service.
|
||||
|
||||
The function ``tm_set_config_file()`` can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
|
||||
|
||||
RETURN VALUES
|
||||
=============
|
||||
|
||||
All these functions return ``0`` on success, or a non-zero return value
|
||||
if an error occurred. The functions ``tm_free_record()`` and ``tm_set_config_file()``
|
||||
do not return any values.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* ``telemd``\(1)
|
||||
* https://github.com/clearlinux/telemetrics-client
|
||||
* https://clearlinux.org/documentation/
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.so man3/telemetry.3
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.so man3/telemetry.3
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.so man3/telemetry.3
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.so man3/telemetry.3
|
||||
|
||||
@@ -14,6 +14,6 @@ if [ "$?" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
find .. -path "../*/*.[ch]" -exec uncrustify {} -c tm.cfg --no-backup \;
|
||||
find .. -path "../*/*.[ch]" ! -path "../src/nica/*" -exec uncrustify {} -c tm.cfg --no-backup \;
|
||||
|
||||
# vi: ts=8 sw=2 sts=2 et tw=80
|
||||
|
||||
+14
-5
@@ -23,6 +23,8 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "configuration.h"
|
||||
#include "util.h"
|
||||
@@ -44,7 +46,8 @@ const char *config_key_int[] = { NULL, "record_expiry", "spool_max_size",
|
||||
"byte_window_length", "record_burst_limit",
|
||||
"byte_burst_limit", NULL };
|
||||
|
||||
const char *config_key_bool[] = { NULL, "rate_limit_enabled", NULL };
|
||||
const char *config_key_bool[] = { NULL, "rate_limit_enabled",
|
||||
"daemon_recycling_enabled", NULL };
|
||||
|
||||
static struct configuration config = { { 0 }, { 0 }, { 0 }, false, NULL };
|
||||
|
||||
@@ -89,7 +92,7 @@ bool read_config_from_file(char *config_file, struct configuration *config)
|
||||
|
||||
keyfile = g_key_file_new();
|
||||
|
||||
if (!g_key_file_load_from_file(keyfile, (gchar *)config_file, flags, &error)) {
|
||||
if (!g_key_file_load_from_file(keyfile, config_file, flags, &error)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "ERR: Failed to read config file: %s\n",
|
||||
error->message);
|
||||
@@ -132,11 +135,11 @@ void initialize_config(void)
|
||||
|
||||
/* No config file provided on command line */
|
||||
if (!config_file) {
|
||||
if (g_file_test(etc_config_file, G_FILE_TEST_IS_REGULAR)) {
|
||||
if (access(etc_config_file, R_OK) == 0) {
|
||||
config_file = etc_config_file;
|
||||
} else {
|
||||
if (g_file_test(default_config_file,
|
||||
G_FILE_TEST_IS_REGULAR)) {
|
||||
if (access(default_config_file,
|
||||
R_OK) == 0) {
|
||||
config_file = default_config_file;
|
||||
} else {
|
||||
/* If there is no default config, exit with failure */
|
||||
@@ -334,4 +337,10 @@ const char *rate_limit_strategy_config()
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool daemon_recycling_enabled_config(void)
|
||||
{
|
||||
initialize_config();
|
||||
return config.boolValues[CONF_DAEMON_RECYCLING_ENABLED];
|
||||
}
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
@@ -46,6 +46,7 @@ enum config_int_keys {
|
||||
enum config_bool_keys {
|
||||
CONF_BOOL_MIN = 0,
|
||||
CONF_RATE_LIMIT_ENABLED,
|
||||
CONF_DAEMON_RECYCLING_ENABLED,
|
||||
CONF_BOOL_MAX
|
||||
};
|
||||
|
||||
@@ -113,4 +114,7 @@ const char *get_cainfo_config(void);
|
||||
/* Gets tidheader */
|
||||
const char *get_tidheader_config(void);
|
||||
|
||||
/* Gets whether recycling is enabled */
|
||||
bool daemon_recycling_enabled_config(void);
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
@@ -35,3 +35,6 @@ rate_limit_enabled=true
|
||||
|
||||
#rate limit strategy if record not send
|
||||
rate_limit_strategy=spool
|
||||
|
||||
#daemon recycling enabled
|
||||
daemon_recycling_enabled=true
|
||||
|
||||
@@ -51,3 +51,7 @@ byte_window_length=20
|
||||
# Valid stategies: spool, drop
|
||||
rate_limit_strategy=spool
|
||||
|
||||
# daemon recycling enabled - if daemon has been running for a while (2 hours),
|
||||
# has not any client nor spool data, then it exits.
|
||||
# this is to ensure that latest code runs.
|
||||
daemon_recycling_enabled=true
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef TM_LOG_SYSTEMD
|
||||
#ifdef HAVE_SYSTEMD_SD_JOURNAL_H
|
||||
|
||||
/* Certain static analysis tools do not understand GCC's __INCLUDE_LEVEL__
|
||||
@@ -32,6 +33,7 @@
|
||||
#endif
|
||||
|
||||
#include <systemd/sd-journal.h>
|
||||
#endif
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@@ -79,7 +81,7 @@
|
||||
#ifdef TM_LOG_STDERR
|
||||
#define telem_log(priority, ...) do { \
|
||||
if (priority <= MAX_LOG_LEVEL) { \
|
||||
fprintf(stderr, __VA_ARGS__ ); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0);
|
||||
#endif
|
||||
@@ -88,10 +90,10 @@
|
||||
#define telem_perror(msg) sd_journal_perror(msg)
|
||||
#endif
|
||||
#ifdef TM_LOG_SYSLOG
|
||||
#define telem_perror(msg) syslog(LOG_ERR, msg ": %s", strerror(errno))
|
||||
#define telem_perror(msg) syslog(LOG_ERR, msg ": %s\n", strerror(errno))
|
||||
#endif
|
||||
#ifdef TM_LOG_STDERR
|
||||
#define telem_perror(msg) fprintf(stderr, ": %s", msg)
|
||||
#define telem_perror(msg) fprintf(stderr, "ERROR: " msg ": %s\n", strerror(errno))
|
||||
#endif
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
+3
-1
@@ -232,6 +232,8 @@ int main(int argc, char **argv)
|
||||
time_t last_spool_run_time = time(NULL);
|
||||
time_t last_daemon_start_time = time(NULL);
|
||||
|
||||
bool daemon_recycling_enabled = daemon_recycling_enabled_config();
|
||||
|
||||
ret = update_machine_id();
|
||||
if (ret == -1) {
|
||||
telem_log(LOG_ERR, "Unable to update machine id\n");
|
||||
@@ -336,7 +338,7 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
time_t now = time(NULL);
|
||||
/* If spool is empty and time to recycle the daemon has elapsed*/
|
||||
if ((daemon.current_spool_size == 0) &&
|
||||
if (daemon_recycling_enabled && (daemon.current_spool_size == 0) &&
|
||||
difftime(now, last_daemon_start_time) >= TM_DAEMON_EXIT_TIME) {
|
||||
/* Exit */
|
||||
telem_log(LOG_INFO, "Daemon exiting for recycling\n");
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
noinst_HEADERS += \
|
||||
%D%/macros.h \
|
||||
%D%/nc-string.h
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of libnica.
|
||||
*
|
||||
* Copyright © 2016-2017 Intel Corporation
|
||||
*
|
||||
* libnica is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#define _nica_public_ __attribute__((visibility("default")))
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 expandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=true:
|
||||
*/
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of libnica.
|
||||
*
|
||||
* Copyright © 2016-2017 Intel Corporation
|
||||
*
|
||||
* libnica is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nc-string.h"
|
||||
|
||||
nc_string *nc_string_dup(const char *str)
|
||||
{
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
struct nc_string_t *st = calloc(1, sizeof(struct nc_string_t));
|
||||
if (!st) {
|
||||
return NULL;
|
||||
}
|
||||
st->len = asprintf(&st->str, "%s", str);
|
||||
if (st->len < 0 || !st->str) {
|
||||
free(st);
|
||||
return NULL;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
nc_string *nc_string_dup_printf(const char *ptn, ...)
|
||||
{
|
||||
if (!ptn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nc_string_t *st = calloc(1, sizeof(struct nc_string_t));
|
||||
if (!st) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_list va;
|
||||
va_start(va, ptn);
|
||||
|
||||
st->len = vasprintf(&st->str, ptn, va);
|
||||
if (st->len < 0 || !st->str) {
|
||||
free(st);
|
||||
st = NULL;
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
va_end(va);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
nc_string *nc_string_append_printf(nc_string *st, const char *ptn, ...)
|
||||
{
|
||||
char *newstr;
|
||||
char *newstr2;
|
||||
int ret;
|
||||
|
||||
if (!ptn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_list va;
|
||||
va_start(va, ptn);
|
||||
|
||||
ret = vasprintf(&newstr, ptn, va);
|
||||
if (ret <= 0)
|
||||
newstr = strdup("");
|
||||
|
||||
st->len = asprintf(&newstr2, "%s%s", st->str, newstr);
|
||||
free(st->str);
|
||||
st->str = newstr2;
|
||||
free(newstr);
|
||||
va_end(va);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
bool nc_string_cat(nc_string *s, const char *append)
|
||||
{
|
||||
char *p = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (!s || !append) {
|
||||
return false;
|
||||
}
|
||||
if (!s->str) {
|
||||
return false;
|
||||
}
|
||||
len = asprintf(&p, "%s%s", s->str, append);
|
||||
if (!p || len < s->len) {
|
||||
return false;
|
||||
}
|
||||
free(s->str);
|
||||
s->str = p;
|
||||
s->len = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nc_string_prepend(nc_string *s, const char *prepend)
|
||||
{
|
||||
char *p = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (!s || !prepend) {
|
||||
return false;
|
||||
}
|
||||
if (!s->str) {
|
||||
return false;
|
||||
}
|
||||
len = asprintf(&p, "%s%s", prepend, s->str);
|
||||
if (!p || len < s->len) {
|
||||
return false;
|
||||
}
|
||||
free(s->str);
|
||||
s->str = p;
|
||||
s->len = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 expandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=true:
|
||||
*/
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* This file is part of libnica.
|
||||
*
|
||||
* Copyright © 2016-2017 Intel Corporation
|
||||
*
|
||||
* libnica is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
/**
|
||||
* Safely represent and store a buffer as a string
|
||||
*/
|
||||
typedef struct nc_string_t {
|
||||
char *str; /**<Buffer holding a NUL-terminated string */
|
||||
int len; /**<Current length of the string */
|
||||
} nc_string;
|
||||
|
||||
/**
|
||||
* Construct a new string using printf style syntax
|
||||
*
|
||||
* @param format Printf-style format string
|
||||
* @param ... Variable arguments
|
||||
*
|
||||
* @return a new nc_string if allocation succeeded, otherwise NULL
|
||||
*/
|
||||
_nica_public_ nc_string *nc_string_dup_printf(const char *format, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
|
||||
|
||||
_nica_public_ nc_string *nc_string_append_printf(nc_string *st, const char *ptn, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
||||
/**
|
||||
* Duplicate a string into a new NUL-terminated nc_string
|
||||
*
|
||||
* @param str Pointer to a string
|
||||
* @return a new nc_string if allocation succeeded, otherwise NULL
|
||||
*/
|
||||
_nica_public_ nc_string *nc_string_dup(const char *str);
|
||||
|
||||
/**
|
||||
* Free an existing string and its contents
|
||||
*
|
||||
* @param str Pointer to an existing string
|
||||
*/
|
||||
static inline void nc_string_free(nc_string *str)
|
||||
{
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
if (str->str) {
|
||||
free(str->str);
|
||||
}
|
||||
free(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the contents of 'append' into the given nc_string
|
||||
*
|
||||
* @param str Pointer to a valid nc_string
|
||||
* @param append Text to append into the nc_string
|
||||
*
|
||||
* @return a boolean value indicating success
|
||||
*/
|
||||
_nica_public_ bool nc_string_cat(nc_string *str, const char *append);
|
||||
|
||||
_nica_public_ bool nc_string_prepend(nc_string *s, const char *prepend);
|
||||
|
||||
|
||||
/**
|
||||
* Determine if string A is equal to string B
|
||||
*
|
||||
* @note This function will not check beyond the length of string A
|
||||
*
|
||||
* @param a string to check
|
||||
* @param b string to check against
|
||||
* @return a boolean value, true if the strings match, otherwise false
|
||||
*/
|
||||
static inline bool nc_string_equal(nc_string *a, nc_string *b)
|
||||
{
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
if (!a->str || !b->str) {
|
||||
return false;
|
||||
}
|
||||
return strncmp(a->str, b->str, (size_t)a->len) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if string A is equal to string B
|
||||
*
|
||||
* @note This function will not check beyond the length of string A
|
||||
*
|
||||
* @param a string to check
|
||||
* @param b const char* string to check against
|
||||
* @return a boolean value, true if the strings match, otherwise false
|
||||
*/
|
||||
static inline bool nc_string_const_equal(nc_string *a, const char *b)
|
||||
{
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
if (!a->str) {
|
||||
return false;
|
||||
}
|
||||
return strncmp(a->str, b, (size_t)a->len) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper to obtain string length
|
||||
*
|
||||
* @note This will assert the string is not NULL, ensuring a termination.
|
||||
*
|
||||
* @return length of the given string
|
||||
*/
|
||||
static inline int ncstrlen(nc_string *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
return str->len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a string has the given suffix
|
||||
*
|
||||
* @param str Valid nc_string
|
||||
* @param suffix A suffix to check
|
||||
* @param len Length of the suffix
|
||||
*
|
||||
* @return True if @str has the given suffix
|
||||
*/
|
||||
static inline bool nc_string_has_suffix_const(nc_string *str, char *suffix, ssize_t len)
|
||||
{
|
||||
if (!str || !suffix) {
|
||||
return false;
|
||||
}
|
||||
if (len > str->len || len <= 0) {
|
||||
return false;
|
||||
}
|
||||
return (strncmp(str->str + (str->len - (len)), suffix, (size_t)len) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a string has the given prefix
|
||||
*
|
||||
* @param str Valid nc_string
|
||||
* @param prefix A prefix to check
|
||||
* @param len Length of the prefix
|
||||
*
|
||||
* @return True if @str has the given prefix
|
||||
*/
|
||||
static inline bool nc_string_has_prefix_const(nc_string *str, char *prefix, ssize_t len)
|
||||
{
|
||||
if (!str || !prefix) {
|
||||
return false;
|
||||
}
|
||||
if (len > str->len || len <= 0) {
|
||||
return false;
|
||||
}
|
||||
return (strncmp(str->str, prefix, (size_t)len) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform inplace modification of a strip to return
|
||||
* a stripped pointer, that is, without start and end whitespace.
|
||||
*
|
||||
* This does not modify the length of the string.
|
||||
*/
|
||||
static inline char *nc_string_strip(nc_string *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!str || !str->str) {
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < str->len; i++) {
|
||||
if (str->str[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int j = str->len - 1; j > i; j--) {
|
||||
if (str->str[j] != ' ') {
|
||||
str->str[j + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return str->str + i;
|
||||
}
|
||||
/**
|
||||
* To be used only with compile time constants.
|
||||
*/
|
||||
#define nc_string_has_suffix(a, suff) nc_string_has_suffix_const(a, suff, (sizeof(suff) - 1))
|
||||
#define nc_string_has_prefix(a, pref) nc_string_has_prefix_const(a, pref, (sizeof(pref) - 1))
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 expandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=true:
|
||||
*/
|
||||
+281
-138
@@ -17,6 +17,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <grp.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
@@ -31,13 +32,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <libelf.h>
|
||||
#include <elfutils/libdwfl.h>
|
||||
|
||||
#include "nica/nc-string.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "probe.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
static Dwfl *d_core = NULL;
|
||||
@@ -53,10 +54,10 @@ static Dwfl *d_core = NULL;
|
||||
static char *debuginfo_path = "-/usr/lib/debug";
|
||||
|
||||
static unsigned int frame_counter = 0;
|
||||
static gchar *proc_name = NULL;
|
||||
static char *proc_name = NULL;
|
||||
static pid_t core_for_pid = 0;
|
||||
static GString *header = NULL;
|
||||
static gchar *errorstr = NULL;
|
||||
static nc_string *header = NULL;
|
||||
static char *errorstr = NULL;
|
||||
|
||||
static uint32_t unknown_severity = 2;
|
||||
static uint32_t default_severity = 3;
|
||||
@@ -84,9 +85,17 @@ static inline void tm_dwfl_err(const char *msg)
|
||||
telem_log(LOG_ERR, "%s: %s\n", msg, dwfl_errmsg(-1));
|
||||
}
|
||||
|
||||
static gchar *replace_exclamations(gchar *str)
|
||||
static char *replace_exclamations(char *str)
|
||||
{
|
||||
return g_strdelimit(str, "!", '/');
|
||||
char *c;
|
||||
while (1) {
|
||||
c = strchr(str, '!');
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
*c = '/';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static void drop_privs(void)
|
||||
@@ -176,6 +185,55 @@ static int temp_core_file(void)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* There are a number of initialization routines required to initialize the Elf
|
||||
* and Dwfl objects used by libdwfl to later process a core file. The argument
|
||||
* e_core is the address of an Elf pointer declared by the caller, and core_fd
|
||||
* is the open file descriptor for the core file.
|
||||
*/
|
||||
static int prepare_corefile(Elf **e_core, int core_fd)
|
||||
{
|
||||
// Cleanup previous corefile processing if needed
|
||||
if (d_core) {
|
||||
dwfl_end(d_core);
|
||||
}
|
||||
if (*e_core) {
|
||||
elf_end(*e_core);
|
||||
}
|
||||
|
||||
// Boilerplate initialization for elfutils (libdwfl)
|
||||
if (!(*e_core = elf_begin(core_fd, ELF_C_READ, NULL))) {
|
||||
tm_elf_err("Failed to get file descriptor for ELF core file");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(d_core = dwfl_begin(&cb))) {
|
||||
tm_dwfl_err("Failed to start new libdwfl session");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
int core_modules = 0;
|
||||
core_modules = dwfl_core_file_report(d_core, *e_core, NULL);
|
||||
if (core_modules == -1) {
|
||||
tm_dwfl_err("Failed to report modules for ELF core file");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (dwfl_report_end(d_core, NULL, NULL) != 0) {
|
||||
tm_dwfl_err("Failed to finish reporting modules");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((core_for_pid = dwfl_core_file_attach(d_core, *e_core)) < 0) {
|
||||
tm_dwfl_err("Failed to prepare libdwfl session for thread"
|
||||
" iteration");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This callback is invoked for every frame in a thread. From a Dwfl_Frame, we
|
||||
* are able to extract the program counter (PC), and from that, the procedure
|
||||
* name via a Dwfl_Module.
|
||||
@@ -185,15 +243,20 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
|
||||
Dwarf_Addr pc;
|
||||
Dwarf_Addr pc_adjusted;
|
||||
Dwfl_Module *module;
|
||||
Dwfl_Line *line;
|
||||
const char *procname;
|
||||
const char *modname;
|
||||
bool activation;
|
||||
GString **bt = (GString **)userdata;
|
||||
nc_string **bt = (nc_string **)userdata;
|
||||
|
||||
if (!dwfl_frame_pc(frame, &pc, &activation)) {
|
||||
errorstr = g_strdup_printf("Failed to find program counter for"
|
||||
" current frame: %s\n",
|
||||
dwfl_errmsg(-1));
|
||||
int ret;
|
||||
ret = asprintf(&errorstr, "Failed to find program counter for"
|
||||
" current frame: %s\n",
|
||||
dwfl_errmsg(-1));
|
||||
if (ret < 0) {
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
|
||||
@@ -210,8 +273,8 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
|
||||
module = dwfl_addrmodule(d_core, pc_adjusted);
|
||||
|
||||
if (!module) {
|
||||
errorstr = g_strdup("Failed to find module for current"
|
||||
" frame\n");
|
||||
errorstr = strdup("Failed to find module for current"
|
||||
" frame\n");
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
|
||||
@@ -219,41 +282,54 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
|
||||
NULL);
|
||||
procname = dwfl_module_addrname(module, pc_adjusted);
|
||||
|
||||
line = dwfl_module_getsrc(module, pc_adjusted);
|
||||
|
||||
if (procname && modname) {
|
||||
g_string_append_printf(*bt, "#%u %s() - [%s]\n",
|
||||
frame_counter++, procname, modname);
|
||||
nc_string_append_printf(*bt, "#%u %s() - [%s]",
|
||||
frame_counter++, procname, modname);
|
||||
} else if (modname) {
|
||||
g_string_append_printf(*bt, "#%u ??? - [%s]\n",
|
||||
frame_counter++, modname);
|
||||
nc_string_append_printf(*bt, "#%u ??? - [%s]",
|
||||
frame_counter++, modname);
|
||||
} else {
|
||||
// TODO: decide on "no symbol" representation
|
||||
g_string_append_printf(*bt, "#%u (no symbols)\n",
|
||||
frame_counter++);
|
||||
nc_string_append_printf(*bt, "#%u (no symbols)",
|
||||
frame_counter++);
|
||||
}
|
||||
|
||||
if (line) {
|
||||
const char *src;
|
||||
int lineno, linecol;
|
||||
src = dwfl_lineinfo(line, &pc_adjusted, &lineno, &linecol, NULL, NULL);
|
||||
if (src) {
|
||||
nc_string_append_printf(*bt, " - %s:%i", src, lineno);
|
||||
}
|
||||
}
|
||||
nc_string_append_printf(*bt, "\n");
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
static int thread_cb(Dwfl_Thread *thread, void *userdata)
|
||||
{
|
||||
int ret;
|
||||
GString **bt = (GString **)userdata;
|
||||
nc_string **bt = (nc_string **)userdata;
|
||||
pid_t tid;
|
||||
|
||||
tid = dwfl_thread_tid(thread);
|
||||
|
||||
g_string_append_printf(*bt, "\nBacktrace (TID %u):\n",
|
||||
(unsigned int)tid);
|
||||
nc_string_append_printf(*bt, "\nBacktrace (TID %u):\n",
|
||||
(unsigned int)tid);
|
||||
|
||||
ret = dwfl_thread_getframes(thread, frame_cb, userdata);
|
||||
|
||||
switch (ret) {
|
||||
case -1:
|
||||
errorstr = g_strdup_printf("Error while iterating"
|
||||
" through frames for thread"
|
||||
" %u: %s\n",
|
||||
(unsigned int)tid,
|
||||
dwfl_errmsg(-1));
|
||||
if (asprintf(&errorstr, "Error while iterating"
|
||||
" through frames for thread"
|
||||
" %u: %s\n",
|
||||
(unsigned int)tid,
|
||||
dwfl_errmsg(-1)) < 0) {
|
||||
errorstr = NULL;
|
||||
}
|
||||
return DWARF_CB_ABORT;
|
||||
case DWARF_CB_ABORT:
|
||||
/* already set the error string in frame_cb */
|
||||
@@ -269,14 +345,14 @@ static int thread_cb(Dwfl_Thread *thread, void *userdata)
|
||||
frame_counter = 0;
|
||||
|
||||
#if 0
|
||||
g_string_append_printf(*bt, "\nRegisters (TID %u):\nTODO\n", current,
|
||||
(unsigned int)tid);
|
||||
nc_string_append_printf(*bt, "\nRegisters (TID %u):\nTODO\n", current,
|
||||
(unsigned int)tid);
|
||||
#endif
|
||||
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
static bool send_data(GString **backtrace, uint32_t severity, char *class)
|
||||
static bool send_data(nc_string **backtrace, uint32_t severity, char *class)
|
||||
{
|
||||
struct telem_ref *handle = NULL;
|
||||
int ret;
|
||||
@@ -305,80 +381,133 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool in_clr_build(gchar *fullpath)
|
||||
/* This is the entry point for libdwfl to unwind the backtrace from the core
|
||||
* file. All data necessary for processing is referenced by d_core (a *Dwfl),
|
||||
* which must be initialized prior to calling this function. The callback
|
||||
* function for processing each core thread is passed as the second argument to
|
||||
* dwfl_getthreads(). The backtrace argument is the address of a pointer to a
|
||||
* nc_string object declared by the caller which stores the backtrace data as a
|
||||
* string.
|
||||
*/
|
||||
static int process_corefile(nc_string **backtrace)
|
||||
{
|
||||
if (*backtrace) {
|
||||
nc_string_free(*backtrace);
|
||||
}
|
||||
*backtrace = nc_string_dup("");
|
||||
|
||||
if (dwfl_getthreads(d_core, thread_cb, backtrace) != DWARF_CB_OK) {
|
||||
/* When errors occur during the unwinding, we reach this point.
|
||||
* If an error string is set for the particular error, send an
|
||||
* "error" record to capture at least a partial backtrace if
|
||||
* some frames were processed.
|
||||
*/
|
||||
if (errorstr != NULL) {
|
||||
telem_log(LOG_ERR, "%s", errorstr);
|
||||
nc_string_append_printf(header, "Error: %s", errorstr);
|
||||
nc_string_prepend(*backtrace, header->str);
|
||||
send_data(backtrace, error_severity, error_class);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool in_clr_build(char *fullpath)
|
||||
{
|
||||
// Global override for privacy filters
|
||||
if (access(TM_PRIVACY_FILTERS_OVERRIDE, F_OK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The build environment for Clear Linux packages is set up by 'mock',
|
||||
* and the chroot in which rpmbuild builds the packages has this prefix.
|
||||
*/
|
||||
if (g_regex_match_simple("^[!/]builddir[!/]build[!/]BUILD[!/]",
|
||||
fullpath, 0, 0) == TRUE) {
|
||||
if ((strstr(fullpath, "/builddir/build/BUILD/")) ||
|
||||
(strstr(fullpath, "!builddir!build!BUILD!"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool filter_binaries(gchar *fullpath)
|
||||
static bool is_banned_path(char *fullpath)
|
||||
{
|
||||
// Anything outside of /usr/, or in /usr/local/, we consider third-party
|
||||
if (g_regex_match_simple("^[!/]usr[!/]", fullpath, 0, 0) == FALSE) {
|
||||
return false;
|
||||
} else if (g_regex_match_simple("^[!/]usr[!/]local[!/]", fullpath,
|
||||
0, 0) == TRUE) {
|
||||
// Global override for privacy filters
|
||||
if (access(TM_PRIVACY_FILTERS_OVERRIDE, F_OK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Anything outside of /usr/, or in /usr/local/, we consider third-party
|
||||
|
||||
if ((strncmp(fullpath, "/usr/", 5) != 0) &&
|
||||
(strncmp(fullpath, "!usr!", 5) != 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((strncmp(fullpath, "/usr/local/", 11) == 0) ||
|
||||
(strncmp(fullpath, "!usr!local!", 11) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gchar *config_file = NULL;
|
||||
static gchar *core_file = NULL;
|
||||
static gchar *proc_path = NULL;
|
||||
static gint signal_num = -1;
|
||||
static gboolean version_p = FALSE;
|
||||
static gboolean verbose = FALSE;
|
||||
static char *config_file = NULL;
|
||||
static char *core_file = NULL;
|
||||
static char *proc_path = NULL;
|
||||
static long int signal_num = -1;
|
||||
static bool verbose = false;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "config-file", 'f', 0, G_OPTION_ARG_FILENAME, &config_file,
|
||||
"Path to configuration file (not implemented yet)", NULL },
|
||||
{ "core-file", 'c', 0, G_OPTION_ARG_FILENAME, &core_file,
|
||||
"Path to core file to process", NULL },
|
||||
{ "process-name", 'p', 0, G_OPTION_ARG_STRING, &proc_name,
|
||||
"Name of process for crash report (required)", NULL },
|
||||
{ "process-path", 'E', 0, G_OPTION_ARG_STRING, &proc_path,
|
||||
"Absolute path of crashed process, with ! or / delimiters", NULL },
|
||||
{ "signal", 's', 0, G_OPTION_ARG_INT, &signal_num,
|
||||
"Signal number that crashed the process", NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version_p,
|
||||
"Print the program version", NULL },
|
||||
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
|
||||
"Print the crash probe payload to stdout", NULL },
|
||||
{ NULL }
|
||||
static const struct option prog_opts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "config-file", required_argument, 0, 'f' },
|
||||
{ "core-file", required_argument, 0, 'c' },
|
||||
{ "process-name", required_argument, 0, 'p' },
|
||||
{ "process-path", required_argument, 0, 'E' },
|
||||
{ "signal", required_argument, 0, 's' },
|
||||
{ "version", no_argument, 0, 'V' },
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void free_glib_strings(void)
|
||||
static void print_help(void)
|
||||
{
|
||||
if (core_file) {
|
||||
g_free(core_file);
|
||||
}
|
||||
if (proc_name) {
|
||||
g_free(proc_name);
|
||||
}
|
||||
if (proc_path) {
|
||||
g_free(proc_path);
|
||||
}
|
||||
printf("Usage:\n");
|
||||
printf(" crashprobe [OPTIONS] - collect data from core files\n");
|
||||
printf("\n");
|
||||
printf("Help Options:\n");
|
||||
printf(" -h, --help Show help options\n");
|
||||
printf("\n");
|
||||
printf("Application Options:\n");
|
||||
printf(" -f, --config-file Path to configuration file (not implemented yet)\n");
|
||||
printf(" -c, --core-file Path to core file to process\n");
|
||||
printf(" -p, --process-name Name of process for crash report (required)\n");
|
||||
printf(" -E, --process-path Absolute path of crashed process, with ! or / delimiters\n");
|
||||
printf(" -s, --signal Signal number that crashed the process\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
printf(" -v, --verbose Print the crash payload to stdout\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Elf *e_core = NULL;
|
||||
int core_modules = 0;
|
||||
int ret = EXIT_FAILURE;
|
||||
int core_fd = STDIN_FILENO;
|
||||
GString *backtrace = NULL;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
nc_string *backtrace = NULL;
|
||||
|
||||
if (fcntl(STDERR_FILENO, F_GETFL) < 0) {
|
||||
// redirect stderr to avoid bad things to happen with
|
||||
// fd 2 when launched from kernel core pattern
|
||||
if (freopen("/dev/null", "w", stderr) == NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Since this program handles core files, make sure it does not produce
|
||||
// core files itself, or else it will be invoked endlessly...
|
||||
@@ -386,28 +515,58 @@ int main(int argc, char **argv)
|
||||
|
||||
drop_privs();
|
||||
|
||||
context = g_option_context_new("- collect data from core files");
|
||||
g_option_context_add_main_entries(context, options, NULL);
|
||||
g_option_context_set_translate_func(context, NULL, NULL, NULL);
|
||||
if (!g_option_context_parse(context, &argc, &argv, &error)) {
|
||||
g_print("Failed to parse options: %s\n", error->message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int opt;
|
||||
|
||||
if (version_p) {
|
||||
g_print(PACKAGE_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
while ((opt = getopt_long(argc, argv, "hf:c:p:E:s:Vv", prog_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_help();
|
||||
goto success;
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
goto success;
|
||||
case 'f':
|
||||
config_file = strdup(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
core_file = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
proc_name = strdup(optarg);
|
||||
break;
|
||||
case 'E':
|
||||
proc_path = strdup(optarg);
|
||||
break;
|
||||
case 's':
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
|
||||
signal_num = strtol(optarg, &endptr, 10);
|
||||
|
||||
if (errno != 0) {
|
||||
telem_perror("Failed to convert signal number");
|
||||
goto fail;
|
||||
}
|
||||
if (endptr && *endptr != '\0') {
|
||||
telem_log(LOG_ERR, "Invalid signal number. Must be an integer\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!proc_name) {
|
||||
g_print("Missing required -p option. See --help output\n");
|
||||
printf("Missing required -p option. See --help output\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (proc_path && in_clr_build(proc_path)) {
|
||||
telem_log(LOG_NOTICE, "Ignoring core (from mock build)\n");
|
||||
|
||||
backtrace = g_string_new("Crash from Clear package build\n");
|
||||
backtrace = nc_string_dup("Crash from Clear package build\n");
|
||||
|
||||
if (!send_data(&backtrace, unknown_severity, clr_build_class)) {
|
||||
goto fail;
|
||||
@@ -415,10 +574,10 @@ int main(int argc, char **argv)
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (proc_path && !filter_binaries(proc_path)) {
|
||||
if (proc_path && is_banned_path(proc_path)) {
|
||||
telem_log(LOG_NOTICE, "Ignoring core (third-party binary)\n");
|
||||
|
||||
backtrace = g_string_new("Crash from third party\n");
|
||||
backtrace = nc_string_dup("Crash from third party\n");
|
||||
|
||||
if (!send_data(&backtrace, unknown_severity, unknown_class)) {
|
||||
goto fail;
|
||||
@@ -452,62 +611,48 @@ int main(int argc, char **argv)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
g_print("Cannot process core file. Use the -c option,"
|
||||
" or pass the core file on stdin.\n");
|
||||
printf("Cannot process core file. Use the -c option,"
|
||||
" or pass the core file on stdin.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
elf_version(EV_CURRENT);
|
||||
|
||||
if (!(e_core = elf_begin(core_fd, ELF_C_READ, NULL))) {
|
||||
tm_elf_err("Failed to get file descriptor for ELF core file");
|
||||
if (prepare_corefile(&e_core, core_fd) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(d_core = dwfl_begin(&cb))) {
|
||||
tm_dwfl_err("Failed to start new libdwfl session");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
core_modules = dwfl_core_file_report(d_core, e_core, NULL);
|
||||
if (core_modules == -1) {
|
||||
tm_dwfl_err("Failed to report modules for ELF core file");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (dwfl_report_end(d_core, NULL, NULL) != 0) {
|
||||
tm_dwfl_err("Failed to finish reporting modules");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((core_for_pid = dwfl_core_file_attach(d_core, e_core)) < 0) {
|
||||
tm_dwfl_err("Failed to prepare libdwfl session for thread"
|
||||
" iteration");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
header = g_string_new(NULL);
|
||||
g_string_printf(header, "Process: %s\nPID: %u\n",
|
||||
proc_path ? replace_exclamations(proc_path) : proc_name,
|
||||
(unsigned int)core_for_pid);
|
||||
header = nc_string_dup_printf("Process: %s\nPID: %u\n",
|
||||
proc_path ? replace_exclamations(proc_path) : proc_name,
|
||||
(unsigned int)core_for_pid);
|
||||
|
||||
if (signal_num >= 0) {
|
||||
g_string_append_printf(header, "Signal: %d\n", signal_num);
|
||||
nc_string_append_printf(header, "Signal: %ld\n", signal_num);
|
||||
}
|
||||
|
||||
backtrace = g_string_new(NULL);
|
||||
if (dwfl_getthreads(d_core, thread_cb, &backtrace) != DWARF_CB_OK) {
|
||||
if (errorstr != NULL) {
|
||||
telem_log(LOG_ERR, "%s", errorstr);
|
||||
g_string_append_printf(header, "Error: %s", errorstr);
|
||||
g_string_prepend(backtrace, header->str);
|
||||
send_data(&backtrace, error_severity, error_class);
|
||||
}
|
||||
if (process_corefile(&backtrace) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
g_string_prepend(backtrace, header->str);
|
||||
/* On Clear Linux OS, missing symbols may appear if automatic debuginfo
|
||||
* downloads are still in flight. So if any missing symbols appear on
|
||||
* the first run (indicated by the presence of "??? - ["), wait 10
|
||||
* seconds and try again.
|
||||
*/
|
||||
if (strstr(backtrace->str, "??? - [")) {
|
||||
sleep(10);
|
||||
|
||||
if (prepare_corefile(&e_core, core_fd) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (process_corefile(&backtrace) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
nc_string_prepend(backtrace, header->str);
|
||||
|
||||
if (!send_data(&backtrace, default_severity, clr_class)) {
|
||||
goto fail;
|
||||
@@ -522,22 +667,20 @@ success:
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
fail:
|
||||
free_glib_strings();
|
||||
|
||||
if (context) {
|
||||
g_option_context_free(context);
|
||||
}
|
||||
free(core_file);
|
||||
free(proc_name);
|
||||
free(proc_path);
|
||||
|
||||
if (header) {
|
||||
g_string_free(header, TRUE);
|
||||
nc_string_free(header);
|
||||
}
|
||||
|
||||
if (backtrace) {
|
||||
g_string_free(backtrace, TRUE);
|
||||
nc_string_free(backtrace);
|
||||
}
|
||||
|
||||
if (errorstr) {
|
||||
g_free(errorstr);
|
||||
free(errorstr);
|
||||
}
|
||||
|
||||
if (d_core) {
|
||||
|
||||
+112
-75
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2015 Intel Corporation
|
||||
* Copyright 2015-2017 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms and conditions of the GNU Lesser General Public License, as
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -22,8 +23,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* Certain static analysis tools do not understand GCC's __INCLUDE_LEVEL__
|
||||
* macro; the conditional definition below is used to fix the build with
|
||||
* systemd's _sd-common.h, included by the public systemd headers, which rely on
|
||||
@@ -39,10 +38,10 @@
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
#include "nica/nc-string.h"
|
||||
#define BOOT_ID_LEN 33
|
||||
|
||||
static GString *payload = NULL;
|
||||
static nc_string *payload = NULL;
|
||||
static uint32_t severity = 2;
|
||||
static uint32_t payload_version = 1;
|
||||
static char error_class[30] = "org.clearlinux/journal/error";
|
||||
@@ -61,12 +60,11 @@ static inline void tm_journal_match_err(int ret)
|
||||
static void add_to_payload(const void *data, size_t length)
|
||||
{
|
||||
if (payload != NULL) {
|
||||
g_string_append_printf(payload, "%.*s", (int)length,
|
||||
(char *)data);
|
||||
nc_string_append_printf(payload, "%.*s\n", (int)length,
|
||||
(char *)data);
|
||||
} else {
|
||||
payload = g_string_new(NULL);
|
||||
g_string_printf(payload, "%.*s", (int)length,
|
||||
(char *)data);
|
||||
payload = nc_string_dup_printf("%.*s\n", (int)length,
|
||||
(char *)data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,16 +75,17 @@ static bool send_data(char *class)
|
||||
|
||||
if ((ret = tm_create_record(&handle, severity, class,
|
||||
payload_version)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to create record: %s",
|
||||
telem_log(LOG_ERR, "Failed to create record: %s\n",
|
||||
strerror(-ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gchar *payload_str = g_string_free(payload, FALSE);
|
||||
char *payload_str = strdup(payload->str);
|
||||
nc_string_free(payload);
|
||||
payload = NULL;
|
||||
|
||||
if ((ret = tm_set_payload(handle, (char *)payload_str)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to set payload: %s", strerror(-ret));
|
||||
telem_log(LOG_ERR, "Failed to set payload: %s\n", strerror(-ret));
|
||||
free(payload_str);
|
||||
tm_free_record(handle);
|
||||
goto fail;
|
||||
@@ -95,7 +94,7 @@ static bool send_data(char *class)
|
||||
free(payload_str);
|
||||
|
||||
if ((ret = tm_send_record(handle)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to send record: %s", strerror(-ret));
|
||||
telem_log(LOG_ERR, "Failed to send record: %s\n", strerror(-ret));
|
||||
tm_free_record(handle);
|
||||
goto fail;
|
||||
}
|
||||
@@ -122,6 +121,16 @@ static int read_new_entries(sd_journal *journal)
|
||||
|
||||
add_to_payload(data, length);
|
||||
|
||||
// For now, we send one record per log message, in case the
|
||||
// there is a large backlog of messages and we exceed the
|
||||
// payload size limit (8KB). And ignore errors, hoping that it's
|
||||
// a transient problem.
|
||||
|
||||
if (!send_data(error_class)) {
|
||||
telem_log(LOG_ERR, "Failed to send data. Ignoring.\n");
|
||||
return num_entries;
|
||||
}
|
||||
|
||||
num_entries++;
|
||||
}
|
||||
|
||||
@@ -148,19 +157,13 @@ static bool process_existing_entries(sd_journal *journal)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read_new_entries(journal)) {
|
||||
ret = read_new_entries(journal);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!payload) {
|
||||
telem_log(LOG_DEBUG, "No existing entries found\n");
|
||||
} else if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!send_data(error_class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,6 +188,33 @@ static bool get_boot_id(char **data)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define JOURNAL_MATCH(data) \
|
||||
do { \
|
||||
r = sd_journal_add_match(journal, data, 0); \
|
||||
if (r < 0) { \
|
||||
tm_journal_match_err(r); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define JOURNAL_AND \
|
||||
do { \
|
||||
r = sd_journal_add_conjunction(journal); \
|
||||
if (r < 0) { \
|
||||
tm_journal_match_err(r); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define JOURNAL_OR \
|
||||
do { \
|
||||
r = sd_journal_add_disjunction(journal); \
|
||||
if (r < 0) { \
|
||||
tm_journal_match_err(r); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
static bool add_filters(sd_journal *journal)
|
||||
{
|
||||
char *data = NULL;
|
||||
@@ -194,24 +224,29 @@ static bool add_filters(sd_journal *journal)
|
||||
return false;
|
||||
}
|
||||
|
||||
r = sd_journal_add_match(journal, data, 0);
|
||||
if (r < 0) {
|
||||
tm_journal_match_err(r);
|
||||
return false;
|
||||
}
|
||||
/* The semantics of how journal entry matching works is described in
|
||||
* detail in sd_journal_add_match(3).
|
||||
*
|
||||
* The matches declared here correspond to the logical expression:
|
||||
*
|
||||
* BOOTID && ((P0 || P1 || P2 || P3) || EXITED)
|
||||
*
|
||||
* BOOTID is short for _BOOT_ID=VAL, where VAL is the boot ID for the
|
||||
* current boot. P0, P1, etc stand for PRIORITY=0, etc. And EXITED is
|
||||
* short for EXIT_CODE=exited.
|
||||
*/
|
||||
|
||||
JOURNAL_MATCH(data);
|
||||
free(data);
|
||||
|
||||
r = sd_journal_add_match(journal, "SYSLOG_IDENTIFIER=crashprobe", 0);
|
||||
if (r < 0) {
|
||||
tm_journal_match_err(r);
|
||||
return false;
|
||||
}
|
||||
|
||||
r = sd_journal_add_match(journal, "PRIORITY=3", 0);
|
||||
if (r < 0) {
|
||||
tm_journal_match_err(r);
|
||||
return false;
|
||||
}
|
||||
JOURNAL_AND;
|
||||
// The four highest log levels, all indicating errors
|
||||
JOURNAL_MATCH("PRIORITY=0");
|
||||
JOURNAL_MATCH("PRIORITY=1");
|
||||
JOURNAL_MATCH("PRIORITY=2");
|
||||
JOURNAL_MATCH("PRIORITY=3");
|
||||
JOURNAL_OR;
|
||||
// Only set for service-level error conditions
|
||||
JOURNAL_MATCH("EXIT_CODE=exited");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -258,50 +293,56 @@ static bool process_journal(void)
|
||||
} else if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!send_data(error_class)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *config_file = NULL;
|
||||
static gboolean version_p = FALSE;
|
||||
static char *config_file = NULL;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "config-file", 'f', 0, G_OPTION_ARG_FILENAME, &config_file,
|
||||
"Path to configuration file (not implemented yet)", NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version_p,
|
||||
"Print the program version", NULL },
|
||||
{ NULL }
|
||||
static const struct option prog_opts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "config-file", required_argument, 0, 'f' },
|
||||
{ "version", no_argument, 0, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void free_glib_strings(void)
|
||||
static void print_help(void)
|
||||
{
|
||||
if (config_file) {
|
||||
g_free(config_file);
|
||||
}
|
||||
printf("Usage:\n");
|
||||
printf(" journalprobe [OPTIONS] - collect data from systemd journal\n");
|
||||
printf("\n");
|
||||
printf("Help Options:\n");
|
||||
printf(" -h, --help Show help options\n");
|
||||
printf("\n");
|
||||
printf("Application Options:\n");
|
||||
printf(" -f, --config-file Path to configuration file (not implemented yet)\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void free_strings(void)
|
||||
{
|
||||
free(config_file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = EXIT_FAILURE;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
int opt;
|
||||
|
||||
context = g_option_context_new("- collect data from systemd journal");
|
||||
g_option_context_add_main_entries(context, options, NULL);
|
||||
g_option_context_set_translate_func(context, NULL, NULL, NULL);
|
||||
if (!g_option_context_parse(context, &argc, &argv, &error)) {
|
||||
g_print("Failed to parse options: %s\n", error->message);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (version_p) {
|
||||
g_print(PACKAGE_VERSION "\n");
|
||||
goto success;
|
||||
while ((opt = getopt_long(argc, argv, "hf:V", prog_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_help();
|
||||
goto success;
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
goto success;
|
||||
case 'f':
|
||||
config_file = strdup(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!process_journal()) {
|
||||
@@ -311,18 +352,14 @@ int main(int argc, char **argv)
|
||||
success:
|
||||
ret = EXIT_SUCCESS;
|
||||
fail:
|
||||
free_glib_strings();
|
||||
free_strings();
|
||||
|
||||
if (journal) {
|
||||
sd_journal_close(journal);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
g_option_context_free(context);
|
||||
}
|
||||
|
||||
if (payload) {
|
||||
g_string_free(payload, TRUE);
|
||||
nc_string_free(payload);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "oops_parser.h"
|
||||
@@ -50,8 +51,9 @@ int main(void)
|
||||
|
||||
buflen = (size_t)log_size;
|
||||
|
||||
if (loopcount++ > 0 && buflen > MAX_BUF)
|
||||
if (loopcount++ > 0 && buflen > MAX_BUF) {
|
||||
buflen = MAX_BUF;
|
||||
}
|
||||
|
||||
// Gets the contents of the kernel ring buffer
|
||||
bufp = (char *)calloc(buflen, sizeof(char));
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <glib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
+9
-2
@@ -44,7 +44,9 @@ endif
|
||||
|
||||
|
||||
%C%_crashprobe_SOURCES = \
|
||||
%D%/crash_probe.c
|
||||
%D%/crash_probe.c \
|
||||
src/nica/nc-string.c \
|
||||
%D%/probe.h
|
||||
%C%_crashprobe_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
$(GLIB_CFLAGS)
|
||||
@@ -68,6 +70,7 @@ endif
|
||||
|
||||
%C%_pstoreprobe_SOURCES = \
|
||||
%D%/pstore_probe.c \
|
||||
src/nica/nc-string.c \
|
||||
%D%/oops_parser.c
|
||||
%C%_pstoreprobe_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
@@ -91,6 +94,7 @@ endif
|
||||
%D%/klog_scanner.c \
|
||||
%D%/klog_scanner.h \
|
||||
%D%/oops_parser.h \
|
||||
src/nica/nc-string.c \
|
||||
%D%/oops_parser.c
|
||||
%C%_klogscanner_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
@@ -120,7 +124,9 @@ endif
|
||||
|
||||
%C%_oopsprobe_SOURCES = \
|
||||
%D%/oops_probe.c \
|
||||
%D%/oops_parser.c
|
||||
%D%/oops_parser.c \
|
||||
src/nica/nc-string.c \
|
||||
%D%/probe.h
|
||||
%C%_oopsprobe_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
$(GLIB_CFLAGS)
|
||||
@@ -144,6 +150,7 @@ bin_PROGRAMS += \
|
||||
%D%/journalprobe
|
||||
|
||||
%C%_journalprobe_SOURCES = \
|
||||
src/nica/nc-string.c \
|
||||
%D%/journal.c
|
||||
%C%_journalprobe_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
|
||||
+99
-55
@@ -21,9 +21,11 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "oops_parser.h"
|
||||
#include "log.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define NUM_TAINTED_FLAGS 16
|
||||
|
||||
@@ -182,7 +184,7 @@ char *skip_timestamp(char *line)
|
||||
return start;
|
||||
}
|
||||
|
||||
char *skip_spaces(char *line)
|
||||
char *skip_space(char *line)
|
||||
{
|
||||
char *start = line;
|
||||
|
||||
@@ -192,6 +194,16 @@ char *skip_spaces(char *line)
|
||||
return start;
|
||||
}
|
||||
|
||||
char *skip_spaces(char *line)
|
||||
{
|
||||
char *start = line;
|
||||
|
||||
while (*start && isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
bool starts_with(const char *line, const char *line_end, const char *substr)
|
||||
{
|
||||
size_t substrlen = strlen(substr);
|
||||
@@ -344,7 +356,7 @@ void parse_single_line(char *line, size_t size)
|
||||
line_end = line + size;
|
||||
start = skip_log_level(line);
|
||||
start = skip_timestamp(start);
|
||||
start = skip_spaces(start);
|
||||
start = skip_space(start);
|
||||
|
||||
struct oops_pattern *pattern;
|
||||
if (oops_msg.length == 0) {
|
||||
@@ -376,13 +388,16 @@ void parse_single_line(char *line, size_t size)
|
||||
} else if (strstr(start, "[ end trace")) {
|
||||
end_found = true;
|
||||
} else if (!in_stack_dump) {
|
||||
if (starts_with(start, line_end, " [<") ||
|
||||
starts_with(start, line_end, " <") || //case : <EOI> [<fff73..]
|
||||
starts_with(start, line_end, "Call Trace:")) {
|
||||
// This line indicates the beginning of a stack trace;
|
||||
// the next line is most likely the topmost frame.
|
||||
if (starts_with(start, line_end, "Call Trace:")) {
|
||||
in_stack_dump = true;
|
||||
}
|
||||
} else if (in_stack_dump) {
|
||||
if (!(starts_with(start, line_end, " [") || starts_with(start, line_end, " <")) ||
|
||||
// In Linux 4.10+, the oops format changed, so we look
|
||||
// for a single leading space character to indicate a
|
||||
// stack frame line.
|
||||
if (!(starts_with(start, line_end, " ")) ||
|
||||
(strlen(start) < 8) ||
|
||||
(strstr(start, "Code:") != NULL) ||
|
||||
(strstr(start, "Instruction Dump::") != NULL)) {
|
||||
@@ -425,9 +440,20 @@ struct stack_frame {
|
||||
void stack_frame_append(struct stack_frame **head, struct stack_frame **tail, char *start)
|
||||
{
|
||||
/*
|
||||
* Format is as :
|
||||
* Format is:
|
||||
*
|
||||
* [<ffffffffa1002128>] do_one_initcall+0xb8/0x1e0
|
||||
* [<ffffffffa118784a>] ? __vunmap+0x9a/0x100
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* <IRQ> [<ffffffff816606a8>] dump_stack+0x19/0x1b
|
||||
*
|
||||
* OR (in 4.10+)
|
||||
*
|
||||
* do_one_initcall+0xb8/0x1e0
|
||||
* ? __vunmap+0x9a/0x100
|
||||
*
|
||||
*/
|
||||
|
||||
struct stack_frame *frame = NULL;
|
||||
@@ -436,18 +462,22 @@ void stack_frame_append(struct stack_frame **head, struct stack_frame **tail, ch
|
||||
if (!start) {
|
||||
return;
|
||||
}
|
||||
start = start + 2;
|
||||
|
||||
// Skip leading spaces
|
||||
start = skip_spaces(start);
|
||||
|
||||
//case: <IRQ> [<ffffffff816606a8>] dump_stack+0x19/0x1b
|
||||
if (!strncmp(start, "IRQ>", 4) || !strncmp(start, "NMI>", 4) ||
|
||||
!strncmp(start, "EOI>", 4) || !strncmp(start, "<EOE>>", 6)) {
|
||||
while (*start && *start != '[') {
|
||||
if (!strncmp(start, "<IRQ>", 5) || !strncmp(start, "<NMI>", 5) ||
|
||||
!strncmp(start, "<EOI>", 5) || !strncmp(start, "<<EOE>>", 7)) {
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (*start == '\0') {
|
||||
if (start && *start == '\0') {
|
||||
return;
|
||||
}
|
||||
start++;
|
||||
|
||||
// Skip intervening space
|
||||
start = skip_spaces(start);
|
||||
}
|
||||
|
||||
frame = malloc(sizeof(struct stack_frame));
|
||||
@@ -462,26 +492,29 @@ void stack_frame_append(struct stack_frame **head, struct stack_frame **tail, ch
|
||||
*tail = frame;
|
||||
}
|
||||
|
||||
if (*start == '<') {
|
||||
// Skip memory address parsing if the address is absent (as in Linux 4.10+).
|
||||
if (!strncmp(start, "[", 1)) {
|
||||
start++;
|
||||
frame->addr = (uint64_t)strtoll(start, (char **)&start, 16);
|
||||
} else {
|
||||
frame->addr = 0;
|
||||
}
|
||||
|
||||
/* Skip up to the space after the closing bracket */
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (*start) {
|
||||
start++;
|
||||
}
|
||||
if (*start == '<') {
|
||||
start++;
|
||||
frame->addr = (uint64_t)strtoll(start, (char **)&start, 16);
|
||||
} else {
|
||||
frame->addr = 0;
|
||||
}
|
||||
|
||||
if (*start && *start == '?') {
|
||||
start++;
|
||||
if (*start && isspace(*start)) {
|
||||
// Skip up to the space after the closing bracket
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (start && *start == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip intervening space
|
||||
start = skip_spaces(start);
|
||||
} else {
|
||||
frame->addr = 0;
|
||||
}
|
||||
|
||||
offset_ptr = strchr(start, '+');
|
||||
@@ -706,18 +739,19 @@ void parse_registers(char *line)
|
||||
|
||||
}
|
||||
|
||||
void append_registers_to_bt(GString **backtrace)
|
||||
void append_registers_to_bt(nc_string **backtrace)
|
||||
{
|
||||
struct reg_s *reg_entry = reg_head;
|
||||
|
||||
while (reg_entry != NULL) {
|
||||
#ifdef DEBUG
|
||||
g_string_append_printf(*backtrace, "Register %s: %" PRIx64 "\n", reg_entry->reg_name,
|
||||
reg_entry->reg_value);
|
||||
#else
|
||||
g_string_append_printf(*backtrace, "Register %s: %s\n", reg_entry->reg_name,
|
||||
reg_entry->reg_value ? "Non-zero" : "Zero");
|
||||
#endif
|
||||
// Global override for privacy filters
|
||||
if (access(TM_PRIVACY_FILTERS_OVERRIDE, F_OK) == 0) {
|
||||
nc_string_append_printf(*backtrace, "Register %s: %" PRIx64 "\n", reg_entry->reg_name,
|
||||
reg_entry->reg_value);
|
||||
} else {
|
||||
nc_string_append_printf(*backtrace, "Register %s: %s\n", reg_entry->reg_name,
|
||||
reg_entry->reg_value ? "Non-zero" : "Zero");
|
||||
}
|
||||
reg_entry = reg_entry->next;
|
||||
}
|
||||
|
||||
@@ -728,25 +762,36 @@ void append_registers_to_bt(GString **backtrace)
|
||||
}
|
||||
}
|
||||
|
||||
GString *parse_backtrace(struct oops_log_msg *msg)
|
||||
nc_string *parse_backtrace(struct oops_log_msg *msg)
|
||||
{
|
||||
struct stack_frame *head = NULL, *tail = NULL, *elem = NULL;
|
||||
//int in_stack_dump = 0;
|
||||
char *line = NULL;
|
||||
GString *backtrace = NULL;
|
||||
nc_string *backtrace = NULL;
|
||||
int frame_counter = 1;
|
||||
char *modules = NULL, *kernel_version = NULL, *tainted = NULL;
|
||||
// Since lines are processed from last to first, the stack trace lines
|
||||
// will appear first.
|
||||
bool in_trace = true;
|
||||
|
||||
for (int i = msg->length - 1; i > 0; i--) {
|
||||
/* Check if this line is part of a stack trace */
|
||||
line = msg->lines[i];
|
||||
|
||||
if (starts_with(line, line + strlen(line), " [") ||
|
||||
starts_with(line, line + strlen(line), " <")) {
|
||||
if (in_trace && starts_with(line, line + strlen(line), " ")) {
|
||||
stack_frame_append(&head, &tail, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We've reached the end of the stack trace
|
||||
if (starts_with(line, line + strlen(line), "Call Trace:")) {
|
||||
in_trace = false;
|
||||
}
|
||||
|
||||
// Stack trace lines must be consecutive, so if this point is
|
||||
// reached, we're outside the trace boundary.
|
||||
in_trace = false;
|
||||
|
||||
if (str_starts_with_casei(line, "Modules linked in: ")) {
|
||||
modules = line + strlen("Modules linked in: ");
|
||||
continue;
|
||||
@@ -760,23 +805,23 @@ GString *parse_backtrace(struct oops_log_msg *msg)
|
||||
parse_registers(line);
|
||||
}
|
||||
|
||||
backtrace = g_string_new(NULL);
|
||||
backtrace = nc_string_dup("");
|
||||
if (kernel_version) {
|
||||
g_string_append_printf(backtrace, "Kernel Version : %s\n", kernel_version);
|
||||
nc_string_append_printf(backtrace, "Kernel Version : %s\n", kernel_version);
|
||||
free(kernel_version);
|
||||
}
|
||||
|
||||
if (tainted) {
|
||||
g_string_append_printf(backtrace, "Tainted : %s\n", tainted);
|
||||
nc_string_append_printf(backtrace, "Tainted : %s\n", tainted);
|
||||
free(tainted);
|
||||
}
|
||||
|
||||
if (modules) {
|
||||
g_string_append_printf(backtrace, "Modules : %s\n", modules);
|
||||
nc_string_append_printf(backtrace, "Modules : %s\n", modules);
|
||||
}
|
||||
|
||||
if (head) {
|
||||
g_string_append_printf(backtrace, "Backtrace :\n");
|
||||
nc_string_append_printf(backtrace, "Backtrace :\n");
|
||||
}
|
||||
|
||||
if (reg_head) {
|
||||
@@ -784,24 +829,24 @@ GString *parse_backtrace(struct oops_log_msg *msg)
|
||||
}
|
||||
|
||||
for (elem = head; elem != NULL; elem = elem->next, frame_counter++) {
|
||||
g_string_append_printf(backtrace, "#%d %s - [%s]\n", frame_counter,
|
||||
elem->function ? elem->function : "???",
|
||||
elem->module);
|
||||
nc_string_append_printf(backtrace, "#%d %s - [%s]\n", frame_counter,
|
||||
elem->function ? elem->function : "???",
|
||||
elem->module);
|
||||
}
|
||||
|
||||
stack_frame_free(&head);
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
GString *parse_payload(struct oops_log_msg *msg)
|
||||
nc_string *parse_payload(struct oops_log_msg *msg)
|
||||
{
|
||||
GString *payload, *backtrace;
|
||||
nc_string *payload, *backtrace;
|
||||
|
||||
payload = g_string_new("Crash Report:\n");
|
||||
g_string_append_printf(payload, "Reason: %s\n", msg->lines[0]);
|
||||
payload = nc_string_dup("Crash Report:\n");
|
||||
nc_string_append_printf(payload, "Reason: %s\n", msg->lines[0]);
|
||||
backtrace = parse_backtrace(msg);
|
||||
g_string_append (payload, backtrace->str);
|
||||
g_string_free(backtrace, true);
|
||||
nc_string_cat(payload, backtrace->str);
|
||||
nc_string_free(backtrace);
|
||||
return payload;
|
||||
|
||||
}
|
||||
@@ -814,4 +859,3 @@ GString *parse_payload(struct oops_log_msg *msg)
|
||||
*/
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#define MAX_LINES 100
|
||||
|
||||
#include <glib.h>
|
||||
#include "nica/nc-string.h"
|
||||
#include <stdbool.h>
|
||||
#include <regex.h>
|
||||
|
||||
@@ -63,7 +63,7 @@ void oops_parser_init(oops_handler_t handler);
|
||||
void parse_single_line(char *line, size_t size);
|
||||
|
||||
/* Parses a payload from an oops msg*/
|
||||
GString *parse_payload(struct oops_log_msg *msg);
|
||||
nc_string *parse_payload(struct oops_log_msg *msg);
|
||||
|
||||
/* Given an entire oops log, verifies that the log is an oops log and
|
||||
* extracts the lines into an oops struct.
|
||||
@@ -74,4 +74,3 @@ bool handle_entire_oops(char *buf, long size, struct oops_log_msg *msg);
|
||||
void oops_msg_cleanup(struct oops_log_msg *msg);
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <poll.h>
|
||||
|
||||
@@ -29,6 +27,8 @@
|
||||
#include "log.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
#include "nica/nc-string.h"
|
||||
|
||||
char *oops_dir_path = KERNELOOPSDIR;
|
||||
|
||||
static uint32_t version = 1;
|
||||
@@ -68,7 +68,7 @@ void handle_oops_file(const char *fname)
|
||||
char *filename = NULL, *contents = NULL;
|
||||
long sz;
|
||||
size_t size, bytes_read;
|
||||
GString *payload;
|
||||
nc_string *payload;
|
||||
|
||||
ret = asprintf(&filename, "%s/%s", oops_dir_path, fname);
|
||||
if (ret == -1) {
|
||||
@@ -138,7 +138,7 @@ void handle_oops_file(const char *fname)
|
||||
|
||||
oops_msg_cleanup(&oops_msg);
|
||||
send_data(payload->str, (char *)oops_msg.pattern->classification, (uint32_t)oops_msg.pattern->severity);
|
||||
g_string_free(payload, true);
|
||||
nc_string_free(payload);
|
||||
} else {
|
||||
/* File does no contain an oops! */
|
||||
telem_log(LOG_ERR, "Did not find an oops in the oops directort\n");
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2017 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms and conditions of the GNU Lesser General Public License, as
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Existence of the opt-in-no-privacy-filters file disables certain privacy
|
||||
* filters enforced in telemetry probes.
|
||||
*/
|
||||
#define TM_PRIVACY_FILTERS_OVERRIDE "/etc/telemetrics/opt-in-no-privacy-filters"
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
@@ -12,7 +12,7 @@
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
@@ -61,7 +61,7 @@ static bool send_data(char *backtrace, char *class, uint32_t severity)
|
||||
|
||||
void handle_complete_oops_message(struct oops_log_msg *msg)
|
||||
{
|
||||
GString *payload;
|
||||
nc_string *payload;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < msg->length; i++) {
|
||||
@@ -74,7 +74,7 @@ void handle_complete_oops_message(struct oops_log_msg *msg)
|
||||
printf("Payload Parsed :%s\n", payload->str);
|
||||
#endif
|
||||
send_data(payload->str, (char *)msg->pattern->classification, (uint32_t)msg->pattern->severity);
|
||||
g_string_free(payload, true);
|
||||
nc_string_free(payload);
|
||||
}
|
||||
|
||||
void handle_crash_dump(char *dump, size_t size)
|
||||
@@ -100,7 +100,7 @@ void handle_crash_dump(char *dump, size_t size)
|
||||
|
||||
char *read_contents(char *filename, size_t *bytes)
|
||||
{
|
||||
gchar *dump_file;
|
||||
char *dump_file = NULL;
|
||||
FILE *fp = NULL;
|
||||
char *contents = NULL;
|
||||
long sz = 0;
|
||||
@@ -108,7 +108,10 @@ char *read_contents(char *filename, size_t *bytes)
|
||||
char *hdr_end;
|
||||
size_t hdr_len;
|
||||
|
||||
dump_file = g_strconcat(pstore_dump_path, "/", filename, NULL);
|
||||
if (asprintf(&dump_file, "%s/%s", pstore_dump_path, filename) < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
fp = fopen(dump_file, "r");
|
||||
if (fp == NULL) {
|
||||
telem_log(LOG_ERR, "Failed to open pstore dump file %s:%s\n", dump_file, strerror(errno));
|
||||
@@ -170,7 +173,7 @@ end:
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
g_free(dump_file);
|
||||
free(dump_file);
|
||||
return contents;
|
||||
}
|
||||
|
||||
|
||||
+115
-61
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -22,78 +24,127 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "common.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
static gchar *config_file = NULL;
|
||||
static gboolean version_p = FALSE;
|
||||
static guint severity = 1;
|
||||
static gchar *opt_class = NULL;
|
||||
static gchar *opt_payload = NULL;
|
||||
static guint payload_version = 1;
|
||||
static gchar *opt_payload_file = NULL;
|
||||
static char *config_file = NULL;
|
||||
static uint32_t severity = 1;
|
||||
static char *opt_class = NULL;
|
||||
static char *opt_payload = NULL;
|
||||
static uint32_t payload_version = 1;
|
||||
static char *opt_payload_file = NULL;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "config-file", 'f', 0, G_OPTION_ARG_FILENAME, &config_file,
|
||||
"Path to configuration file (not implemented yet)", NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version_p,
|
||||
"Print the program version", NULL },
|
||||
{ "severity", 's', 0, G_OPTION_ARG_INT, &severity,
|
||||
"Severity level (1-4) - (default 1)", NULL },
|
||||
{ "class", 'c', 0, G_OPTION_ARG_STRING, &opt_class,
|
||||
"Classification level_1/level_2/level_3", NULL },
|
||||
{ "payload", 'p', 0, G_OPTION_ARG_STRING, &opt_payload,
|
||||
"Record body (max size = 8k)", NULL },
|
||||
{ "payload-file", 'P', 0, G_OPTION_ARG_STRING, &opt_payload_file,
|
||||
"File to read payload from", NULL },
|
||||
{ "record-version", 'R', 0, G_OPTION_ARG_INT, &payload_version,
|
||||
"Version number for format of payload (default 1)", NULL },
|
||||
{ NULL }
|
||||
static const struct option prog_opts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "config-file", required_argument, 0, 'f' },
|
||||
{ "version", no_argument, 0, 'V' },
|
||||
{ "severity", required_argument, 0, 's' },
|
||||
{ "class", required_argument, 0, 'c' },
|
||||
{ "payload", required_argument, 0, 'p' },
|
||||
{ "payload-file", required_argument, 0, 'P' },
|
||||
{ "record-version", required_argument, 0, 'R' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void free_glib_strings(void)
|
||||
static void print_help(void)
|
||||
{
|
||||
if (config_file) {
|
||||
g_free(config_file);
|
||||
}
|
||||
printf("Usage:\n");
|
||||
printf(" telem-record-gen [OPTIONS] - create and send a custom telemetry record\n");
|
||||
printf("\n");
|
||||
printf("Help Options:\n");
|
||||
printf(" -h, --help Show help options\n");
|
||||
printf("\n");
|
||||
printf("Application Options:\n");
|
||||
printf(" -f, --config-file Path to configuration file (not implemented yet)\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
printf(" -s, --severity Severity level (1-4) - (default 1)\n");
|
||||
printf(" -c, --class Classification level_1/level_2/level_3\n");
|
||||
printf(" -p, --payload Record body (max size = 8k)\n");
|
||||
printf(" -P, --payload-file File to read payload from\n");
|
||||
printf(" -R, --record-version Version number for format of payload (default 1)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (opt_class) {
|
||||
g_free(opt_class);
|
||||
const unsigned int count_chars(const char *check, const char character)
|
||||
{
|
||||
unsigned int count = 0U;
|
||||
if (check == NULL) {
|
||||
return count;
|
||||
}
|
||||
|
||||
if (opt_payload) {
|
||||
g_free(opt_payload);
|
||||
for (; *check != '\0'; ++check) {
|
||||
if (*check == character) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int parse_options(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
GError *error = NULL;
|
||||
GOptionContext *context;
|
||||
char *endptr = NULL;
|
||||
long unsigned int tmp = 0;
|
||||
|
||||
context = g_option_context_new(
|
||||
"- create and send a custom telemetry record\n");
|
||||
g_option_context_add_main_entries(context, options, NULL);
|
||||
g_option_context_set_translate_func(context, NULL, NULL, NULL);
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "hc:Vs:c:p:P:R:", prog_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case 's':
|
||||
errno = 0;
|
||||
|
||||
if (!g_option_context_parse(context, &argc, &argv, &error)) {
|
||||
g_print("Failed to parse options: %s\n", error->message);
|
||||
goto fail;
|
||||
tmp = strtoul(optarg, &endptr, 10);
|
||||
|
||||
if (errno != 0) {
|
||||
telem_perror("Failed to convert severity number");
|
||||
goto fail;
|
||||
}
|
||||
if (endptr && *endptr != '\0') {
|
||||
telem_log(LOG_ERR, "Invalid severity number. Must be an integer\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
severity = (uint32_t)tmp;
|
||||
break;
|
||||
case 'c':
|
||||
opt_class = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
opt_payload = strdup(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
opt_payload_file = strdup(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
errno = 0;
|
||||
|
||||
tmp = strtoul(optarg, &endptr, 10);
|
||||
|
||||
if (errno != 0) {
|
||||
telem_perror("Failed to convert record-version number");
|
||||
goto fail;
|
||||
}
|
||||
if (endptr && *endptr != '\0') {
|
||||
telem_log(LOG_ERR, "Invalid record-version number. Must be an integer\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
payload_version = (uint32_t)tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
fail:
|
||||
if (context) {
|
||||
g_option_context_free(context);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -116,9 +167,17 @@ int validate_opts(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!g_str_is_ascii(opt_class)) {
|
||||
fprintf(stderr, "Error: Non-ascii characters detected "
|
||||
"in classification - aborting\n");
|
||||
for (int c = 0; c < strlen(opt_class); c++) {
|
||||
if (isascii(opt_class[c]) == 0) {
|
||||
fprintf(stderr, "Error: Non-ascii characters detected "
|
||||
"in classification - aborting\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (count_chars(opt_class, '/') != 2) {
|
||||
fprintf(stderr, "Error: Classification needs to be in "
|
||||
"most/to/least specific format, 2 \'/\' required.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -135,7 +194,7 @@ int allocate_payload_buffer(char **payload)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
*payload = (char *)malloc(sizeof(gchar) * MAX_PAYLOAD_SIZE);
|
||||
*payload = (char *)malloc(MAX_PAYLOAD_SIZE);
|
||||
|
||||
if (*payload == NULL) {
|
||||
goto out1;
|
||||
@@ -162,7 +221,7 @@ int get_payload_from_file(char **payload)
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes_in = fread(*payload, sizeof(gchar),
|
||||
bytes_in = fread(*payload, 1,
|
||||
MAX_PAYLOAD_SIZE - 1, fp);
|
||||
|
||||
/* if fread fails */
|
||||
@@ -195,7 +254,7 @@ void get_payload_from_stdin(char **payload)
|
||||
size_t bytes_in = 0;
|
||||
int c;
|
||||
|
||||
bytes_in = fread(*payload, sizeof(gchar), MAX_PAYLOAD_SIZE - 1, stdin);
|
||||
bytes_in = fread(*payload, 1, MAX_PAYLOAD_SIZE - 1, stdin);
|
||||
|
||||
if (bytes_in == MAX_PAYLOAD_SIZE - 1) {
|
||||
/* Throw away the rest of stdin */
|
||||
@@ -272,11 +331,6 @@ int main(int argc, char **argv)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (version_p) {
|
||||
g_print(PACKAGE_VERSION "\n");
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (!validate_opts()) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -289,13 +343,13 @@ int main(int argc, char **argv)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
success:
|
||||
ret = EXIT_SUCCESS;
|
||||
fail:
|
||||
free_glib_strings();
|
||||
free(config_file);
|
||||
free(opt_class);
|
||||
free(opt_payload);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
|
||||
+4
-4
@@ -511,11 +511,11 @@ bool post_record_http(char *headers[], char *body, bool spool)
|
||||
if (res) {
|
||||
size_t len = strlen(errorbuf);
|
||||
if (len) {
|
||||
telem_log(LOG_ERR, "Failed sending record: %s%s", errorbuf,
|
||||
((errorbuf[len - 1] != '\n') ? "\n" : ""));
|
||||
telem_log(LOG_ERR, "Failed sending record: %s%s", errorbuf,
|
||||
((errorbuf[len - 1] != '\n') ? "\n" : ""));
|
||||
} else {
|
||||
telem_log(LOG_ERR, "Failed sending record: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
telem_log(LOG_ERR, "Failed sending record: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
}
|
||||
} else if (http_response != 201 && http_response != 200) {
|
||||
/* 201 means the record was successfully created
|
||||
|
||||
+3
-3
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -29,6 +28,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "configuration.h"
|
||||
@@ -806,8 +806,8 @@ int payload_is_ascii(char *payload, size_t len)
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!g_ascii_isprint((gchar)payload[i]) &&
|
||||
!g_ascii_isspace((gchar)payload[i])) {
|
||||
if (!isprint(payload[i]) &&
|
||||
!isspace(payload[i])) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ START_TEST(check_read_valid_config)
|
||||
ck_assert_str_eq(config.strValues[CONF_CAINFO], "/tmp/cacert.crt");
|
||||
ck_assert_str_eq(config.strValues[CONF_TIDHEADER],
|
||||
"X-Telemetry-TID: 6907c830-eed9-4ce9-81ae-76daf8d88f0f");
|
||||
ck_assert(config.boolValues[CONF_DAEMON_RECYCLING_ENABLED] == true);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
@@ -75,6 +76,7 @@ START_TEST(check_config_initialised)
|
||||
ck_assert_str_eq(get_cainfo_config(), "/tmp/cacert.crt");
|
||||
ck_assert_str_eq(get_tidheader_config(),
|
||||
"X-Telemetry-TID: 6907c830-eed9-4ce9-81ae-76daf8d88f0f");
|
||||
ck_assert(daemon_recycling_enabled_config() == true);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
+176
-128
@@ -22,16 +22,16 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "nica/nc-string.h"
|
||||
#include "log.h"
|
||||
#include "read_oopsfile.h"
|
||||
#include "src/probes/klog_scanner.h"
|
||||
#include "src/probes/oops_parser.h"
|
||||
|
||||
char reason[1024];
|
||||
GString *bt;
|
||||
GString *pl;
|
||||
nc_string *bt;
|
||||
nc_string *pl;
|
||||
|
||||
void callback_func(struct oops_log_msg *msg)
|
||||
{
|
||||
@@ -100,26 +100,26 @@ START_TEST(watchdog_payload)
|
||||
ck_assert(strstr(pl->str, "#1 dump_stack"));
|
||||
ck_assert(strstr(pl->str, "#2 warn_slowpath_common"));
|
||||
ck_assert(strstr(pl->str, "#3 warn_slowpath_fmt"));
|
||||
ck_assert(strstr(pl->str, "#4 __queue_work"));
|
||||
ck_assert(strstr(pl->str, "#4 ? __queue_work"));
|
||||
ck_assert(strstr(pl->str, "#5 dev_watchdog"));
|
||||
ck_assert(strstr(pl->str, "#6 dev_deactivate_queue.constprop.30"));
|
||||
ck_assert(strstr(pl->str, "#6 ? dev_deactivate_queue.constprop.30"));
|
||||
ck_assert(strstr(pl->str, "#7 call_timer_fn"));
|
||||
ck_assert(strstr(pl->str, "#8 dev_deactivate_queue.constprop.30"));
|
||||
ck_assert(strstr(pl->str, "#8 ? dev_deactivate_queue.constprop.30"));
|
||||
ck_assert(strstr(pl->str, "#9 run_timer_softirq"));
|
||||
ck_assert(strstr(pl->str, "#10 __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#11 irq_exit"));
|
||||
ck_assert(strstr(pl->str, "#12 smp_apic_timer_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#13 apic_timer_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#14 __hrtimer_start_range_ns"));
|
||||
ck_assert(strstr(pl->str, "#15 cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#16 cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#14 ? __hrtimer_start_range_ns"));
|
||||
ck_assert(strstr(pl->str, "#15 ? cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#16 ? cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#17 cpuidle_idle_call"));
|
||||
ck_assert(strstr(pl->str, "#18 arch_cpu_idle"));
|
||||
ck_assert(strstr(pl->str, "#19 cpu_startup_entry"));
|
||||
ck_assert(strstr(pl->str, "#20 clockevents_register_device"));
|
||||
ck_assert(strstr(pl->str, "#20 ? clockevents_register_device"));
|
||||
ck_assert(strstr(pl->str, "#21 start_secondary"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
@@ -141,10 +141,10 @@ START_TEST(alsa_bug_payload)
|
||||
ck_assert(strstr(pl->str, "Tainted : Not tainted"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 warn_on_slowpath"));
|
||||
ck_assert(strstr(pl->str, "#2 vsnprintf"));
|
||||
ck_assert(strstr(pl->str, "#3 _spin_unlock_irqrestore"));
|
||||
ck_assert(strstr(pl->str, "#2 ? vsnprintf"));
|
||||
ck_assert(strstr(pl->str, "#3 ? _spin_unlock_irqrestore"));
|
||||
ck_assert(strstr(pl->str, "#10 start_kernel"));
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -173,16 +173,16 @@ START_TEST(warning_payload)
|
||||
ck_assert(strstr(pl->str, "#3 warn_slowpath_fmt"));
|
||||
ck_assert(strstr(pl->str, "#4 preempt_notifier_register"));
|
||||
ck_assert(strstr(pl->str, "#5 VBoxHost_RTThreadCtxHooksRegister"));
|
||||
ck_assert(strstr(pl->str, "#6 update_curr"));
|
||||
ck_assert(strstr(pl->str, "#7 supdrvIOCtlFast"));
|
||||
ck_assert(strstr(pl->str, "#8 VBoxDrvLinuxIOCtl_4_3_28"));
|
||||
ck_assert(strstr(pl->str, "#9 put_prev_entity"));
|
||||
ck_assert(strstr(pl->str, "#10 do_vfs_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#11 pick_next_task_rt"));
|
||||
ck_assert(strstr(pl->str, "#12 SyS_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#13 entry_SYSCALL_64_fastpath"));
|
||||
ck_assert(strstr(pl->str, "#6 ? update_curr"));
|
||||
ck_assert(strstr(pl->str, "#7 ? supdrvIOCtlFast"));
|
||||
ck_assert(strstr(pl->str, "#8 ? VBoxDrvLinuxIOCtl_4_3_28"));
|
||||
ck_assert(strstr(pl->str, "#9 ? put_prev_entity"));
|
||||
ck_assert(strstr(pl->str, "#10 ? do_vfs_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#11 ? pick_next_task_rt"));
|
||||
ck_assert(strstr(pl->str, "#12 ? SyS_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#13 ? entry_SYSCALL_64_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -208,21 +208,21 @@ START_TEST(warn_on_payload)
|
||||
ck_assert(strstr(pl->str, "#2 warn_slowpath_common"));
|
||||
ck_assert(strstr(pl->str, "#3 warn_slowpath_fmt"));
|
||||
ck_assert(strstr(pl->str, "#4 dev_watchdog"));
|
||||
ck_assert(strstr(pl->str, "#5 qdisc_rcu_free"));
|
||||
ck_assert(strstr(pl->str, "#5 ? qdisc_rcu_free"));
|
||||
ck_assert(strstr(pl->str, "#6 call_timer_fn"));
|
||||
ck_assert(strstr(pl->str, "#7 qdisc_rcu_free"));
|
||||
ck_assert(strstr(pl->str, "#7 ? qdisc_rcu_free"));
|
||||
ck_assert(strstr(pl->str, "#8 run_timer_softirq"));
|
||||
ck_assert(strstr(pl->str, "#9 __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#10 irq_exit"));
|
||||
ck_assert(strstr(pl->str, "#11 smp_apic_timer_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#12 apic_timer_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#13 cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#14 cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#13 ? cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#14 ? cpuidle_enter_state"));
|
||||
ck_assert(strstr(pl->str, "#15 cpuidle_enter"));
|
||||
ck_assert(strstr(pl->str, "#16 cpu_startup_entry"));
|
||||
ck_assert(strstr(pl->str, "#17 start_secondary"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -285,22 +285,22 @@ START_TEST(sysctl2_payload)
|
||||
ck_assert(strstr(pl->str, "Kernel Version : 2.6.32.53-bigmem-5-openvz #28"));
|
||||
ck_assert(strstr(pl->str, "Tainted : P"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 set_fail"));
|
||||
ck_assert(strstr(pl->str, "#2 sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#3 sysctl_check_lookup"));
|
||||
ck_assert(strstr(pl->str, "#4 sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#5 sysctl_check_lookup"));
|
||||
ck_assert(strstr(pl->str, "#6 sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#7 __kmalloc"));
|
||||
ck_assert(strstr(pl->str, "#8 __register_sysctl_paths"));
|
||||
ck_assert(strstr(pl->str, "#9 proc_register"));
|
||||
ck_assert(strstr(pl->str, "#10 register_net_sysctl_table"));
|
||||
ck_assert(strstr(pl->str, "#11 nf_conntrack_net_init"));
|
||||
ck_assert(strstr(pl->str, "#12 setup_net"));
|
||||
ck_assert(strstr(pl->str, "#13 copy_net_ns"));
|
||||
ck_assert(strstr(pl->str, "#14 create_new_namespaces"));
|
||||
ck_assert(strstr(pl->str, "#1 ? set_fail"));
|
||||
ck_assert(strstr(pl->str, "#2 ? sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#3 ? sysctl_check_lookup"));
|
||||
ck_assert(strstr(pl->str, "#4 ? sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#5 ? sysctl_check_lookup"));
|
||||
ck_assert(strstr(pl->str, "#6 ? sysctl_check_table"));
|
||||
ck_assert(strstr(pl->str, "#7 ? __kmalloc"));
|
||||
ck_assert(strstr(pl->str, "#8 ? __register_sysctl_paths"));
|
||||
ck_assert(strstr(pl->str, "#9 ? proc_register"));
|
||||
ck_assert(strstr(pl->str, "#10 ? register_net_sysctl_table"));
|
||||
ck_assert(strstr(pl->str, "#11 ? nf_conntrack_net_init"));
|
||||
ck_assert(strstr(pl->str, "#12 ? setup_net"));
|
||||
ck_assert(strstr(pl->str, "#13 ? copy_net_ns"));
|
||||
ck_assert(strstr(pl->str, "#14 ? create_new_namespaces"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -327,7 +327,7 @@ START_TEST(softlockup_payload)
|
||||
ck_assert(strstr(pl->str, "#2 btrfs_tree_read_lock"));
|
||||
ck_assert(strstr(pl->str, "#3 btrfs_read_lock_root_node"));
|
||||
ck_assert(strstr(pl->str, "#4 btrfs_search_slot"));
|
||||
ck_assert(strstr(pl->str, "#5 crypto_shash_update"));
|
||||
ck_assert(strstr(pl->str, "#5 ? crypto_shash_update"));
|
||||
ck_assert(strstr(pl->str, "#6 btrfs_lookup_xattr"));
|
||||
ck_assert(strstr(pl->str, "#7 __btrfs_getxattr"));
|
||||
ck_assert(strstr(pl->str, "#8 btrfs_getxattr"));
|
||||
@@ -337,7 +337,7 @@ START_TEST(softlockup_payload)
|
||||
ck_assert(strstr(pl->str, "#12 SyS_fgetxattr"));
|
||||
ck_assert(strstr(pl->str, "#13 system_call_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -356,21 +356,21 @@ START_TEST(rtnl_payload)
|
||||
|
||||
ck_assert(strstr(pl->str, "Tainted : Not tainted"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 dump_stack"));
|
||||
ck_assert(strstr(pl->str, "#2 bond_set_rx_mode"));
|
||||
ck_assert(strstr(pl->str, "#3 __dev_mc_add"));
|
||||
ck_assert(strstr(pl->str, "#4 igmp6_group_added"));
|
||||
ck_assert(strstr(pl->str, "#5 sock_def_readable"));
|
||||
ck_assert(strstr(pl->str, "#6 ipv6_dev_mc_inc"));
|
||||
ck_assert(strstr(pl->str, "#7 ipv6_sock_mc_join"));
|
||||
ck_assert(strstr(pl->str, "#8 do_ipv6_setsockopt.isra.6"));
|
||||
ck_assert(strstr(pl->str, "#9 pipe_write"));
|
||||
ck_assert(strstr(pl->str, "#10 SYSC_sendto"));
|
||||
ck_assert(strstr(pl->str, "#11 ipv6_setsockopt"));
|
||||
ck_assert(strstr(pl->str, "#12 SyS_setsockopt"));
|
||||
ck_assert(strstr(pl->str, "#13 system_call_fastpath"));
|
||||
ck_assert(strstr(pl->str, "#1 ? dump_stack"));
|
||||
ck_assert(strstr(pl->str, "#2 ? bond_set_rx_mode"));
|
||||
ck_assert(strstr(pl->str, "#3 ? __dev_mc_add"));
|
||||
ck_assert(strstr(pl->str, "#4 ? igmp6_group_added"));
|
||||
ck_assert(strstr(pl->str, "#5 ? sock_def_readable"));
|
||||
ck_assert(strstr(pl->str, "#6 ? ipv6_dev_mc_inc"));
|
||||
ck_assert(strstr(pl->str, "#7 ? ipv6_sock_mc_join"));
|
||||
ck_assert(strstr(pl->str, "#8 ? do_ipv6_setsockopt.isra.6"));
|
||||
ck_assert(strstr(pl->str, "#9 ? pipe_write"));
|
||||
ck_assert(strstr(pl->str, "#10 ? SYSC_sendto"));
|
||||
ck_assert(strstr(pl->str, "#11 ? ipv6_setsockopt"));
|
||||
ck_assert(strstr(pl->str, "#12 ? SyS_setsockopt"));
|
||||
ck_assert(strstr(pl->str, "#13 ? system_call_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -400,7 +400,7 @@ START_TEST(kernel_null_pointer_payload)
|
||||
ck_assert(strstr(pl->str, "#6 sys_inotify_rm_watch"));
|
||||
ck_assert(strstr(pl->str, "#7 system_call_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -432,7 +432,7 @@ START_TEST(kernel_bug_payload)
|
||||
ck_assert(strstr(pl->str, "#8 ptregscall_common"));
|
||||
ck_assert(strstr(pl->str, "#9 sysret_signal"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -454,51 +454,51 @@ START_TEST(irq_payload)
|
||||
ck_assert(strstr(pl->str, "#1 dump_stack"));
|
||||
ck_assert(strstr(pl->str, "#2 __report_bad_irq"));
|
||||
ck_assert(strstr(pl->str, "#3 note_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#4 __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#4 ? __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#5 handle_irq_event_percpu"));
|
||||
ck_assert(strstr(pl->str, "#6 handle_irq_event"));
|
||||
ck_assert(strstr(pl->str, "#7 handle_nested_irq"));
|
||||
ck_assert(strstr(pl->str, "#7 ? handle_nested_irq"));
|
||||
ck_assert(strstr(pl->str, "#8 handle_level_irq"));
|
||||
ck_assert(strstr(pl->str, "#9 do_IRQ"));
|
||||
ck_assert(strstr(pl->str, "#10 common_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#11 __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#12 handle_irq"));
|
||||
ck_assert(strstr(pl->str, "#13 irq_exit"));
|
||||
ck_assert(strstr(pl->str, "#14 do_IRQ"));
|
||||
ck_assert(strstr(pl->str, "#15 pci_write"));
|
||||
ck_assert(strstr(pl->str, "#16 common_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#17 audit_make_tree"));
|
||||
ck_assert(strstr(pl->str, "#18 usbdev_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#19 _raw_spin_unlock_irqrestore"));
|
||||
ck_assert(strstr(pl->str, "#20 __setup_irq"));
|
||||
ck_assert(strstr(pl->str, "#21 kmem_cache_alloc_trace"));
|
||||
ck_assert(strstr(pl->str, "#22 vsnprintf"));
|
||||
ck_assert(strstr(pl->str, "#23 request_threaded_irq"));
|
||||
ck_assert(strstr(pl->str, "#24 usb_hcd_platform_shutdown"));
|
||||
ck_assert(strstr(pl->str, "#25 request_threaded_irq"));
|
||||
ck_assert(strstr(pl->str, "#26 usb_add_hcd"));
|
||||
ck_assert(strstr(pl->str, "#27 usb_hcd_pci_probe"));
|
||||
ck_assert(strstr(pl->str, "#28 rpm_resume"));
|
||||
ck_assert(strstr(pl->str, "#29 pci_device_probe"));
|
||||
ck_assert(strstr(pl->str, "#30 driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#31 pci_match_device"));
|
||||
ck_assert(strstr(pl->str, "#32 __driver_attach"));
|
||||
ck_assert(strstr(pl->str, "#33 driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#34 bus_for_each_dev"));
|
||||
ck_assert(strstr(pl->str, "#35 driver_attach"));
|
||||
ck_assert(strstr(pl->str, "#36 driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#37 bus_add_driver"));
|
||||
ck_assert(strstr(pl->str, "#38 pci_match_id"));
|
||||
ck_assert(strstr(pl->str, "#39 driver_register"));
|
||||
ck_assert(strstr(pl->str, "#40 ohci_hcd_mod_init"));
|
||||
ck_assert(strstr(pl->str, "#41 ohci_hcd_mod_init"));
|
||||
ck_assert(strstr(pl->str, "#42 __pci_register_driver"));
|
||||
ck_assert(strstr(pl->str, "#43 uhci_hcd_init"));
|
||||
ck_assert(strstr(pl->str, "#44 do_one_initcall"));
|
||||
ck_assert(strstr(pl->str, "#45 kernel_init_freeable"));
|
||||
ck_assert(strstr(pl->str, "#46 do_early_param"));
|
||||
ck_assert(strstr(pl->str, "#9 ? do_IRQ"));
|
||||
ck_assert(strstr(pl->str, "#10 ? common_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#11 ? __do_softirq"));
|
||||
ck_assert(strstr(pl->str, "#12 ? handle_irq"));
|
||||
ck_assert(strstr(pl->str, "#13 ? irq_exit"));
|
||||
ck_assert(strstr(pl->str, "#14 ? do_IRQ"));
|
||||
ck_assert(strstr(pl->str, "#15 ? pci_write"));
|
||||
ck_assert(strstr(pl->str, "#16 ? common_interrupt"));
|
||||
ck_assert(strstr(pl->str, "#17 ? audit_make_tree"));
|
||||
ck_assert(strstr(pl->str, "#18 ? usbdev_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#19 ? _raw_spin_unlock_irqrestore"));
|
||||
ck_assert(strstr(pl->str, "#20 ? __setup_irq"));
|
||||
ck_assert(strstr(pl->str, "#21 ? kmem_cache_alloc_trace"));
|
||||
ck_assert(strstr(pl->str, "#22 ? vsnprintf"));
|
||||
ck_assert(strstr(pl->str, "#23 ? request_threaded_irq"));
|
||||
ck_assert(strstr(pl->str, "#24 ? usb_hcd_platform_shutdown"));
|
||||
ck_assert(strstr(pl->str, "#25 ? request_threaded_irq"));
|
||||
ck_assert(strstr(pl->str, "#26 ? usb_add_hcd"));
|
||||
ck_assert(strstr(pl->str, "#27 ? usb_hcd_pci_probe"));
|
||||
ck_assert(strstr(pl->str, "#28 ? rpm_resume"));
|
||||
ck_assert(strstr(pl->str, "#29 ? pci_device_probe"));
|
||||
ck_assert(strstr(pl->str, "#30 ? driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#31 ? pci_match_device"));
|
||||
ck_assert(strstr(pl->str, "#32 ? __driver_attach"));
|
||||
ck_assert(strstr(pl->str, "#33 ? driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#34 ? bus_for_each_dev"));
|
||||
ck_assert(strstr(pl->str, "#35 ? driver_attach"));
|
||||
ck_assert(strstr(pl->str, "#36 ? driver_probe_device"));
|
||||
ck_assert(strstr(pl->str, "#37 ? bus_add_driver"));
|
||||
ck_assert(strstr(pl->str, "#38 ? pci_match_id"));
|
||||
ck_assert(strstr(pl->str, "#39 ? driver_register"));
|
||||
ck_assert(strstr(pl->str, "#40 ? ohci_hcd_mod_init"));
|
||||
ck_assert(strstr(pl->str, "#41 ? ohci_hcd_mod_init"));
|
||||
ck_assert(strstr(pl->str, "#42 ? __pci_register_driver"));
|
||||
ck_assert(strstr(pl->str, "#43 ? uhci_hcd_init"));
|
||||
ck_assert(strstr(pl->str, "#44 ? do_one_initcall"));
|
||||
ck_assert(strstr(pl->str, "#45 ? kernel_init_freeable"));
|
||||
ck_assert(strstr(pl->str, "#46 ? do_early_param"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
@@ -521,16 +521,16 @@ START_TEST(general_protection_fault_payload)
|
||||
ck_assert(strstr(pl->str, "Modules : tun 8021q garp mrp bridge stp llc bonding ipt_REJECT xt_comment xt_multiport"));
|
||||
ck_assert(strstr(pl->str, "lpc_ich iw_cm mfd_core nfsd auth_rpcgss wmi nfs_acl lockd ipmi_si ipmi_devintf"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 alloc_pipe_info"));
|
||||
ck_assert(strstr(pl->str, "#1 ? alloc_pipe_info"));
|
||||
ck_assert(strstr(pl->str, "#2 alloc_pipe_info"));
|
||||
ck_assert(strstr(pl->str, "#3 create_pipe_files"));
|
||||
ck_assert(strstr(pl->str, "#4 __do_pipe_flags"));
|
||||
ck_assert(strstr(pl->str, "#5 SyS_pipe2"));
|
||||
ck_assert(strstr(pl->str, "#6 __audit_syscall_exit"));
|
||||
ck_assert(strstr(pl->str, "#6 ? __audit_syscall_exit"));
|
||||
ck_assert(strstr(pl->str, "#7 SyS_pipe"));
|
||||
ck_assert(strstr(pl->str, "#8 system_call_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -552,7 +552,7 @@ START_TEST(double_fault_payload)
|
||||
ck_assert(strstr(pl->str, "Modules : nls_utf8 vfat fat sit tunnel4 ext2 fuse ip6table_filter ip6_tables ebtable_nat"));
|
||||
ck_assert(strstr(pl->str, "joydev sdhci_pci sdhci usb_storage mmc_core video output [last unloaded: speedstep_lib]"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -571,7 +571,7 @@ START_TEST(bad_page_map_payload)
|
||||
ck_assert(strstr(pl->str, "Kernel Version : 3.12-1-amd64 #1 Debian 3.12.9-1"));
|
||||
ck_assert(strstr(pl->str, "Tainted : Not tainted"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
@@ -594,31 +594,78 @@ START_TEST(bug_kernel_handle_payload)
|
||||
ck_assert(strstr(pl->str, "Modules : nf_conntrack_netbios_ns nf_conntrack_broadcast ipt_MASQUERADE be2iscsi"));
|
||||
ck_assert(strstr(pl->str, "drm_kms_helper firewire_ohci drm firewire_core tg3 crc_itu_t i2c_core video usb_storage sunrpc"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 _nv007312rm"));
|
||||
ck_assert(strstr(pl->str, "#2 _nv007847rm"));
|
||||
ck_assert(strstr(pl->str, "#3 _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#4 _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#5 _nv010019rm"));
|
||||
ck_assert(strstr(pl->str, "#6 _nv014983rm"));
|
||||
ck_assert(strstr(pl->str, "#7 _nv001097rm"));
|
||||
ck_assert(strstr(pl->str, "#8 rm_init_adapter"));
|
||||
ck_assert(strstr(pl->str, "#1 ? _nv007312rm"));
|
||||
ck_assert(strstr(pl->str, "#2 ? _nv007847rm"));
|
||||
ck_assert(strstr(pl->str, "#3 ? _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#4 ? _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#5 ? _nv010019rm"));
|
||||
ck_assert(strstr(pl->str, "#6 ? _nv014983rm"));
|
||||
ck_assert(strstr(pl->str, "#7 ? _nv001097rm"));
|
||||
ck_assert(strstr(pl->str, "#8 ? rm_init_adapter"));
|
||||
ck_assert(strstr(pl->str, "#9 ? nv_kern_open"));
|
||||
ck_assert(strstr(pl->str, "#10 ? chrdev_open"));
|
||||
ck_assert(strstr(pl->str, "#11 ? do_dentry_open"));
|
||||
ck_assert(strstr(pl->str, "#12 ? cdev_put"));
|
||||
ck_assert(strstr(pl->str, "#13 ? finish_open"));
|
||||
ck_assert(strstr(pl->str, "#14 ? do_last"));
|
||||
ck_assert(strstr(pl->str, "#15 ? inode_permission"));
|
||||
ck_assert(strstr(pl->str, "#16 ? link_path_walk"));
|
||||
ck_assert(strstr(pl->str, "#17 ? path_openat"));
|
||||
ck_assert(strstr(pl->str, "#18 ? do_filp_open"));
|
||||
ck_assert(strstr(pl->str, "#19 ? __alloc_fd"));
|
||||
ck_assert(strstr(pl->str, "#20 ? do_sys_open"));
|
||||
ck_assert(strstr(pl->str, "#21 ? __audit_syscall_entry"));
|
||||
ck_assert(strstr(pl->str, "#22 ? sys_open"));
|
||||
ck_assert(strstr(pl->str, "#23 ? system_call_fastpath"));
|
||||
|
||||
nc_string_free(pl);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(bug_kernel_handle_payload_new_format)
|
||||
{
|
||||
char *oopsfile = NULL;
|
||||
|
||||
oopsfile = TESTOOPSDIR "/bug_kernel_handle_new.txt";
|
||||
setup_payload(oopsfile);
|
||||
|
||||
telem_log(LOG_ERR, "Bug kernel handle backtrace: %s\n", pl->str);
|
||||
|
||||
ck_assert(pl->len > 0);
|
||||
ck_assert_str_eq(reason, "BUG: unable to handle kernel paging request at 0000000000002658");
|
||||
|
||||
ck_assert(strstr(pl->str, "Kernel Version : 3.7.9-201.fc18.x86_64 #1 Apple Inc. MacBookPro6,2/Mac-F22586C8"));
|
||||
ck_assert(strstr(pl->str, "Tainted : PF"));
|
||||
|
||||
ck_assert(strstr(pl->str, "Modules : nf_conntrack_netbios_ns nf_conntrack_broadcast ipt_MASQUERADE be2iscsi"));
|
||||
ck_assert(strstr(pl->str, "drm_kms_helper firewire_ohci drm firewire_core tg3 crc_itu_t i2c_core video usb_storage sunrpc"));
|
||||
|
||||
ck_assert(strstr(pl->str, "#1 ? _nv007312rm"));
|
||||
ck_assert(strstr(pl->str, "#2 ? _nv007847rm"));
|
||||
ck_assert(strstr(pl->str, "#3 ? _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#4 ? _nv004049rm"));
|
||||
ck_assert(strstr(pl->str, "#5 ? _nv010019rm"));
|
||||
ck_assert(strstr(pl->str, "#6 ? _nv014983rm"));
|
||||
ck_assert(strstr(pl->str, "#7 ? _nv001097rm"));
|
||||
ck_assert(strstr(pl->str, "#8 ? rm_init_adapter"));
|
||||
ck_assert(strstr(pl->str, "#9 nv_kern_open"));
|
||||
ck_assert(strstr(pl->str, "#10 chrdev_open"));
|
||||
ck_assert(strstr(pl->str, "#11 do_dentry_open"));
|
||||
ck_assert(strstr(pl->str, "#12 cdev_put"));
|
||||
ck_assert(strstr(pl->str, "#13 finish_open"));
|
||||
ck_assert(strstr(pl->str, "#14 do_last"));
|
||||
ck_assert(strstr(pl->str, "#15 inode_permission"));
|
||||
ck_assert(strstr(pl->str, "#10 ? chrdev_open"));
|
||||
ck_assert(strstr(pl->str, "#11 ? do_dentry_open"));
|
||||
ck_assert(strstr(pl->str, "#12 ? cdev_put"));
|
||||
ck_assert(strstr(pl->str, "#13 ? finish_open"));
|
||||
ck_assert(strstr(pl->str, "#14 ? do_last"));
|
||||
ck_assert(strstr(pl->str, "#15 ? inode_permission"));
|
||||
ck_assert(strstr(pl->str, "#16 link_path_walk"));
|
||||
ck_assert(strstr(pl->str, "#17 path_openat"));
|
||||
ck_assert(strstr(pl->str, "#18 do_filp_open"));
|
||||
ck_assert(strstr(pl->str, "#19 __alloc_fd"));
|
||||
ck_assert(strstr(pl->str, "#20 do_sys_open"));
|
||||
ck_assert(strstr(pl->str, "#21 __audit_syscall_entry"));
|
||||
ck_assert(strstr(pl->str, "#22 sys_open"));
|
||||
ck_assert(strstr(pl->str, "#23 system_call_fastpath"));
|
||||
ck_assert(strstr(pl->str, "#18 ? do_filp_open"));
|
||||
ck_assert(strstr(pl->str, "#19 ? __alloc_fd"));
|
||||
ck_assert(strstr(pl->str, "#20 ? do_sys_open"));
|
||||
ck_assert(strstr(pl->str, "#21 ? __audit_syscall_entry"));
|
||||
ck_assert(strstr(pl->str, "#22 ? sys_open"));
|
||||
ck_assert(strstr(pl->str, "#23 ? system_call_fastpath"));
|
||||
|
||||
g_string_free(pl, true);
|
||||
nc_string_free(pl);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
@@ -648,6 +695,7 @@ Suite *config_suite(void)
|
||||
tcase_add_test(t, double_fault_payload);
|
||||
tcase_add_test(t, bad_page_map_payload);
|
||||
tcase_add_test(t, bug_kernel_handle_payload);
|
||||
tcase_add_test(t, bug_kernel_handle_payload_new_format);
|
||||
|
||||
//TODO fix
|
||||
//tcase_add_test(t, badness_payload);
|
||||
|
||||
@@ -61,6 +61,7 @@ endif
|
||||
%D%/read_oopsfile.h \
|
||||
%D%/read_oopsfile.c \
|
||||
%D%/check_probes.c \
|
||||
src/nica/nc-string.c \
|
||||
src/probes/klog_scanner.c \
|
||||
src/probes/klog_scanner.h \
|
||||
src/probes/oops_parser.c \
|
||||
@@ -72,6 +73,7 @@ EXTRA_DIST += \
|
||||
%D%/oops_test_files/badness.txt \
|
||||
%D%/oops_test_files/bad_page_map.txt \
|
||||
%D%/oops_test_files/bug_kernel_handle.txt \
|
||||
%D%/oops_test_files/bug_kernel_handle_new.txt \
|
||||
%D%/oops_test_files/double_fault_DONE.txt \
|
||||
%D%/oops_test_files/double_fault.txt \
|
||||
%D%/oops_test_files/general_protection_fault.txt \
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<4>[ 68764.975947] BUG: unable to handle kernel paging request at 0000000000002658
|
||||
<4>[ 68764.975947] IP: [<ffffffffa07f92e5>] _nv007245rm+0x54/0xc4 [nvidia]
|
||||
<4>[ 68764.975947] PGD 22d005067 PUD 22d006067 PMD 0
|
||||
<4>[ 68764.975947] Oops: 0000 [#1] SMP
|
||||
<4>[ 68764.975947] Modules linked in: nf_conntrack_netbios_ns nf_conntrack_broadcast ipt_MASQUERADE be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio ip6table_mangle libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp ip6t_REJECT libiscsi scsi_transport_iscsi nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables rfcomm ip6table_filter ip6_tables bnep nls_utf8 hfsplus binfmt_misc snd_hda_codec_hdmi arc4 brcmsmac cordic brcmutil mac80211 cfg80211 joydev iTCO_wdt iTCO_vendor_support nvidia(POF) coretemp applesmc input_polldev microcode uvcvideo i2c_i801 intel_ips snd_hda_codec_cirrus videobuf2_vmalloc videobuf2_memops videobuf2_core videodev btusb media bluetooth snd_hda_intel snd_hda_codec rfkill snd_hwdep bcm5974 snd_seq snd_seq_device snd_pcm lpc_ich mfd_core bcma snd_page_alloc snd_timer vhost_net tun snd macvtap macvlan soundcore kvm_intel kvm apple_gmux apple_bl uinput crc32c_intel i915 ghash_clmulni_intel i2c_algo_bit drm_kms_helper firewire_ohci drm firewire_core tg3 crc_itu_t i2c_core video usb_storage sunrpc
|
||||
<4>[ 68764.975947] CPU 2
|
||||
<4>[ 68764.975947] Pid: 1059, comm: Xorg Tainted: PF O 3.7.9-201.fc18.x86_64 #1 Apple Inc. MacBookPro6,2/Mac-F22586C8
|
||||
<4>[ 68764.975947] RIP: 0010:[<ffffffffa07f92e5>] [<ffffffffa07f92e5>] _nv007245rm+0x54/0xc4 [nvidia]
|
||||
<4>[ 68764.975947] RSP: 0018:ffff88022d0639b8 EFLAGS: 00010282
|
||||
<4>[ 68764.975947] RAX: 0000000000000000 RBX: ffff88022d190008 RCX: 0000000000000000
|
||||
<4>[ 68764.975947] RDX: 0000000000000000 RSI: 0000000000000015 RDI: 0000000000000000
|
||||
<4>[ 68764.975947] RBP: ffff88022d30df08 R08: 0000000000000002 R09: ffff88023f342508
|
||||
<4>[ 68764.975947] R10: ffff88022d951030 R11: 0000000000000000 R12: 0000000000000000
|
||||
<4>[ 68764.975947] R13: ffff88023f3b0008 R14: 0000000000000000 R15: ffff88022da96008
|
||||
<4>[ 68764.975947] FS: 00007f771f4f2940(0000) GS:ffff88024fc80000(0000) knlGS:0000000000000000
|
||||
<4>[ 68764.975947] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
||||
<4>[ 68764.975947] CR2: 0000000000002658 CR3: 000000022d004000 CR4: 00000000000007e0
|
||||
<4>[ 68764.975947] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
|
||||
<4>[ 68764.975947] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
|
||||
<4>[ 68764.975947] Process Xorg
|
||||
<4>[ 68764.975947] Stack:
|
||||
<4>[ 68764.975947] ffff88022d33a008 ffff88022d33a008 0000000000000002 ffff88023f3b0008
|
||||
<4>[ 68764.975947] ffff88022d190008 ffffffffa07deec8 ffff88023d67b008 ffff88022d190008
|
||||
<4>[ 68764.975947] ffff88023f3b0008 ffff88023f3b0008 ffff88022da94808 ffffffffa083e77f
|
||||
<4>[ 68764.975947] Call Trace:
|
||||
<4>[ 68764.975947] ? _nv007312rm+0x7f8/0x938 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv007847rm+0x80/0x276 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv004049rm+0x85fb/0xaef0 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv004049rm+0x705f/0xaef0 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv010019rm+0x25/0x40 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv014983rm+0x7c9/0x943 [nvidia]
|
||||
<4>[ 68764.975947] ? _nv001097rm+0x42b/0x661 [nvidia]
|
||||
<4>[ 68764.975947] ? rm_init_adapter+0xac/0x146 [nvidia]
|
||||
<4>[ 68764.975947] nv_kern_open+0x4b4/0x800 [nvidia]
|
||||
<4>[ 68764.975947] ? chrdev_open+0x9b/0x180
|
||||
<4>[ 68764.975947] ? do_dentry_open+0x203/0x290
|
||||
<4>[ 68764.975947] ? cdev_put+0x30/0x30
|
||||
<4>[ 68764.975947] ? finish_open+0x35/0x50
|
||||
<4>[ 68764.975947] ? do_last+0x6de/0xe00
|
||||
<4>[ 68764.975947] ? inode_permission+0x18/0x50
|
||||
<4>[ 68764.975947] link_path_walk+0x77/0x870
|
||||
<4>[ 68764.975947] path_openat+0xbc/0x4d0
|
||||
<4>[ 68764.975947] ? do_filp_open+0x41/0xa0
|
||||
<4>[ 68764.975947] ? __alloc_fd+0x42/0x110
|
||||
<4>[ 68764.975947] ? do_sys_open+0xf4/0x1e0
|
||||
<4>[ 68764.975947] ? __audit_syscall_entry+0xcc/0x300
|
||||
<4>[ 68764.975947] ? sys_open+0x21/0x30
|
||||
<4>[ 68764.975947] ? system_call_fastpath+0x16/0x1b
|
||||
<4>[ 68764.975947] Code: e0 05 00 00 00 00 00 00 41 bc 00 00 00 00 eb 18 44 89 e2 48 89 de 4c 89 ef ff 93 48 1a 00 00 01 83 e0 05 00 00 41 ff c4 4c 89 f7 <41> ff 96 58 26 00 00 44 39 e0 77 d9 ba 74 06 10 00 be 00 00 00
|
||||
<4>[ 68764.975947] RIP [<ffffffffa07f92e5>] _nv007245rm+0x54/0xc4 [nvidia]
|
||||
<4>[ 68764.975947] RSP <ffff88022d0639b8>
|
||||
Reference in New Issue
Block a user