Remove klogd from the sysklogd project
This patch removes one of the traditionally key pieces of the sysklogd project, klogd. Now that syslogd performs logging of kernel messages we no longer require a separate daemon for that. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
parent
8aa2060312
commit
6bb6672ebf
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,7 +18,6 @@ config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
klogd.service
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
|
@ -22,9 +22,6 @@ EXTRA_DIST = README.md ChangeLog.md syslog.conf
|
||||
|
||||
if HAVE_SYSTEMD
|
||||
systemd_DATA = syslogd.service
|
||||
if ENABLE_KLOGD
|
||||
systemd_DATA += klogd.service
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
|
24
configure.ac
24
configure.ac
@ -31,7 +31,6 @@ AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
src/libsyslog.pc
|
||||
test/Makefile
|
||||
klogd.service
|
||||
syslogd.service])
|
||||
|
||||
AC_PROG_CC
|
||||
@ -49,14 +48,6 @@ AC_CONFIG_LIBOBJ_DIR([lib])
|
||||
AC_CHECK_FUNCS([getprogname strtobytes])
|
||||
|
||||
# Command line options
|
||||
AC_ARG_WITH(klogd,
|
||||
AS_HELP_STRING([--with-klogd], [Build a separate klogd, default: disabled]),
|
||||
[klogd=$withval], [klogd='no'])
|
||||
|
||||
AC_ARG_WITH(klogd-delay,
|
||||
AS_HELP_STRING([--with-klogd-delay=SEC], [Delay before klogd connects to syslogd, default: 0]),
|
||||
[klogd_delay=$withval], [klogd_delay='no'])
|
||||
|
||||
AC_ARG_WITH(suspend-time,
|
||||
AS_HELP_STRING([--with-suspend-time=SEC], [Retry delay for sending to remote, default: 180]),
|
||||
[suspend_time=$withval], [suspend_time='no'])
|
||||
@ -69,19 +60,6 @@ AC_ARG_WITH(logger,
|
||||
AS_HELP_STRING([--without-logger], [Build without extended logger tool, default: enabled]),
|
||||
[logger=$withval], [logger='yes'])
|
||||
|
||||
AS_IF([test "x$klogd" != "xno"],
|
||||
with_klogd="yes"
|
||||
AC_DEFINE(KLOGD, 1, [Build with klogd, default: built-in /dev/kmsg support in syslogd]),
|
||||
with_klogd="no")
|
||||
AM_CONDITIONAL([ENABLE_KLOGD], [test "x$with_klogd" != "xno"])
|
||||
|
||||
AS_IF([test "x$klogd_delay" != "xno"],[
|
||||
AS_IF([test "x$klogd_delay" = "xyes"],[
|
||||
AC_MSG_ERROR([Must supply argument])])
|
||||
]
|
||||
AC_DEFINE_UNQUOTED(KLOGD_DELAY, $klogd_delay, [Delay klogd startup N seconds, default: 0]),
|
||||
klogd_delay=0)
|
||||
|
||||
AS_IF([test "x$logger" != "xno"], with_logger="yes", with_logger="no")
|
||||
AM_CONDITIONAL([ENABLE_LOGGER], [test "x$with_logger" != "xno"])
|
||||
|
||||
@ -136,8 +114,6 @@ cat <<EOF
|
||||
C Compiler.....: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
|
||||
Optional features:
|
||||
klogd..........: $with_klogd
|
||||
klogd delay....: $klogd_delay sec
|
||||
logger.........: $with_logger
|
||||
suspend time...: $suspend_time sec
|
||||
systemd........: $with_systemd
|
||||
|
@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Kernel Logging Service
|
||||
Documentation=man:klogd
|
||||
After=syslogd.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=@SBINDIR@/klogd -n
|
||||
StandardOutput=null
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -3,10 +3,6 @@ dist_man3_MANS = syslogp.3
|
||||
dist_man5_MANS = syslog.conf.5
|
||||
dist_man8_MANS = syslogd.8
|
||||
|
||||
if ENABLE_KLOGD
|
||||
dist_man8_MANS += klogd.8
|
||||
endif
|
||||
|
||||
if ENABLE_LOGGER
|
||||
dist_man1_MANS += logger.1
|
||||
endif
|
||||
|
435
man/klogd.8
435
man/klogd.8
@ -1,435 +0,0 @@
|
||||
.\" -*- nroff -*-
|
||||
.\" Copyright 1994-1996 Dr. Greg Wettstein, Enjellic Systems Development.
|
||||
.\" Copyright 1997-2007 Martin Schulze <joey@infodrom.org>
|
||||
.\" Copyright 2018-2019 Joachim Nilsson <troglobit@gmail.com>
|
||||
.\"
|
||||
.\" May be distributed under the GNU General Public License
|
||||
.\"
|
||||
.Dd Oct 30, 2019
|
||||
.Dt klogd 8
|
||||
.Os "sysklogd (2.0)"
|
||||
.Sh NAME
|
||||
.Nm klogd
|
||||
.Nd Kernel Log Daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 2dFnopsvx
|
||||
.Op Fl c Ar NUM
|
||||
.Op Fl f Ar FILE
|
||||
.Op Fl k Ar FILE
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a system daemon which intercepts and logs Linux kernel messages.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c Ar NUM
|
||||
Sets the default log level of console messages to
|
||||
.Ar NUM
|
||||
(1-8).
|
||||
.It Fl d
|
||||
Enable debugging mode. This will generate potentially LOTS of output to
|
||||
stderr.
|
||||
.It Fl f Ar FILE
|
||||
Log messages to the specified filename rather than to the syslog facility.
|
||||
.It Fl n | Fl F
|
||||
Run in foreground, required when run from a modern init/supervisor. See
|
||||
your system
|
||||
.Xr init 1
|
||||
for details.
|
||||
.It Fl o
|
||||
Execute in one-shot mode. This causes
|
||||
.Nm
|
||||
to read and log all the messages that are found in the kernel message
|
||||
buffers. After a single read and log cycle the daemon exits.
|
||||
.It Fl p
|
||||
Enable paranoia mode. This option controls when klogd loads kernel
|
||||
module symbol information. This mode causes klogd to load the kernel
|
||||
module symbol information whenever a kernel "Oops" string is detected in
|
||||
the kernel message stream.
|
||||
.It Fl s
|
||||
Force
|
||||
.Nm
|
||||
to use the system call interface to the kernel message buffers.
|
||||
.It Fl k Ar FILE
|
||||
Use the specified file as the source of kernel symbol information.
|
||||
.It Fl v
|
||||
Print version and exit.
|
||||
.It Fl x
|
||||
Omits EIP translation and therefore doesn't read the System.map file.
|
||||
.It Fl 2
|
||||
When symbols are expanded, print the line twice. Once with addresses
|
||||
converted to symbols, once with the raw text. This allows external
|
||||
programs such as ksymoops do their own processing on the original data.
|
||||
.Sh OVERVIEW
|
||||
The basic functionality of klogd is typically included in
|
||||
.Nm syslogd .
|
||||
In a modern Linux kernel a number of kernel messaging issues such as
|
||||
sourcing, prioritization and resolution of kernel addresses must be
|
||||
addressed. This task was previously the role of
|
||||
.Nm ,
|
||||
but with the addition of features like
|
||||
.Ql CONFIG_KALLSYSMS
|
||||
the need for a separate
|
||||
.Nm
|
||||
has been greatly reduced, so the
|
||||
.Nm sysklogd
|
||||
project have disabled
|
||||
.Nm
|
||||
by default.
|
||||
.Pp
|
||||
In Linux there are two potential sources of kernel log information: the
|
||||
.Pa /proc
|
||||
file system, specifically the file
|
||||
.Pa /proc/kmsg ,
|
||||
and the syscall,
|
||||
.Fn sys_syslog
|
||||
interface, see
|
||||
.Xr syslog 2
|
||||
for details, although ultimately they are one and the same.
|
||||
.Nm syslogd
|
||||
reads from
|
||||
.Pa /proc/kmsg ,
|
||||
but
|
||||
.Nm
|
||||
is designed to choose whichever source of information is the most
|
||||
appropriate. It does this by first checking for the presence of a
|
||||
mounted
|
||||
.Pa /proc
|
||||
file system. If this is found the
|
||||
.Pa /proc/kmsg
|
||||
file is used as the source of kernel log
|
||||
information. If the proc file system is not mounted
|
||||
.Nm
|
||||
uses a system call to obtain kernel messages. The command line switch
|
||||
.Fl s
|
||||
can be used to force
|
||||
.Nm
|
||||
to use the system call interface as its messaging source.
|
||||
.Pp
|
||||
The raw kernel messages are of the form:
|
||||
.Bd -literal -offset indent
|
||||
<[0-7]>Something said by the kernel.
|
||||
.Ed
|
||||
.Pp
|
||||
The priority of the kernel message is encoded as a single numeric
|
||||
digit enclosed inside the
|
||||
.Ql <>
|
||||
pair. The definitions of these values is given in the kernel include
|
||||
file kernel.h. When a message is received from the kernel, by either
|
||||
.Nm syslogd
|
||||
or
|
||||
.Nm klogd ,
|
||||
the daemon reads this priority value and assigns the appropriate
|
||||
priority level and kernel facility to the syslog message. If file
|
||||
output,
|
||||
.Fl f Ar FILE ,
|
||||
is used the prioritization sequence is left pre-pended to the kernel
|
||||
message.
|
||||
.Pp
|
||||
The klogd daemon can also be used in a 'one-shot' mode for reading the
|
||||
kernel message buffers. One shot mode is selected by specifying the
|
||||
.Fl o
|
||||
switch on the command line. Output will be directed to either the
|
||||
syslog daemon or to an alternate file specified by the
|
||||
.Fl -f Ar FILE
|
||||
switch.
|
||||
.Pp
|
||||
For example, to read all the kernel messages after a system
|
||||
boot and record them in a file called krnl.msg the following
|
||||
command would be given:
|
||||
.Bd -literal -offset indent
|
||||
klogd -o -f ./krnl.msg
|
||||
.Ed
|
||||
.Sh KERNEL ADDRESS RESOLUTION
|
||||
If the kernel detects an internal error condition a general protection
|
||||
fault will be triggered. As part of the GPF handling procedure the
|
||||
kernel prints out a status report indicating the state of the
|
||||
processor at the time of the fault. Included in this display are the
|
||||
contents of the microprocessor's registers, the contents of the kernel
|
||||
stack and a tracing of what functions were being executed at the time
|
||||
of the fault.
|
||||
.Pp
|
||||
This information is
|
||||
.Sy EXTREMELY IMPORTANT
|
||||
in determining what caused the internal error condition. The
|
||||
difficulty comes when a kernel developer attempts to analyze this
|
||||
information. The raw numeric information present in the protection
|
||||
fault printout is of very little use to the developers. This is due
|
||||
to the fact that kernels are not identical and the addresses of
|
||||
variable locations or functions will not be the same in all kernels.
|
||||
In order to correctly diagnose the cause of failure a kernel developer
|
||||
needs to know what specific kernel functions or variable locations
|
||||
were involved in the error.
|
||||
.Pp
|
||||
As part of the kernel compilation process a listing is created which
|
||||
specified the address locations of important variables and function in
|
||||
the kernel being compiled. This listing is saved in a file called
|
||||
System.map in the top of the kernel directory source tree. Using this
|
||||
listing a kernel developer can determine exactly what the kernel was
|
||||
doing when the error condition occurred.
|
||||
.Pp
|
||||
The process of resolving the numeric addresses from the protection
|
||||
fault printout can be done manually or by using the
|
||||
.Xr ksymoops 8
|
||||
program which is included in Linux kernel sources before 1999, or
|
||||
from this location:
|
||||
.Lk https://www.kernel.org/pub/linux/utils/kernel/ksymoops
|
||||
.Pp
|
||||
As a convenience
|
||||
.Nm
|
||||
will attempt to resolve kernel numeric addresses to their symbolic forms
|
||||
if a kernel symbol table is available at execution time. If you require
|
||||
the original address of the symbol, use the
|
||||
.Fl 2
|
||||
switch to preserve the numeric address. A symbol table may be specified
|
||||
by using the
|
||||
.Fl k Ar FILE
|
||||
switch on the command line. If a symbol file is not explicitly
|
||||
specified the following filenames will be tried:
|
||||
.Pp
|
||||
.Bl -tag -width /usr/src/linux/System.map -compact -offset indent
|
||||
.It Pa /boot/System.map
|
||||
.It Pa /System.map
|
||||
.It Pa /usr/src/linux/System.map
|
||||
.El
|
||||
.Pp
|
||||
Version information is supplied in the system maps as of Linux 1.3.43.
|
||||
This version information is used to direct an intelligent search of the
|
||||
list of symbol tables. This feature is useful since it provides support
|
||||
for both production and experimental kernels.
|
||||
.Pp
|
||||
For example a production kernel may have its map file stored in
|
||||
.Pa /boot/System.map .
|
||||
If an experimental or test kernel is compiled with
|
||||
the sources in the 'standard' location of
|
||||
.Pa /usr/src/linux
|
||||
the system
|
||||
map will be found in
|
||||
.Pa /usr/src/linux/System.map .
|
||||
When
|
||||
.Nm
|
||||
starts under the experimental kernel the map in
|
||||
.Pa /boot/System.map
|
||||
will be bypassed in favor of the map in
|
||||
.Pa /usr/src/linux/System.map .
|
||||
.Pp
|
||||
Modern kernels as of 1.3.43 properly format important kernel addresses
|
||||
so that they will be recognized and translated by klogd. Earlier
|
||||
kernels require a source code patch be applied to the kernel sources.
|
||||
This patch is supplied with the sysklogd sources.
|
||||
.Pp
|
||||
The process of analyzing kernel protections faults works very well with
|
||||
a static kernel. Additional difficulties are encountered when
|
||||
attempting to diagnose errors which occur in loadable kernel modules.
|
||||
Loadable kernel modules are used to implement kernel functionality in a
|
||||
form which can be loaded or unloaded at will. The use of loadable
|
||||
modules is useful from a debugging standpoint and can also be useful in
|
||||
decreasing the amount of memory required by a kernel.
|
||||
.Pp
|
||||
The difficulty with diagnosing errors in loadable modules is due to the
|
||||
dynamic nature of the kernel modules. When a module is loaded the
|
||||
kernel will allocate memory to hold the module, when the module is
|
||||
unloaded this memory will be returned back to the kernel. This dynamic
|
||||
memory allocation makes it impossible to produce a map file which
|
||||
details the addresses of the variable and functions in a kernel loadable
|
||||
module. Without this location map it is not possible for a kernel
|
||||
developer to determine what went wrong if a protection fault involves a
|
||||
kernel module.
|
||||
.Pp
|
||||
.Nm
|
||||
has support for dealing with the problem of diagnosing protection faults
|
||||
in kernel loadable modules. At program start time or in response to a
|
||||
signal the daemon will interrogate the kernel for a listing of all
|
||||
modules loaded and the addresses in memory they are loaded at.
|
||||
Individual modules can also register the locations of important
|
||||
functions when the module is loaded. The addresses of these exported
|
||||
symbols are also determined during this interrogation process.
|
||||
.Pp
|
||||
When a protection fault occurs an attempt will be made to resolve kernel
|
||||
addresses from the static symbol table. If this fails the symbols from
|
||||
the currently loaded modules are examined in an attempt to resolve the
|
||||
addresses. At the very minimum this allows klogd to indicate which
|
||||
loadable module was responsible for generating the protection fault.
|
||||
Additional information may be available if the module developer chose to
|
||||
export symbol information from the module.
|
||||
.Pp
|
||||
Proper and accurate resolution of addresses in kernel modules requires
|
||||
that
|
||||
.Nm
|
||||
be informed whenever the kernel module status changes. The
|
||||
.Ar SIGUSR1
|
||||
and
|
||||
.Ar SIGUSR2
|
||||
signals can be used to signal the currently executing
|
||||
.Nm
|
||||
that symbol information should be reloaded. Of most importance to
|
||||
proper resolution of module symbols is
|
||||
.Ar SIGUSR1 .
|
||||
Each time a kernel module is loaded or removed from the kernel the
|
||||
following command should be executed:
|
||||
.Bd -literal -offset indent
|
||||
kill -USR1 `cat /run/klogd.pid`
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Fl p
|
||||
switch can also be used to ensure that module symbol information is up
|
||||
to date. This switch instructs
|
||||
.Nm
|
||||
to reload the module symbol information whenever a protection fault
|
||||
is detected. Caution should be used before invoking the program in
|
||||
'paranoid' mode. The stability of the kernel and the operating
|
||||
environment is always under question when a protection fault occurs.
|
||||
Since the klogd daemon must execute system calls in order to read the
|
||||
module symbol information there is the possibility that the system may
|
||||
be too unstable to capture useful information. A much better policy is
|
||||
to insure that klogd is updated whenever a module is loaded or unloaded.
|
||||
Having uptodate symbol information loaded increases the probability of
|
||||
properly resolving a protection fault if it should occur.
|
||||
.Pp
|
||||
Included in the sysklogd source distribution is a patch to the
|
||||
modules-2.0.0 package which allows the
|
||||
.Xr insmod 8 ,
|
||||
.Xr rmmod 8 ,
|
||||
and
|
||||
.Xr modprobe 8
|
||||
utilities to automatically signal
|
||||
.Nm
|
||||
whenever a module is inserted or removed from the kernel. Using this
|
||||
patch will insure that the symbol information maintained in klogd is
|
||||
always consistent with the current kernel state.
|
||||
.Sh CONSOLE LOG LEVEL
|
||||
The
|
||||
.Nm
|
||||
daemon allows the ability to alter the presentation of kernel messages
|
||||
to the system console. Consequent with the prioritization of kernel
|
||||
messages was the inclusion of default messaging levels for the kernel.
|
||||
In a stock kernel the the default console log level is set to 7. Any
|
||||
messages with a priority level numerically lower than 7 (higher
|
||||
priority) appear on the console.
|
||||
.Pp
|
||||
Messages of priority level 7 are considered to be 'debug' messages and
|
||||
will thus not appear on the console. Many administrators, particularly
|
||||
in a multi-user environment, prefer that all kernel messages be handled
|
||||
by klogd and either directed to a file or to the syslogd daemon. This
|
||||
prevents 'nuisance' messages such as line printer out of paper or disk
|
||||
change detected from cluttering the console.
|
||||
.Pp
|
||||
When
|
||||
.Fl c
|
||||
is given on the commandline,
|
||||
.Nm
|
||||
will execute a system call to inhibit all kernel messages from being
|
||||
displayed on the console. Former versions always issued this system
|
||||
call and defaulted to all kernel messages except for panics. This is
|
||||
handled differently currently so
|
||||
.Nm
|
||||
doesn't need to set this value anymore. The
|
||||
.Ar NUM
|
||||
argument given to the
|
||||
.Fl c
|
||||
switch specifies the priority level of messages which will be directed
|
||||
to the console. Note that messages of a priority value LOWER than the
|
||||
indicated number will be directed to the console.
|
||||
.Pp
|
||||
For example, to have the kernel display all messages with a priority
|
||||
level of 3,
|
||||
.Ql (KERN_ERR)
|
||||
or more severe the following command would be executed:
|
||||
.Bd -literal -offset indent
|
||||
klogd \-c 4
|
||||
.Ed
|
||||
.Pp
|
||||
The definitions of the numeric values for kernel messages are given in
|
||||
the file
|
||||
.Pa kernel.h
|
||||
which can be found in the
|
||||
.Pa /usr/include/linux
|
||||
directory if the kernel sources are installed. These values parallel
|
||||
the syslog priority values which are defined in the file
|
||||
.Pa syslog.h
|
||||
found in the
|
||||
.PA /usr/include/sys
|
||||
sub-directory.
|
||||
.Pp
|
||||
The console log level is usually configured with the
|
||||
.Xr sysctl 8
|
||||
program, directly or via its configuration file
|
||||
.Pa /etc/sysctl.conf .
|
||||
In this file the following line
|
||||
.Bd -lilteral -offset indent
|
||||
kernel.printk = 4 4 1 7
|
||||
.Ed
|
||||
.Pp
|
||||
corresponds to the sampe setting above.
|
||||
.Sh SIGNALS
|
||||
.Nm
|
||||
responds to eight signals:
|
||||
.Pp
|
||||
.Bl -tag -width TERM
|
||||
.It HUP , INT , KILL , TERM
|
||||
The SIGINT, SIGKILL, SIGTERM and SIGHUP signals cause the daemon to
|
||||
close its kernel log sources and terminate gracefully.
|
||||
.It TSTP , CONT
|
||||
The SIGTSTP and SIGCONT signals are used to start and stop kernel
|
||||
logging. Upon receipt of SIGTSTP the daemon will close its log sources
|
||||
and spin in an idle loop. Subsequent receipt of SIGCONT cause the
|
||||
daemon to go through its initialization sequence and re-choose an input
|
||||
source. Using SIGSTOP and SIGCONT in combination the kernel log input
|
||||
can be re-chosen without stopping and restarting the daemon. For
|
||||
example if the
|
||||
.PA /proc
|
||||
file system is to be un-mounted the following command sequence should be
|
||||
used:
|
||||
.Bd -literal -offset indent
|
||||
kill -TSTP pid
|
||||
umount /proc
|
||||
kill -CONT pid
|
||||
.Ed
|
||||
.Pp
|
||||
Notations will be made in the system logs with
|
||||
.Ql LOG_INFO
|
||||
priority documenting the start/stop of logging.
|
||||
.It USR1 , USR2
|
||||
The SIGUSR1 and SIGUSR2 signals are used to initiate loading/reloading
|
||||
of kernel symbol information. Receipt of SIGUSR1 will cause the kernel
|
||||
module symbols to be reloaded. Signaling the daemon with SIGUSR2 will
|
||||
cause both the static kernel symbols and the kernel module symbols to be
|
||||
reloaded.
|
||||
.Pp
|
||||
Provided that the
|
||||
.Pa System.map
|
||||
file is placed in an appropriate location the signal of generally
|
||||
greatest usefulness is SIGUSR1. It is designed to be used to signal the
|
||||
daemon when kernel modules are loaded/unloaded. Sending this signal to
|
||||
the daemon after a kernel module state change will insure that proper
|
||||
resolution of symbols will occur if a protection fault occurs in the
|
||||
address space occupied by a kernel module.
|
||||
.El
|
||||
.Pp
|
||||
.Sh FILES
|
||||
.Bl -tag -width TERM
|
||||
.It Pa /proc/kmsg
|
||||
One source for kernel messages for
|
||||
.Nm klogd
|
||||
.It Pa /var/run/klogd.pid
|
||||
The file containing the process id of
|
||||
.Nm
|
||||
.It Pa /boot/System.map , Pa /System.map , Pa /usr/src/linux/System.map
|
||||
Default locations for kernel system maps
|
||||
.Ed
|
||||
.Sh BUGS
|
||||
Probably numerous. Well formed unidiffs and/or GitHub pull
|
||||
requests appreciated.
|
||||
.Sh SEE ALSO
|
||||
.Xr syslogd 8
|
||||
.Xr syslog 2
|
||||
.Xr klogctl 2
|
||||
.Sh AUTHORS
|
||||
The kernel log daemon
|
||||
.Nm
|
||||
was originally written by Steve Lord <lord@cray.com>, Greg Wettstein
|
||||
made major improvements. Martin Schulze <joey@infodrom.org> fixed some
|
||||
bugs and took over maintenance. Later
|
||||
.An Joachim Nilsson Aq Mt troglobit@gmail.com
|
||||
picked up maintenance at GitHub.
|
@ -173,11 +173,6 @@ and
|
||||
in GLIBC does not allow logging to the
|
||||
.Ql kern
|
||||
facility.
|
||||
.Xr klogd 8
|
||||
circumvents this restriction when logging to
|
||||
.Xr syslogd 8
|
||||
by using the
|
||||
.Lb libsyslog
|
||||
.Pp
|
||||
The
|
||||
.I priority
|
||||
@ -543,7 +538,6 @@ intermediate whitespace.
|
||||
.Sh SEE ALSO
|
||||
.Xr mkfifo 1 ,
|
||||
.Xr sysklogd 8 ,
|
||||
.Xr klogd 8 ,
|
||||
.Xr logger 1 ,
|
||||
.Xr syslog 2 ,
|
||||
.Xr syslogp 3 .
|
||||
|
@ -10,7 +10,7 @@
|
||||
.Os "sysklogd (2.0)"
|
||||
.Sh NAME
|
||||
.Nm syslogd
|
||||
.Nd System Log Daemon
|
||||
.Nd System and Kernel Log Daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl ?46AdFknsTv
|
||||
@ -27,14 +27,7 @@
|
||||
.Nm
|
||||
support RFC3164 and RFC5424 style log messages for both local and remote
|
||||
logging using Internet and UNIX domain sockets. Differences in style is
|
||||
shown below. The optional companion daemon,
|
||||
.Xr klogd 8 ,
|
||||
can be used to trap kernel messages and interpret events like Oops. By
|
||||
default
|
||||
.Nm klogd
|
||||
is not built and
|
||||
.Nm
|
||||
handles reading and logging of kernel messages.
|
||||
shown below.
|
||||
.Pp
|
||||
.Bl -tag -compact -width "RFC3164:"
|
||||
.It RFC3164:
|
||||
@ -184,11 +177,7 @@ facility
|
||||
.Ql user .
|
||||
Usually the
|
||||
.Ql kern
|
||||
facility is reserved for kernel log messages. When the
|
||||
.Nm klogd
|
||||
daemon runs alongside
|
||||
.Nm ,
|
||||
this option is always set.
|
||||
facility is reserved for kernel log messages.
|
||||
.It Fl m Ar interval
|
||||
Specify interval in minutes between
|
||||
.Ql -- MARK --
|
||||
@ -544,10 +533,9 @@ kill -SIGNAL `cat /var/run/syslogd.pid`
|
||||
.It Pa /dev/log
|
||||
The UNIX domain socket to from where local syslog messages are read.
|
||||
.It Pa /proc/kmsg
|
||||
The Linux kernel log file
|
||||
The kernel log file
|
||||
.Nm
|
||||
reads when built without the optional
|
||||
.Nm klogd .
|
||||
reads on Linux.
|
||||
.It Pa /etc/syslog.conf
|
||||
Configuration file for
|
||||
.Nm .
|
||||
@ -588,7 +576,6 @@ correctly, this should be reported as a bug to this project. See below
|
||||
for contact details.
|
||||
.Sh SEE ALSO
|
||||
.Xr syslog.conf 5 ,
|
||||
.Xr klogd 8 ,
|
||||
.Xr logger 1 ,
|
||||
.Xr syslog 2 ,
|
||||
.Xr syslogp 3 ,
|
||||
|
3
src/.gitignore
vendored
3
src/.gitignore
vendored
@ -1,11 +1,8 @@
|
||||
*.o
|
||||
*.lo
|
||||
.libs/*
|
||||
klogd
|
||||
logger
|
||||
syslogd
|
||||
syslog_tst
|
||||
tsyslogd
|
||||
libcompat.la
|
||||
libsyslog.la
|
||||
libsyslog.pc
|
||||
|
@ -21,10 +21,6 @@ sbin_PROGRAMS = syslogd
|
||||
lib_LTLIBRARIES = libsyslog.la
|
||||
noinst_LTLIBRARIES = libcompat.la
|
||||
|
||||
if ENABLE_KLOGD
|
||||
sbin_PROGRAMS += klogd
|
||||
endif
|
||||
|
||||
if ENABLE_LOGGER
|
||||
bin_PROGRAMS += logger
|
||||
endif
|
||||
@ -38,11 +34,6 @@ syslogd_SOURCES = syslogd.c syslogd.h socket.c socket.h syslog.h timer.c t
|
||||
syslogd_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600
|
||||
syslogd_LDADD = $(LIBS) $(LIBOBJS)
|
||||
|
||||
klogd_SOURCES = klogd.c klogd.h syslog.h compat.h ksym.c ksyms.h ksym_mod.c module.h
|
||||
klogd_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
klogd_LDADD = $(LIBS) $(LIBOBJS)
|
||||
klogd_LDADD += libsyslog.la
|
||||
|
||||
logger_SOURCES = logger.c syslog.h
|
||||
logger_CPPFLAGS = $(AM_CPPFLAGS) -D_XOPEN_SOURCE=600
|
||||
logger_LDADD = $(LIBS) $(LIBOBJS)
|
||||
|
827
src/klogd.c
827
src/klogd.c
@ -1,827 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* klogd.c - main program for Linux kernel log daemon.
|
||||
*
|
||||
* Copyright (c) 1995 Dr. G.W. Wettstein <greg@wind.rmcc.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "compat.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "klogd.h"
|
||||
#include "ksyms.h"
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define __LIBRARY__
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/klog.h>
|
||||
#define ksyslog klogctl
|
||||
|
||||
#define LOG_BUFFER_SIZE 4096
|
||||
#define LOG_LINE_LENGTH 1000
|
||||
|
||||
static struct syslog_data log = SYSLOG_DATA_INIT;
|
||||
|
||||
static char *PidFile = RUNSTATEDIR "/klogd.pid";
|
||||
|
||||
static int kmsg;
|
||||
static int change_state = 0;
|
||||
static int terminate = 0;
|
||||
static int caught_TSTP = 0;
|
||||
static int reload_symbols = 0;
|
||||
static int console_log_level = -1;
|
||||
|
||||
static int use_syscall = 0;
|
||||
static int one_shot = 0;
|
||||
static int symbol_lookup = 1;
|
||||
static int no_fork = 0; /* don't fork - don't run in daemon mode */
|
||||
|
||||
static char *symfile = NULL;
|
||||
static char log_buffer[LOG_BUFFER_SIZE];
|
||||
|
||||
static FILE *output_file = NULL;
|
||||
|
||||
static enum LOGSRC { none, proc, kernel } logsrc;
|
||||
|
||||
int debugging = 0;
|
||||
int symbols_twice = 0;
|
||||
|
||||
/* Function prototypes. */
|
||||
extern int ksyslog(int type, char *buf, int len);
|
||||
static void CloseLogSrc(void);
|
||||
extern void restart(int sig);
|
||||
extern void stop_logging(int sig);
|
||||
extern void stop_daemon(int sig);
|
||||
extern void reload_daemon(int sig);
|
||||
static void Terminate(void);
|
||||
static void ReloadSymbols(void);
|
||||
static void ChangeLogging(void);
|
||||
static enum LOGSRC GetKernelLogSrc(void);
|
||||
static void LogLine(char *ptr, int len);
|
||||
static void LogKernelLine(void);
|
||||
static void LogProcLine(void);
|
||||
extern int main(int argc, char *argv[]);
|
||||
|
||||
static void CloseLogSrc(void)
|
||||
{
|
||||
/* Shutdown the log sources. */
|
||||
switch (logsrc) {
|
||||
case kernel:
|
||||
ksyslog(0, 0, 0);
|
||||
Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped.");
|
||||
break;
|
||||
|
||||
case proc:
|
||||
close(kmsg);
|
||||
Syslog(LOG_INFO, "Kernel logging (proc) stopped.");
|
||||
break;
|
||||
|
||||
case none:
|
||||
break;
|
||||
}
|
||||
|
||||
if (output_file != NULL)
|
||||
fflush(output_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal handler to terminate the parent process.
|
||||
*/
|
||||
void doexit(int signo)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void restart(int signo)
|
||||
{
|
||||
change_state = 1;
|
||||
caught_TSTP = 0;
|
||||
}
|
||||
|
||||
void stop_logging(int signo)
|
||||
{
|
||||
change_state = 1;
|
||||
caught_TSTP = 1;
|
||||
}
|
||||
|
||||
void stop_daemon(int signo)
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void reload_daemon(int signo)
|
||||
{
|
||||
change_state = 1;
|
||||
reload_symbols = 1;
|
||||
|
||||
if (signo == SIGUSR2)
|
||||
++reload_symbols;
|
||||
}
|
||||
|
||||
static void Terminate(void)
|
||||
{
|
||||
CloseLogSrc();
|
||||
Syslog(LOG_INFO, "Kernel log daemon terminating.");
|
||||
sleep(1);
|
||||
|
||||
if (output_file != NULL)
|
||||
fclose(output_file);
|
||||
closelog_r(&log);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void ReloadSymbols(void)
|
||||
{
|
||||
if (symbol_lookup) {
|
||||
if (reload_symbols > 1)
|
||||
InitKsyms(symfile);
|
||||
InitMsyms();
|
||||
}
|
||||
reload_symbols = change_state = 0;
|
||||
}
|
||||
|
||||
static void ChangeLogging(void)
|
||||
{
|
||||
/* Terminate kernel logging. */
|
||||
if (terminate == 1)
|
||||
Terminate();
|
||||
|
||||
/* Indicate that something is happening. */
|
||||
Syslog(LOG_INFO, "klogd v%s, ---------- state change ----------\n",
|
||||
PACKAGE_VERSION);
|
||||
|
||||
/* Reload symbols. */
|
||||
if (reload_symbols > 0) {
|
||||
ReloadSymbols();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop kernel logging. */
|
||||
if (caught_TSTP == 1) {
|
||||
CloseLogSrc();
|
||||
logsrc = none;
|
||||
change_state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rest of this function is responsible for restarting
|
||||
* kernel logging after it was stopped.
|
||||
*
|
||||
* In the following section we make a decision based on the
|
||||
* kernel log state as to what is causing us to restart. Somewhat
|
||||
* groady but it keeps us from creating another static variable.
|
||||
*/
|
||||
if (logsrc != none) {
|
||||
Syslog(LOG_INFO, "Kernel logging re-started after SIGSTOP.");
|
||||
change_state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restart logging. */
|
||||
logsrc = GetKernelLogSrc();
|
||||
change_state = 0;
|
||||
}
|
||||
|
||||
static enum LOGSRC GetKernelLogSrc(void)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
/* Set level of kernel console messaging.. */
|
||||
if ((console_log_level != -1) && (ksyslog(8, NULL, console_log_level) < 0) &&
|
||||
(errno == EINVAL)) {
|
||||
/*
|
||||
* An invalid arguement error probably indicates that
|
||||
* a pre-0.14 kernel is being run. At this point we
|
||||
* issue an error message and simply shut-off console
|
||||
* logging completely.
|
||||
*/
|
||||
Syslog(LOG_WARN, "Cannot set console log level - disabling console output.");
|
||||
}
|
||||
|
||||
/*
|
||||
* First do a stat to determine whether or not the proc based
|
||||
* file system is available to get kernel messages from.
|
||||
*/
|
||||
if (use_syscall ||
|
||||
((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT))) {
|
||||
/* Initialize kernel logging. */
|
||||
ksyslog(1, NULL, 0);
|
||||
Syslog(LOG_INFO, "klogd v%s, log source = ksyslog started.", PACKAGE_VERSION);
|
||||
return kernel;
|
||||
}
|
||||
|
||||
if ((kmsg = open(_PATH_KLOG, O_RDONLY)) < 0) {
|
||||
fprintf(stderr, "klogd: Cannot open proc file system, %d - %s.\n",
|
||||
errno, strerror(errno));
|
||||
ksyslog(7, NULL, 0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Syslog(LOG_INFO, "klogd v%s, log source = %s started.",
|
||||
VERSION, _PATH_KLOG);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
extern void Syslog(int priority, char *fmt, ...)
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
char *argl;
|
||||
|
||||
if (debugging) {
|
||||
fputs("Logging line:\n", stderr);
|
||||
fprintf(stderr, "\tLine: %s\n", fmt);
|
||||
fprintf(stderr, "\tPriority: %d\n", priority);
|
||||
}
|
||||
|
||||
/* Handle output to a file. */
|
||||
if (output_file != NULL) {
|
||||
va_start(ap, fmt);
|
||||
vfprintf(output_file, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', output_file);
|
||||
fflush(output_file);
|
||||
if (!one_shot)
|
||||
fsync(fileno(output_file));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Output using syslog. */
|
||||
if (!strcmp(fmt, "%s")) {
|
||||
va_start(ap, fmt);
|
||||
argl = va_arg(ap, char *);
|
||||
if (argl[0] == '<' && argl[1] && argl[2] == '>') {
|
||||
switch (argl[1]) {
|
||||
case '0':
|
||||
priority = LOG_EMERG;
|
||||
break;
|
||||
case '1':
|
||||
priority = LOG_ALERT;
|
||||
break;
|
||||
case '2':
|
||||
priority = LOG_CRIT;
|
||||
break;
|
||||
case '3':
|
||||
priority = LOG_ERR;
|
||||
break;
|
||||
case '4':
|
||||
priority = LOG_WARN;
|
||||
break;
|
||||
case '5':
|
||||
priority = LOG_NOTICE;
|
||||
break;
|
||||
case '6':
|
||||
priority = LOG_INFO;
|
||||
break;
|
||||
case '7':
|
||||
default:
|
||||
priority = LOG_DEBUG;
|
||||
}
|
||||
argl += 3;
|
||||
}
|
||||
syslog_r(priority, &log, fmt, argl);
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsyslog_r(priority, &log, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy characters from ptr to line until a char in the delim
|
||||
* string is encountered or until min( space, len ) chars have
|
||||
* been copied.
|
||||
*
|
||||
* Returns the actual number of chars copied.
|
||||
*/
|
||||
static int copyin(char *line, int space,
|
||||
const char *ptr, int len,
|
||||
const char *delim)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
|
||||
count = len < space ? len : space;
|
||||
|
||||
for (i = 0; i < count && !strchr(delim, *ptr); i++)
|
||||
*line++ = *ptr++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Messages are separated by "\n". Messages longer than
|
||||
* LOG_LINE_LENGTH are broken up.
|
||||
*
|
||||
* Kernel symbols show up in the input buffer as : "[<aaaaaa>]",
|
||||
* where "aaaaaa" is the address. These are replaced with
|
||||
* "[symbolname+offset/size]" in the output line - symbolname,
|
||||
* offset, and size come from the kernel symbol table.
|
||||
*
|
||||
* If a kernel symbol happens to fall at the end of a message close
|
||||
* in length to LOG_LINE_LENGTH, the symbol will not be expanded.
|
||||
* (This should never happen, since the kernel should never generate
|
||||
* messages that long.
|
||||
*
|
||||
* To preserve the original addresses, lines containing kernel symbols
|
||||
* are output twice. Once with the symbols converted and again with the
|
||||
* original text. Just in case somebody wants to run their own Oops
|
||||
* analysis on the syslog, e.g. ksymoops.
|
||||
*/
|
||||
static void LogLine(char *ptr, int len)
|
||||
{
|
||||
enum parse_state_enum {
|
||||
PARSING_TEXT,
|
||||
PARSING_SYMSTART, /* at < */
|
||||
PARSING_SYMBOL,
|
||||
PARSING_SYMEND /* at ] */
|
||||
};
|
||||
|
||||
static char line_buff[LOG_LINE_LENGTH];
|
||||
|
||||
static char * line = line_buff;
|
||||
static enum parse_state_enum parse_state = PARSING_TEXT;
|
||||
static int space = sizeof(line_buff) - 1;
|
||||
|
||||
static char *sym_start; /* points at the '<' of a symbol */
|
||||
|
||||
int delta = 0; /* number of chars copied */
|
||||
int symbols_expanded = 0; /* 1 if symbols were expanded */
|
||||
int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */
|
||||
char *save_ptr = ptr; /* save start of input line */
|
||||
int save_len = len; /* save length at start of input line */
|
||||
|
||||
while (len > 0) {
|
||||
if (space == 0) { /* line buffer is full */
|
||||
/*
|
||||
** Line too long. Start a new line.
|
||||
*/
|
||||
*line = 0; /* force null terminator */
|
||||
|
||||
if (debugging) {
|
||||
fputs("Line buffer full:\n", stderr);
|
||||
fprintf(stderr, "\tLine: %s\n", line);
|
||||
}
|
||||
|
||||
Syslog(LOG_INFO, "%s", line_buff);
|
||||
line = line_buff;
|
||||
space = sizeof(line_buff) - 1;
|
||||
parse_state = PARSING_TEXT;
|
||||
symbols_expanded = 0;
|
||||
skip_symbol_lookup = 0;
|
||||
save_ptr = ptr;
|
||||
save_len = len;
|
||||
}
|
||||
|
||||
switch (parse_state) {
|
||||
case PARSING_TEXT:
|
||||
delta = copyin(line, space, ptr, len, "\n[");
|
||||
line += delta;
|
||||
ptr += delta;
|
||||
space -= delta;
|
||||
len -= delta;
|
||||
|
||||
if (space == 0 || len == 0)
|
||||
break; /* full line_buff or end of input buffer */
|
||||
|
||||
if (*ptr == '\0') { /* zero byte */
|
||||
ptr++; /* skip zero byte */
|
||||
space -= 1;
|
||||
len -= 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (*ptr == '\n') { /* newline */
|
||||
ptr++; /* skip newline */
|
||||
space -= 1;
|
||||
len -= 1;
|
||||
|
||||
*line = 0; /* force null terminator */
|
||||
Syslog(LOG_INFO, "%s", line_buff);
|
||||
line = line_buff;
|
||||
space = sizeof(line_buff) - 1;
|
||||
if (symbols_twice) {
|
||||
if (symbols_expanded) {
|
||||
/* reprint this line without symbol lookup */
|
||||
symbols_expanded = 0;
|
||||
skip_symbol_lookup = 1;
|
||||
ptr = save_ptr;
|
||||
len = save_len;
|
||||
} else {
|
||||
skip_symbol_lookup = 0;
|
||||
save_ptr = ptr;
|
||||
save_len = len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*ptr == '[') { /* possible kernel symbol */
|
||||
*line++ = *ptr++;
|
||||
space -= 1;
|
||||
len -= 1;
|
||||
if (!skip_symbol_lookup)
|
||||
parse_state = PARSING_SYMSTART; /* at < */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSING_SYMSTART:
|
||||
if (*ptr != '<') {
|
||||
parse_state = PARSING_TEXT; /* not a symbol */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** Save this character for now. If this turns out to
|
||||
** be a valid symbol, this char will be replaced later.
|
||||
** If not, we'll just leave it there.
|
||||
*/
|
||||
sym_start = line; /* this will point at the '<' */
|
||||
|
||||
*line++ = *ptr++;
|
||||
space -= 1;
|
||||
len -= 1;
|
||||
parse_state = PARSING_SYMBOL; /* symbol... */
|
||||
break;
|
||||
|
||||
case PARSING_SYMBOL:
|
||||
delta = copyin(line, space, ptr, len, ">\n[");
|
||||
line += delta;
|
||||
ptr += delta;
|
||||
space -= delta;
|
||||
len -= delta;
|
||||
if (space == 0 || len == 0)
|
||||
break; /* full line_buff or end of input buffer */
|
||||
|
||||
if (*ptr != '>') {
|
||||
parse_state = PARSING_TEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
*line++ = *ptr++; /* copy the '>' */
|
||||
space -= 1;
|
||||
len -= 1;
|
||||
|
||||
parse_state = PARSING_SYMEND;
|
||||
break;
|
||||
|
||||
case PARSING_SYMEND:
|
||||
if (*ptr != ']') {
|
||||
parse_state = PARSING_TEXT; /* not a symbol */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** It's really a symbol! Replace address with the
|
||||
** symbol text.
|
||||
*/
|
||||
{
|
||||
unsigned long value;
|
||||
struct symbol sym;
|
||||
char *symbol;
|
||||
int sym_space;
|
||||
|
||||
*(line - 1) = 0; /* null terminate the address string */
|
||||
value = strtoul(sym_start + 1, NULL, 16);
|
||||
*(line - 1) = '>'; /* put back delim */
|
||||
|
||||
symbol = LookupSymbol(value, &sym);
|
||||
if (!symbol_lookup || symbol == NULL) {
|
||||
parse_state = PARSING_TEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** verify there is room in the line buffer
|
||||
*/
|
||||
sym_space = space + (line - sym_start);
|
||||
if (sym_space < (int)strlen(symbol) + 30) { /*(30 should be overkill)*/
|
||||
parse_state = PARSING_TEXT; /* not enough space */
|
||||
break;
|
||||
}
|
||||
|
||||
delta = sprintf(sym_start, "%s+0x%x/0x%02x]",
|
||||
symbol, sym.offset, sym.size);
|
||||
|
||||
space = sym_space + delta;
|
||||
line = sym_start + delta;
|
||||
symbols_expanded = 1;
|
||||
}
|
||||
ptr++;
|
||||
len--;
|
||||
parse_state = PARSING_TEXT;
|
||||
break;
|
||||
|
||||
default: /* Can't get here! */
|
||||
parse_state = PARSING_TEXT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LogKernelLine(void)
|
||||
{
|
||||
int rdcnt;
|
||||
|
||||
/*
|
||||
* Zero-fill the log buffer. This should cure a multitude of
|
||||
* problems with klogd logging the tail end of the message buffer
|
||||
* which will contain old messages. Then read the kernel log
|
||||
* messages into this fresh buffer.
|
||||
*/
|
||||
memset(log_buffer, 0, sizeof(log_buffer));
|
||||
if ((rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer) - 1)) < 0) {
|
||||
if (errno == EINTR)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "klogd: Error return from sys_sycall: %d - %s\n",
|
||||
errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
LogLine(log_buffer, rdcnt);
|
||||
}
|
||||
|
||||
static void LogProcLine(void)
|
||||
{
|
||||
int rdcnt;
|
||||
|
||||
/*
|
||||
* Zero-fill the log buffer. This should cure a multitude of
|
||||
* problems with klogd logging the tail end of the message buffer
|
||||
* which will contain old messages. Then read the kernel messages
|
||||
* from the message pseudo-file into this fresh buffer.
|
||||
*/
|
||||
memset(log_buffer, 0, sizeof(log_buffer));
|
||||
if ((rdcnt = read(kmsg, log_buffer, sizeof(log_buffer) - 1)) < 0) {
|
||||
if (errno == EINTR)
|
||||
return;
|
||||
Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.",
|
||||
errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
LogLine(log_buffer, rdcnt);
|
||||
}
|
||||
|
||||
int usage(int code)
|
||||
{
|
||||
fprintf(stdout,
|
||||
"Usage:\n"
|
||||
" klogd [-2dnopsvx?] [-c NUM] [-f FILE] [-k FILE]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -? Show this help text\n"
|
||||
" -2 Print line twice if symbols are successfully expanded\n"
|
||||
" -c NUM Set default log level of console messages to NUM (1-8)\n"
|
||||
" -d Enable debug mode\n"
|
||||
" -f FILE Log messages to FILE rather than the syslog facility\n"
|
||||
" -k FILE Location of kernel symbols (System.map), default: auto\n"
|
||||
" -n | -F Run in foreground, required when run from a modern init/supervisor\n"
|
||||
" -o Run once, read kernel log messages and syslog them, then exit\n"
|
||||
" -p Paranoia mode, forces klogd to reload all kernel symbols on Ooops\n"
|
||||
" -s Force use of system call interface to kernel message buffers\n"
|
||||
" -v Show program version and exit\n"
|
||||
" -x Omit EIP translation, i.e. do not read System.map file\n"
|
||||
"\n"
|
||||
"SIGUSR1 reloads kernel module symbols, SIGUSR2 reloads all kernel symbols.\n"
|
||||
"\n"
|
||||
"Bug report address: %s\n",
|
||||
PACKAGE_BUGREPORT);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *log_level = NULL;
|
||||
char *output = NULL;
|
||||
int use_output = 0;
|
||||
int ch;
|
||||
pid_t ppid = getpid();
|
||||
|
||||
/* Parse the command-line. */
|
||||
while ((ch = getopt(argc, argv, "c:dFf:k:nopsvx2?")) != EOF) {
|
||||
switch (ch) {
|
||||
case '2': /* Print lines with symbols twice. */
|
||||
symbols_twice = 1;
|
||||
break;
|
||||
|
||||
case 'c': /* Set console message level. */
|
||||
log_level = optarg;
|
||||
break;
|
||||
|
||||
case 'd': /* Activity debug mode. */
|
||||
debugging = 1;
|
||||
break;
|
||||
|
||||
case 'f': /* Define an output file. */
|
||||
output = optarg;
|
||||
use_output++;
|
||||
break;
|
||||
|
||||
case 'k': /* Kernel symbol file. */
|
||||
symfile = optarg;
|
||||
break;
|
||||
|
||||
case 'F': /* compat with syslogd */
|
||||
case 'n': /* don't fork */
|
||||
no_fork++;
|
||||
break;
|
||||
|
||||
case 'o': /* One-shot mode. */
|
||||
one_shot = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
SetParanoiaLevel(1); /* Load symbols on oops. */
|
||||
break;
|
||||
|
||||
case 's': /* Use syscall interface. */
|
||||
use_syscall = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
printf("klogd v%s\n", VERSION);
|
||||
exit(1);
|
||||
|
||||
case 'x':
|
||||
symbol_lookup = 0;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set console logging level. */
|
||||
if (log_level != NULL) {
|
||||
if ((strlen(log_level) > 1) ||
|
||||
(strchr("12345678", *log_level) == NULL)) {
|
||||
fprintf(stderr, "klogd: Invalid console logging level <%s>.\n", log_level);
|
||||
return 1;
|
||||
}
|
||||
console_log_level = *log_level - '0';
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code allows klogd to auto-background itself.
|
||||
* What happens is that the program forks and the parent quits.
|
||||
* The child closes all its open file descriptors, and issues a
|
||||
* call to setsid to establish itself as an independent session
|
||||
* immune from control signals.
|
||||
*
|
||||
* fork() is only called if it should run in daemon mode, fork is
|
||||
* not disabled with the command line argument and there's no
|
||||
* such process running.
|
||||
*/
|
||||
if ((!one_shot) && (!no_fork)) {
|
||||
signal(SIGTERM, doexit);
|
||||
if (fork() == 0) {
|
||||
int num_fds = getdtablesize();
|
||||
int fl;
|
||||
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
|
||||
/* This is the child closing its file descriptors. */
|
||||
for (fl = 0; fl <= num_fds; ++fl) {
|
||||
if (fileno(stdout) == fl && use_output)
|
||||
if (strcmp(output, "-") == 0)
|
||||
continue;
|
||||
close(fl);
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
setsid();
|
||||
} else {
|
||||
/*
|
||||
* Parent process
|
||||
*/
|
||||
sleep(300);
|
||||
/*
|
||||
* Not reached unless something major went wrong.
|
||||
*/
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pidfile(PidFile)) {
|
||||
Syslog(LOG_ERR, "Failed creating PID file %s: %s",
|
||||
PidFile, strerror(errno));
|
||||
Terminate();
|
||||
}
|
||||
|
||||
/* Signal setups. */
|
||||
for (ch = 1; ch < NSIG; ++ch)
|
||||
signal(ch, SIG_IGN);
|
||||
signal(SIGINT, stop_daemon);
|
||||
signal(SIGKILL, stop_daemon);
|
||||
signal(SIGTERM, stop_daemon);
|
||||
signal(SIGHUP, stop_daemon);
|
||||
signal(SIGTSTP, stop_logging);
|
||||
signal(SIGCONT, restart);
|
||||
signal(SIGUSR1, reload_daemon);
|
||||
signal(SIGUSR2, reload_daemon);
|
||||
|
||||
/* Open outputs. */
|
||||
if (use_output) {
|
||||
if (strcmp(output, "-") == 0)
|
||||
output_file = stdout;
|
||||
else if ((output_file = fopen(output, "w")) == NULL) {
|
||||
fprintf(stderr, "klogd: Cannot open output file "
|
||||
"%s - %s\n",
|
||||
output, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* No, I really want to use LOG_KERN */
|
||||
log.log_fac = LOG_KERN;
|
||||
openlog_r("kernel", 0, LOG_KERN, &log);
|
||||
}
|
||||
|
||||
/* Handle one-shot logging. */
|
||||
if (one_shot) {
|
||||
if (symbol_lookup) {
|
||||
InitKsyms(symfile);
|
||||
InitMsyms();
|
||||
}
|
||||
if ((logsrc = GetKernelLogSrc()) == kernel)
|
||||
LogKernelLine();
|
||||
else
|
||||
LogProcLine();
|
||||
Terminate();
|
||||
}
|
||||
|
||||
#if defined(KLOGD_DELAY)
|
||||
sleep(KLOGD_DELAY);
|
||||
#endif
|
||||
|
||||
/* Determine where kernel logging information is to come from. */
|
||||
logsrc = GetKernelLogSrc();
|
||||
if (symbol_lookup) {
|
||||
InitKsyms(symfile);
|
||||
InitMsyms();
|
||||
}
|
||||
|
||||
if (getpid() != ppid)
|
||||
kill(ppid, SIGTERM);
|
||||
|
||||
while (1) {
|
||||
if (change_state)
|
||||
ChangeLogging();
|
||||
|
||||
switch (logsrc) {
|
||||
case kernel:
|
||||
LogKernelLine();
|
||||
break;
|
||||
|
||||
case proc:
|
||||
LogProcLine();
|
||||
break;
|
||||
|
||||
case none:
|
||||
pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
36
src/klogd.h
36
src/klogd.h
@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* klogd.h - main header file for Linux kernel log daemon.
|
||||
*
|
||||
* Copyright (c) 1995 Dr. G.W. Wettstein <greg@wind.rmcc.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SYSKLOGD_KLOGD_H_
|
||||
#define SYSKLOGD_KLOGD_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "syslog.h"
|
||||
|
||||
extern int InitKsyms(char *);
|
||||
extern int InitMsyms(void);
|
||||
extern char *ExpandKadds(char *, char *);
|
||||
extern void SetParanoiaLevel(int);
|
||||
extern void Syslog(int priority, char *fmt, ...);
|
||||
|
||||
#endif /* SYSKLOGD_KLOGD_H_ */
|
725
src/ksym.c
725
src/ksym.c
@ -1,725 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* ksym.c - functions for kernel address->symbol translation
|
||||
*
|
||||
* Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
|
||||
* Copyright (c) 1996 Enjellic Systems Development
|
||||
* Copyright (c) 1997-2007 Martin Schulze <joey@infodrom.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains functions which handle the translation of kernel
|
||||
* numeric addresses into symbols for the klogd utility.
|
||||
*/
|
||||
|
||||
#include "klogd.h"
|
||||
#include "ksyms.h"
|
||||
#include "module.h"
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define VERBOSE_DEBUGGING 0
|
||||
|
||||
int num_syms = 0;
|
||||
static int i_am_paranoid = 0;
|
||||
static char vstring[12];
|
||||
static struct sym_table *sym_array = NULL;
|
||||
|
||||
static char *system_maps[] =
|
||||
{
|
||||
"/boot/System.map",
|
||||
"/System.map",
|
||||
"/usr/src/linux/System.map",
|
||||
#if defined(TEST)
|
||||
"./System.map",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
#if defined(TEST)
|
||||
int debugging;
|
||||
#else
|
||||
extern int debugging;
|
||||
#endif
|
||||
|
||||
/* Function prototypes. */
|
||||
static char *FindSymbolFile(void);
|
||||
static int AddSymbol(unsigned long, char *);
|
||||
static void FreeSymbols(void);
|
||||
static int CheckVersion(char *);
|
||||
static int CheckMapVersion(char *);
|
||||
|
||||
/**************************************************************************
|
||||
* Function: InitKsyms
|
||||
*
|
||||
* Purpose: This function is responsible for initializing and loading
|
||||
* the data tables used by the kernel address translations.
|
||||
*
|
||||
* Arguments: (char *) mapfile
|
||||
*
|
||||
* mapfile:-> A pointer to a complete path
|
||||
* specification of the file containing
|
||||
* the kernel map to use.
|
||||
*
|
||||
* Return: int
|
||||
*
|
||||
* A boolean style context is returned. The return value will
|
||||
* be true if initialization was successful. False if not.
|
||||
**************************************************************************/
|
||||
int InitKsyms(char *mapfile)
|
||||
{
|
||||
unsigned long int address;
|
||||
FILE *sym_file;
|
||||
char sym[512];
|
||||
char type;
|
||||
int version = 0;
|
||||
|
||||
/* Check and make sure that we are starting with a clean slate. */
|
||||
if (num_syms > 0)
|
||||
FreeSymbols();
|
||||
|
||||
/*
|
||||
* Search for and open the file containing the kernel symbols.
|
||||
*/
|
||||
if (mapfile == NULL) {
|
||||
if ((mapfile = FindSymbolFile()) == NULL) {
|
||||
Syslog(LOG_WARN, "Cannot find a map file.");
|
||||
if (debugging)
|
||||
fputs("Cannot find a map file.\n", stderr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sym_file = fopen(mapfile, "r")) == NULL) {
|
||||
Syslog(LOG_WARN, "Cannot open map file: %s.", mapfile);
|
||||
if (debugging)
|
||||
fprintf(stderr, "Cannot open map file: %s.\n", mapfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the kernel symbol table file and add entries for each
|
||||
* line. I suspect that the use of fscanf is not really in vogue
|
||||
* but it was quick and dirty and IMHO suitable for fixed format
|
||||
* data such as this. If anybody doesn't agree with this please
|
||||
* e-mail me a diff containing a parser with suitable political
|
||||
* correctness -- GW.
|
||||
*/
|
||||
while (!feof(sym_file)) {
|
||||
if (fscanf(sym_file, "%lx %c %511s\n", &address, &type, sym) != 3) {
|
||||
Syslog(LOG_ERR, "Error in symbol table input (#1).");
|
||||
fclose(sym_file);
|
||||
return 0;
|
||||
}
|
||||
if (VERBOSE_DEBUGGING && debugging)
|
||||
fprintf(stderr, "Address: %lx, Type: %c, Symbol: %s\n",
|
||||
address, type, sym);
|
||||
|
||||
if (AddSymbol(address, sym) == 0) {
|
||||
Syslog(LOG_ERR, "Error adding symbol - %s.", sym);
|
||||
fclose(sym_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (version == 0)
|
||||
version = CheckVersion(sym);
|
||||
}
|
||||
|
||||
Syslog(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile);
|
||||
switch (version) {
|
||||
case -1:
|
||||
Syslog(LOG_WARN, "Symbols do not match kernel version.");
|
||||
num_syms = 0;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
Syslog(LOG_WARN, "Cannot verify that symbols match "
|
||||
"kernel version.");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Syslog(LOG_INFO, "Symbols match kernel version %s.", vstring);
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(sym_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: FindSymbolFile
|
||||
*
|
||||
* Purpose: This function is responsible for encapsulating the search
|
||||
* for a valid symbol file. Encapsulating the search for
|
||||
* the map file in this function allows an intelligent search
|
||||
* process to be implemented.
|
||||
*
|
||||
* The list of symbol files will be searched until either a
|
||||
* symbol file is found whose version matches the currently
|
||||
* executing kernel or the end of the list is encountered. If
|
||||
* the end of the list is encountered the first available
|
||||
* symbol file is returned to the caller.
|
||||
*
|
||||
* This strategy allows klogd to locate valid symbol files
|
||||
* for both a production and an experimental kernel. For
|
||||
* example a map for a production kernel could be installed
|
||||
* in /boot. If an experimental kernel is loaded the map
|
||||
* in /boot will be skipped and the map in /usr/src/linux would
|
||||
* be used if its version number matches the executing kernel.
|
||||
*
|
||||
* Arguments: None specified.
|
||||
*
|
||||
* Return: char *
|
||||
*
|
||||
* If a valid system map cannot be located a null pointer
|
||||
* is returned to the caller.
|
||||
*
|
||||
* If the search is succesful a pointer is returned to the
|
||||
* caller which points to the name of the file containing
|
||||
* the symbol table to be used.
|
||||
**************************************************************************/
|
||||
static char *FindSymbolFile(void)
|
||||
{
|
||||
static char symfile[100];
|
||||
struct utsname utsname;
|
||||
FILE *sym_file = NULL;
|
||||
char **mf = system_maps;
|
||||
char *file = NULL;
|
||||
|
||||
if (uname(&utsname) < 0) {
|
||||
Syslog(LOG_ERR, "Cannot get kernel version information.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debugging)
|
||||
fputs("Searching for symbol map.\n", stderr);
|
||||
|
||||
for (mf = system_maps; *mf != NULL && file == NULL; ++mf) {
|
||||
|
||||
sprintf(symfile, "%s-%s", *mf, utsname.release);
|
||||
if (debugging)
|
||||
fprintf(stderr, "Trying %s.\n", symfile);
|
||||
if ((sym_file = fopen(symfile, "r")) != NULL) {
|
||||
if (CheckMapVersion(symfile) == 1)
|
||||
file = symfile;
|
||||
fclose(sym_file);
|
||||
}
|
||||
if (sym_file == NULL || file == NULL) {
|
||||
sprintf(symfile, "%s", *mf);
|
||||
if (debugging)
|
||||
fprintf(stderr, "Trying %s.\n", symfile);
|
||||
if ((sym_file = fopen(symfile, "r")) != NULL) {
|
||||
if (CheckMapVersion(symfile) == 1)
|
||||
file = symfile;
|
||||
fclose(sym_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At this stage of the game we are at the end of the symbol
|
||||
* tables.
|
||||
*/
|
||||
if (debugging)
|
||||
fprintf(stderr, "End of search list encountered.\n");
|
||||
return file;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: CheckVersion
|
||||
*
|
||||
* Purpose: This function is responsible for determining whether or
|
||||
* the system map being loaded matches the version of the
|
||||
* currently running kernel.
|
||||
*
|
||||
* The kernel version is checked by examing a variable which
|
||||
* is of the form: _Version_66347 (a.out) or Version_66437 (ELF).
|
||||
*
|
||||
* The suffix of this variable is the current kernel version
|
||||
* of the kernel encoded in base 256. For example the
|
||||
* above variable would be decoded as:
|
||||
*
|
||||
* (66347 = 1*65536 + 3*256 + 43 = 1.3.43)
|
||||
*
|
||||
* (Insert appropriate deities here) help us if Linus ever
|
||||
* needs more than 255 patch levels to get a kernel out the
|
||||
* door... :-)
|
||||
*
|
||||
* Arguments: (char *) version
|
||||
*
|
||||
* version:-> A pointer to the string which
|
||||
* is to be decoded as a kernel
|
||||
* version variable.
|
||||
*
|
||||
* Return: int
|
||||
*
|
||||
* -1:-> The currently running kernel version does
|
||||
* not match this version string.
|
||||
*
|
||||
* 0:-> The string is not a kernel version variable.
|
||||
*
|
||||
* 1:-> The executing kernel is of the same version
|
||||
* as the version string.
|
||||
**************************************************************************/
|
||||
static int CheckVersion(char *version)
|
||||
{
|
||||
static char *prefix = { "Version_" };
|
||||
int vnum;
|
||||
int major;
|
||||
int minor;
|
||||
int patch;
|
||||
struct utsname utsname;
|
||||
int kvnum;
|
||||
|
||||
/* Early return if there is no hope. */
|
||||
if (strncmp(version, prefix, strlen(prefix)) == 0 /* ELF */ ||
|
||||
(*version == '_' &&
|
||||
strncmp(++version, prefix, strlen(prefix)) == 0) /* a.out */)
|
||||
;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Since the symbol looks like a kernel version we can start
|
||||
* things out by decoding the version string into its component
|
||||
* parts.
|
||||
*/
|
||||
vnum = atoi(version + strlen(prefix));
|
||||
patch = vnum & 0x000000FF;
|
||||
minor = (vnum >> 8) & 0x000000FF;
|
||||
major = (vnum >> 16) & 0x000000FF;
|
||||
if (debugging)
|
||||
fprintf(stderr, "Version string = %s, Major = %d, "
|
||||
"Minor = %d, Patch = %d.\n",
|
||||
version +
|
||||
strlen(prefix),
|
||||
major, minor,
|
||||
patch);
|
||||
sprintf(vstring, "%d.%d.%d", major, minor, patch);
|
||||
|
||||
/*
|
||||
* We should now have the version string in the vstring variable in
|
||||
* the same format that it is stored in by the kernel. We now
|
||||
* ask the kernel for its version information and compare the two
|
||||
* values to determine if our system map matches the kernel
|
||||
* version level.
|
||||
*/
|
||||
if (uname(&utsname) < 0) {
|
||||
Syslog(LOG_ERR, "Cannot get kernel version information.");
|
||||
return 0;
|
||||
}
|
||||
if (debugging)
|
||||
fprintf(stderr, "Comparing kernel %s with symbol table %s.\n",
|
||||
utsname.release, vstring);
|
||||
|
||||
if (sscanf(utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3) {
|
||||
Syslog(LOG_ERR, "Kernel send bogus release string `%s'.",
|
||||
utsname.release);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute the version code from data sent by the kernel */
|
||||
kvnum = (major << 16) | (minor << 8) | patch;
|
||||
|
||||
/* Failure. */
|
||||
if (vnum != kvnum)
|
||||
return -1;
|
||||
|
||||
/* Success. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: CheckMapVersion
|
||||
*
|
||||
* Purpose: This function is responsible for determining whether or
|
||||
* the system map being loaded matches the version of the
|
||||
* currently running kernel. It uses CheckVersion as
|
||||
* backend.
|
||||
*
|
||||
* Arguments: (char *) fname
|
||||
*
|
||||
* fname:-> A pointer to the string which
|
||||
* references the system map file to
|
||||
* be used.
|
||||
*
|
||||
* Return: int
|
||||
*
|
||||
* -1:-> The currently running kernel version does
|
||||
* not match the version in the given file.
|
||||
*
|
||||
* 0:-> No system map file or no version information.
|
||||
*
|
||||
* 1:-> The executing kernel is of the same version
|
||||
* as the version of the map file.
|
||||
**************************************************************************/
|
||||
static int CheckMapVersion(char *fname)
|
||||
{
|
||||
unsigned long int address;
|
||||
FILE *sym_file;
|
||||
char sym[512];
|
||||
char type;
|
||||
int version;
|
||||
|
||||
if ((sym_file = fopen(fname, "r")) != NULL) {
|
||||
/*
|
||||
* At this point a map file was successfully opened. We
|
||||
* now need to search this file and look for version
|
||||
* information.
|
||||
*/
|
||||
Syslog(LOG_INFO, "Inspecting %s", fname);
|
||||
|
||||
version = 0;
|
||||
while (!feof(sym_file) && (version == 0)) {
|
||||
if (fscanf(sym_file, "%lx %c %511s\n", &address,
|
||||
&type, sym) != 3) {
|
||||
Syslog(LOG_ERR, "Error in symbol table input (#2).");
|
||||
fclose(sym_file);
|
||||
return 0;
|
||||
}
|
||||
if (VERBOSE_DEBUGGING && debugging)
|
||||
fprintf(stderr, "Address: %lx, Type: %c, "
|
||||
"Symbol: %s\n",
|
||||
address, type, sym);
|
||||
|
||||
version = CheckVersion(sym);
|
||||
}
|
||||
fclose(sym_file);
|
||||
|
||||
switch (version) {
|
||||
case -1:
|
||||
Syslog(LOG_ERR, "Symbol table has incorrect "
|
||||
"version number.\n");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (debugging)
|
||||
fprintf(stderr, "No version information "
|
||||
"found.\n");
|
||||
break;
|
||||
case 1:
|
||||
if (debugging)
|
||||
fprintf(stderr, "Found table with "
|
||||
"matching version number.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: AddSymbol
|
||||
*
|
||||
* Purpose: This function is responsible for adding a symbol name
|
||||
* and its address to the symbol table.
|
||||
*
|
||||
* Arguments: (unsigned long) address, (char *) symbol
|
||||
*
|
||||
* Return: int
|
||||
*
|
||||
* A boolean value is assumed. True if the addition is
|
||||
* successful. False if not.
|
||||
**************************************************************************/
|
||||
static int AddSymbol(unsigned long address, char *symbol)
|
||||
{
|
||||
/* Allocate the the symbol table entry. */
|
||||
sym_array = realloc(sym_array, (num_syms + 1) * sizeof(struct sym_table));
|
||||
if (sym_array == NULL)
|
||||
return 0;
|
||||
|
||||
/* Then the space for the symbol. */
|
||||
sym_array[num_syms].name = malloc(strlen(symbol) * sizeof(char) + 1);
|
||||
if (sym_array[num_syms].name == NULL)
|
||||
return 0;
|
||||
|
||||
sym_array[num_syms].value = address;
|
||||
strcpy(sym_array[num_syms].name, symbol);
|
||||
++num_syms;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: LookupSymbol
|
||||
*
|
||||
* Purpose: Find the symbol which is related to the given kernel
|
||||
* address.
|
||||
*
|
||||
* Arguments: (long int) value, (struct symbol *) sym
|
||||
*
|
||||
* value:-> The address to be located.
|
||||
*
|
||||
* sym:-> A pointer to a structure which will be
|
||||
* loaded with the symbol's parameters.
|
||||
*
|
||||
* Return: (char *)
|
||||
*
|
||||
* If a match cannot be found a diagnostic string is printed.
|
||||
* If a match is found the pointer to the symbolic name most
|
||||
* closely matching the address is returned.
|
||||
**************************************************************************/
|
||||
char *LookupSymbol(unsigned long value, struct symbol *sym)
|
||||
{
|
||||
struct symbol ksym, msym;
|
||||
char *last;
|
||||
char *name;
|
||||
int lp;
|
||||
|
||||
if (!sym_array)
|
||||
return NULL;
|
||||
|
||||
last = sym_array[0].name;
|
||||
ksym.offset = 0;
|
||||
ksym.size = 0;
|
||||
if (value < sym_array[0].value)
|
||||
return NULL;
|
||||
|
||||
for (lp = 0; lp <= num_syms; ++lp) {
|
||||
if (sym_array[lp].value > value) {
|
||||
ksym.offset = value - sym_array[lp - 1].value;
|
||||
ksym.size = sym_array[lp].value -
|
||||
sym_array[lp - 1].value;
|
||||
break;
|
||||
}
|
||||
last = sym_array[lp].name;
|
||||
}
|
||||
|
||||
name = LookupModuleSymbol(value, &msym);
|
||||
|
||||
if (ksym.offset == 0 && msym.offset == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ksym.offset == 0 || msym.offset < 0 ||
|
||||
(ksym.offset > 0 && ksym.offset < msym.offset)) {
|
||||
sym->offset = ksym.offset;
|
||||
sym->size = ksym.size;
|
||||
return last;
|
||||
} else {
|
||||
sym->offset = msym.offset;
|
||||
sym->size = msym.size;
|
||||
return name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: FreeSymbols
|
||||
*
|
||||
* Purpose: This function is responsible for freeing all memory which
|
||||
* has been allocated to hold the static symbol table. It
|
||||
* also initializes the symbol count and in general prepares
|
||||
* for a re-read of a static symbol table.
|
||||
*
|
||||
* Arguments: void
|
||||
*
|
||||
* Return: void
|
||||
**************************************************************************/
|
||||
|
||||
static void FreeSymbols(void)
|
||||
{
|
||||
int lp;
|
||||
|
||||
/* Free each piece of memory allocated for symbol names. */
|
||||
for (lp = 0; lp < num_syms; ++lp)
|
||||
free(sym_array[lp].name);
|
||||
|
||||
/* Whack the entire array and initialize everything. */
|
||||
free(sym_array);
|
||||
sym_array = NULL;
|
||||
num_syms = 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: LogExpanded
|
||||
*
|
||||
* Purpose: This function is responsible for logging a kernel message
|
||||
* line after all potential numeric kernel addresses have
|
||||
* been resolved symolically.
|
||||
*
|
||||
* Arguments: (char *) line, (char *) el
|
||||
*
|
||||
* line:-> A pointer to the buffer containing the kernel
|
||||
* message to be expanded and logged.
|
||||
*
|
||||
* el:-> A pointer to the buffer into which the expanded
|
||||
* kernel line will be written.
|
||||
*
|
||||
* Return: void
|
||||
**************************************************************************/
|
||||
|
||||
char *ExpandKadds(char *line, char *el)
|
||||
{
|
||||
unsigned long int value;
|
||||
struct symbol sym;
|
||||
char *symbol;
|
||||
char *elp = el;
|
||||
char *sl = line;
|
||||
char *kp;
|
||||
char num[15];
|
||||
|
||||
sym.offset = 0;
|
||||
sym.size = 0;
|
||||
|
||||
/*
|
||||
* This is as handy a place to put this as anyplace.
|
||||
*
|
||||
* Since the insertion of kernel modules can occur in a somewhat
|
||||
* dynamic fashion we need some mechanism to insure that the
|
||||
* kernel symbol tables get read just prior to when they are
|
||||
* needed.
|
||||
*
|
||||
* To accomplish this we look for the Oops string and use its
|
||||
* presence as a signal to load the module symbols.
|
||||
*
|
||||
* This is not the best solution of course, especially if the
|
||||
* kernel is rapidly going out to lunch. What really needs to
|
||||
* be done is to somehow generate a callback from the
|
||||
* kernel whenever a module is loaded or unloaded. I am
|
||||
* open for patches.
|
||||
*/
|
||||
if (i_am_paranoid &&
|
||||
(strstr(line, "Oops:") != NULL) && !InitMsyms())
|
||||
Syslog(LOG_WARN, "Cannot load kernel module symbols.\n");
|
||||
|
||||
/*
|
||||
* Early return if there do not appear to be any kernel
|
||||
* messages in this line.
|
||||
*/
|
||||
if ((num_syms == 0) ||
|
||||
(kp = strstr(line, "[<")) == NULL) {
|
||||
strcpy(el, line);
|
||||
return el;
|
||||
}
|
||||
|
||||
/* Loop through and expand all kernel messages. */
|
||||
do {
|
||||
while (sl < kp + 1)
|
||||
*elp++ = *sl++;
|
||||
|
||||
/* Now poised at a kernel delimiter. */
|
||||
if ((kp = strstr(sl, ">]")) == NULL) {
|
||||
strcpy(el, sl);
|
||||
return el;
|
||||
}
|
||||
|
||||
strncpy(num, sl + 1, kp - sl - 1);
|
||||
num[kp - sl - 1] = '\0';
|
||||
value = strtoul(num, NULL, 16);
|
||||
if ((symbol = LookupSymbol(value, &sym)) == NULL)
|
||||
symbol = sl;
|
||||
|
||||
strcat(elp, symbol);
|
||||
elp += strlen(symbol);
|
||||
if (debugging)
|
||||
fprintf(stderr, "Symbol: %s = %lx = %s, %x/%d\n",
|
||||
sl + 1, value,
|
||||
(sym.size == 0) ? symbol + 1 : symbol,
|
||||
sym.offset, sym.size);
|
||||
|
||||
value = 2;
|
||||
if (sym.size != 0) {
|
||||
--value;
|
||||
++kp;
|
||||
elp += sprintf(elp, "+0x%x/0x%02x", sym.offset, sym.size);
|
||||
}
|
||||
strncat(elp, kp, value);
|
||||
elp += value;
|
||||
sl = kp + value;
|
||||
if ((kp = strstr(sl, "[<")) == NULL)
|
||||
strcat(elp, sl);
|
||||
} while (kp != NULL);
|
||||
|
||||
if (debugging)
|
||||
fprintf(stderr, "Expanded line: %s\n", el);
|
||||
return el;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: SetParanoiaLevel
|
||||
*
|
||||
* Purpose: This function is an interface function for setting the
|
||||
* mode of loadable module symbol lookups. Probably overkill
|
||||
* but it does slay another global variable.
|
||||
*
|
||||
* Arguments: (int) level
|
||||
*
|
||||
* level:-> The amount of paranoia which is to be
|
||||
* present when resolving kernel exceptions.
|
||||
* Return: void
|
||||
**************************************************************************/
|
||||
void SetParanoiaLevel(int level)
|
||||
{
|
||||
i_am_paranoid = level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting the -DTEST define enables the following code fragment to
|
||||
* be compiled. This produces a small standalone program which will
|
||||
* echo the standard input of the process to stdout while translating
|
||||
* all numeric kernel addresses into their symbolic equivalent.
|
||||
*/
|
||||
#if defined(TEST)
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char line[1024], eline[2048];
|
||||
|
||||
debugging = 1;
|
||||
|
||||
if (!InitKsyms(NULL)) {
|
||||
fputs("ksym: Error loading system map.\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!feof(stdin)) {
|
||||
fgets(line, sizeof(line), stdin);
|
||||
if (line[strlen(line) - 1] == '\n')
|
||||
line[strlen(line) - 1] = '\0'; /* Trash NL char */
|
||||
memset(eline, 0, sizeof(eline));
|
||||
ExpandKadds(line, eline);
|
||||
fprintf(stdout, "%s\n", eline);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Syslog(int priority, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stdout, "Pr: %d, ", priority);
|
||||
vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
484
src/ksym_mod.c
484
src/ksym_mod.c
@ -1,484 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* ksym_mod.c - functions for building symbol lookup tables for klogd
|
||||
*
|
||||
* Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
|
||||
* Copyright (c) 1996 Enjellic Systems Development
|
||||
* Copyright (c) 1998-2007 Martin Schulze <joey@infodrom.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements functions which are useful for building
|
||||
* a symbol lookup table based on the in kernel symbol table
|
||||
* maintained by the Linux kernel.
|
||||
*
|
||||
* Proper logging of kernel panics generated by loadable modules
|
||||
* tends to be difficult. Since the modules are loaded dynamically
|
||||
* their addresses are not known at kernel load time. A general
|
||||
* protection fault (Oops) cannot be properly deciphered with
|
||||
* classic methods using the static symbol map produced at link time.
|
||||
*
|
||||
* One solution to this problem is to have klogd attempt to translate
|
||||
* addresses from module when the fault occurs. By referencing the
|
||||
* the kernel symbol table proper resolution of these symbols is made
|
||||
* possible.
|
||||
*
|
||||
* At least that is the plan.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "module.h"
|
||||
#include <linux/version.h>
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "klogd.h"
|
||||
#include "ksyms.h"
|
||||
|
||||
#define KSYMS "/proc/kallsyms"
|
||||
|
||||
static int num_modules = 0;
|
||||
struct Module *sym_array_modules = NULL;
|
||||
|
||||
static int have_modules = 0;
|
||||
|
||||
#if defined(TEST)
|
||||
static int debugging = 1;
|
||||
#else
|
||||
extern int debugging;
|
||||
#endif
|
||||
|
||||
/* Function prototypes. */
|
||||
static void FreeModules(void);
|
||||
static int AddSymbol(const char *);
|
||||
struct Module *AddModule(const char *);
|
||||
static int symsort(const void *, const void *);
|
||||
|
||||
/* Imported from ksym.c */
|
||||
extern int num_syms;
|
||||
|
||||
/**************************************************************************
|
||||
* Function: InitMsyms
|
||||
*
|
||||
* Purpose: This function is responsible for building a symbol
|
||||
* table which can be used to resolve addresses for
|
||||
* loadable modules.
|
||||
*
|
||||
* Arguments: Void
|
||||
*
|
||||
* Return: A boolean return value is assumed.
|
||||
*
|
||||
* A false value indicates that something went wrong.
|
||||
*
|
||||
* True if loading is successful.
|
||||
**************************************************************************/
|
||||
|
||||
extern int InitMsyms(void)
|
||||
{
|
||||
FILE *ksyms;
|
||||
char *p;
|
||||
char buf[128];
|
||||
int rtn;
|
||||
int tmp;
|
||||
|
||||
/* Initialize the kernel module symbol table. */
|
||||
FreeModules();
|
||||
|
||||
ksyms = fopen(KSYMS, "r");
|
||||
|
||||
if (ksyms == NULL) {
|
||||
if (errno == ENOENT)
|
||||
Syslog(LOG_INFO, "No module symbols loaded - "
|
||||
"kernel modules not enabled.\n");
|
||||
else
|
||||
Syslog(LOG_ERR, "Error loading kernel symbols "
|
||||
"- %s\n",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debugging)
|
||||
fprintf(stderr, "Loading kernel module symbols - "
|
||||
"Source: %s\n",
|
||||
KSYMS);
|
||||
|
||||
while (fgets(buf, sizeof(buf), ksyms) != NULL) {
|
||||
if (num_syms > 0 && index(buf, '[') == NULL)
|
||||
continue;
|
||||
|
||||
p = index(buf, ' ');
|
||||
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
if (buf[strlen(buf) - 1] == '\n')
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
/* overlong lines will be ignored above */
|
||||
|
||||
AddSymbol(buf);
|
||||
}
|
||||
|
||||
fclose(ksyms);
|
||||
|
||||
have_modules = 1;
|
||||
|
||||
/* Sort the symbol tables in each module. */
|
||||
for (rtn = tmp = 0; tmp < num_modules; ++tmp) {
|
||||
rtn += sym_array_modules[tmp].num_syms;
|
||||
if (sym_array_modules[tmp].num_syms < 2)
|
||||
continue;
|
||||
qsort(sym_array_modules[tmp].sym_array,
|
||||
sym_array_modules[tmp].num_syms,
|
||||
sizeof(struct sym_table), symsort);
|
||||
}
|
||||
|
||||
if (rtn == 0)
|
||||
Syslog(LOG_INFO, "No module symbols loaded.");
|
||||
else
|
||||
Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn,
|
||||
(rtn == 1) ? "symbol" : "symbols",
|
||||
num_modules, (num_modules == 1) ? "." : "s.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int symsort(const void *p1, const void *p2)
|
||||
{
|
||||
const struct sym_table *sym1 = p1,
|
||||
*sym2 = p2;
|
||||
|
||||
if (sym1->value < sym2->value)
|
||||
return -1;
|
||||
|
||||
if (sym1->value == sym2->value)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: FreeModules
|
||||
*
|
||||
* Purpose: This function is used to free all memory which has been
|
||||
* allocated for the modules and their symbols.
|
||||
*
|
||||
* Arguments: None specified.
|
||||
*
|
||||
* Return: void
|
||||
**************************************************************************/
|
||||
static void FreeModules(void)
|
||||
{
|
||||
struct Module *mp;
|
||||
int nmods;
|
||||
int nsyms;
|
||||
|
||||
/* Check to see if the module symbol tables need to be cleared. */
|
||||
have_modules = 0;
|
||||
if (num_modules == 0)
|
||||
return;
|
||||
|
||||
if (sym_array_modules == NULL)
|
||||
return;
|
||||
|
||||
for (nmods = 0; nmods < num_modules; ++nmods) {
|
||||
mp = &sym_array_modules[nmods];
|
||||
if (mp->num_syms == 0)
|
||||
continue;
|
||||
|
||||
for (nsyms = 0; nsyms < mp->num_syms; ++nsyms)
|
||||
free(mp->sym_array[nsyms].name);
|
||||
free(mp->sym_array);
|
||||
if (mp->name != NULL)
|
||||
free(mp->name);
|
||||
}
|
||||
|
||||
free(sym_array_modules);
|
||||
sym_array_modules = NULL;
|
||||
num_modules = 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: AddModule
|
||||
*
|
||||
* Purpose: This function is responsible for adding a module to
|
||||
* the list of currently loaded modules.
|
||||
*
|
||||
* Arguments: (const char *) module
|
||||
*
|
||||
* module:-> The name of the module.
|
||||
*
|
||||
* Return: struct Module *
|
||||
**************************************************************************/
|
||||
|
||||
struct Module *AddModule(const char *module)
|
||||
{
|
||||
struct Module *mp;
|
||||
|
||||
if (num_modules == 0) {
|
||||
sym_array_modules = (struct Module *)malloc(sizeof(struct Module));
|
||||
if (sym_array_modules == NULL) {
|
||||
Syslog(LOG_WARN, "Cannot allocate Module array.\n");
|
||||
return NULL;
|
||||
}
|
||||
mp = sym_array_modules;
|
||||
} else {
|
||||
/* Allocate space for the module. */
|
||||
mp = realloc(sym_array_modules, (num_modules + 1) * sizeof(struct Module));
|
||||
if (mp == NULL) {
|
||||
Syslog(LOG_WARN, "Cannot allocate Module array.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sym_array_modules = mp;
|
||||
mp = &sym_array_modules[num_modules];
|
||||
}
|
||||
|
||||
num_modules++;
|
||||
mp->sym_array = NULL;
|
||||
mp->num_syms = 0;
|
||||
|
||||
if (module != NULL)
|
||||
mp->name = strdup(module);
|
||||
else
|
||||
mp->name = NULL;
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: AddSymbol
|
||||
*
|
||||
* Purpose: This function is responsible for adding a symbol name
|
||||
* and its address to the symbol table.
|
||||
*
|
||||
* Arguments: (struct Module *) mp, (unsigned long) address, (char *) symbol
|
||||
*
|
||||
* mp:-> A pointer to the module which the symbol is
|
||||
* to be added to.
|
||||
*
|
||||
* address:-> The address of the symbol.
|
||||
*
|
||||
* symbol:-> The name of the symbol.
|
||||
*
|
||||
* Return: int
|
||||
*
|
||||
* A boolean value is assumed. True if the addition is
|
||||
* successful. False if not.
|
||||
**************************************************************************/
|
||||
static int AddSymbol(const char *line)
|
||||
{
|
||||
static char *lastmodule = NULL;
|
||||
struct Module *mp;
|
||||
unsigned long address;
|
||||
char *module;
|
||||
char *p;
|
||||
|
||||
module = index(line, '[');
|
||||
if (module != NULL) {
|
||||
p = index(module, ']');
|
||||
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
|
||||
p = module++;
|
||||
|
||||
while (isspace(*(--p)))
|
||||
;
|
||||
*(++p) = '\0';
|
||||
}
|
||||
|
||||
p = index(line, ' ');
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
*p = '\0';
|
||||
|
||||
address = strtoul(line, NULL, 16);
|
||||
|
||||
p += 3;
|
||||
|
||||
if (num_modules == 0 ||
|
||||
(lastmodule == NULL && module != NULL) ||
|
||||
(module == NULL && lastmodule != NULL) ||
|
||||
(module != NULL && strcmp(module, lastmodule))) {
|
||||
mp = AddModule(module);
|
||||
|
||||
if (mp == NULL)
|
||||
return 0;
|
||||
} else
|
||||
mp = &sym_array_modules[num_modules - 1];
|
||||
|
||||
lastmodule = mp->name;
|
||||
|
||||
/* Allocate space for the symbol table entry. */
|
||||
mp->sym_array = (struct sym_table *)realloc(mp->sym_array,
|
||||
(mp->num_syms + 1) * sizeof(struct sym_table));
|
||||
|
||||
if (mp->sym_array == NULL)
|
||||
return 0;
|
||||
|
||||
mp->sym_array[mp->num_syms].name = strdup(p);
|
||||
if (mp->sym_array[mp->num_syms].name == NULL)
|
||||
return 0;
|
||||
|
||||
/* Stuff interesting information into the module. */
|
||||
mp->sym_array[mp->num_syms].value = address;
|
||||
++mp->num_syms;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Function: LookupModuleSymbol
|
||||
*
|
||||
* Purpose: Find the symbol which is related to the given address from
|
||||
* a kernel module.
|
||||
*
|
||||
* Arguments: (long int) value, (struct symbol *) sym
|
||||
*
|
||||
* value:-> The address to be located.
|
||||
*
|
||||
* sym:-> A pointer to a structure which will be
|
||||
* loaded with the symbol's parameters.
|
||||
*
|
||||
* Return: (char *)
|
||||
*
|
||||
* If a match cannot be found a diagnostic string is printed.
|
||||
* If a match is found the pointer to the symbolic name most
|
||||
* closely matching the address is returned.
|
||||
**************************************************************************/
|
||||
char *LookupModuleSymbol(unsigned long value, struct symbol *sym)
|
||||
{
|
||||
static char ret[100];
|
||||
struct sym_table *last;
|
||||
struct Module *mp;
|
||||
int nmod;
|
||||
int nsym;
|
||||
|
||||
sym->size = 0;
|
||||
sym->offset = 0;
|
||||
if (num_modules == 0)
|
||||
return NULL;
|
||||
|
||||
for (nmod = 0; nmod < num_modules; ++nmod) {
|
||||
mp = &sym_array_modules[nmod];
|
||||
|
||||
/*
|
||||
* Run through the list of symbols in this module and
|
||||
* see if the address can be resolved.
|
||||
*/
|
||||
for (nsym = 1, last = &mp->sym_array[0];
|
||||
nsym < mp->num_syms;
|
||||
++nsym) {
|
||||
if (mp->sym_array[nsym].value > value) {
|
||||
if (sym->size == 0 ||
|
||||
(value - last->value) < (unsigned long)sym->offset ||
|
||||
(((unsigned long)sym->offset == (value - last->value)) &&
|
||||
(mp->sym_array[nsym].value - last->value) < (unsigned long)sym->size)) {
|
||||
sym->offset = value - last->value;
|
||||
sym->size = mp->sym_array[nsym].value -
|
||||
last->value;
|
||||
ret[sizeof(ret) - 1] = '\0';
|
||||
if (mp->name == NULL)
|
||||
snprintf(ret, sizeof(ret) - 1,
|
||||
"%s", last->name);
|
||||
else
|
||||
snprintf(ret, sizeof(ret) - 1,
|
||||
"%s:%s", mp->name, last->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
last = &mp->sym_array[nsym];
|
||||
}
|
||||
}
|
||||
|
||||
if (sym->size > 0)
|
||||
return ret;
|
||||
|
||||
/* It has been a hopeless exercise. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting the -DTEST define enables the following code fragment to
|
||||
* be compiled. This produces a small standalone program which will
|
||||
* dump the current kernel symbol table.
|
||||
*/
|
||||
#if defined(TEST)
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int lp, syms;
|
||||
|
||||
if (!InitMsyms()) {
|
||||
fprintf(stderr, "Cannot load module symbols.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Number of modules: %d\n\n", num_modules);
|
||||
|
||||
for (lp = 0; lp < num_modules; ++lp) {
|
||||
printf("Module #%d = %s, Number of symbols = %d\n", lp + 1,
|
||||
sym_array_modules[lp].name == NULL
|
||||
? "kernel space"
|
||||
: sym_array_modules[lp].name,
|
||||
sym_array_modules[lp].num_syms);
|
||||
|
||||
for (syms = 0; syms < sym_array_modules[lp].num_syms; ++syms) {
|
||||
printf("\tSymbol #%d\n", syms + 1);
|
||||
printf("\tName: %s\n",
|
||||
sym_array_modules[lp].sym_array[syms].name);
|
||||
printf("\tAddress: %lx\n\n",
|
||||
sym_array_modules[lp].sym_array[syms].value);
|
||||
}
|
||||
}
|
||||
|
||||
FreeModules();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Syslog(int priority, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stdout, "Pr: %d, ", priority);
|
||||
vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
36
src/ksyms.h
36
src/ksyms.h
@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* ksym.h - Definitions for symbol table utilities.
|
||||
*
|
||||
* Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
|
||||
* Copyright (c) 1996 Enjellic Systems Development
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SYSKLOGD_KSYMS_H_
|
||||
#define SYSKLOGD_KSYMS_H_
|
||||
|
||||
struct symbol {
|
||||
char *name;
|
||||
int size;
|
||||
int offset;
|
||||
};
|
||||
|
||||
extern char *LookupSymbol(unsigned long, struct symbol *);
|
||||
extern char *LookupModuleSymbol(unsigned long int, struct symbol *);
|
||||
|
||||
#endif /* SYSKLOGD_KSYMS_H_ */
|
39
src/module.h
39
src/module.h
@ -1,39 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* module.h - Miscellaneous module definitions
|
||||
*
|
||||
* Copyright (c) 1996 Richard Henderson <rth@tamu.edu>
|
||||
* Copyright (c) 2004-7 Martin Schulze <joey@infodrom.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef SYSKLOGD_MODULE_H_
|
||||
#define SYSKLOGD_MODULE_H_
|
||||
|
||||
struct sym_table {
|
||||
unsigned long value;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct Module {
|
||||
struct sym_table *sym_array;
|
||||
int num_syms;
|
||||
|
||||
char *name;
|
||||
};
|
||||
|
||||
#endif /* SYSKLOGD_MODULE_H_ */
|
@ -1,65 +0,0 @@
|
||||
diff -u --new-file --recursive base/modules-2.0.0/depmod/modprobe.c ./modules-2.0.0/depmod/modprobe.c
|
||||
--- base/modules-2.0.0/depmod/modprobe.c Mon Jun 10 05:29:08 1996
|
||||
+++ ./modules-2.0.0/depmod/modprobe.c Thu Aug 29 09:58:01 1996
|
||||
@@ -233,6 +233,13 @@
|
||||
verbose ("\r\t%s\n\t\t",cmd);
|
||||
int ret = system(cmd);
|
||||
#endif
|
||||
+ if ( fork() == 0 )
|
||||
+ {
|
||||
+ /* Child process. */
|
||||
+ if ( execlp("klogd", "klogd", "-i", (char *) 0) < 0 )
|
||||
+ fprintf(stderr, "Failure in signaling klogd.\n");
|
||||
+ exit(0);
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
diff -u --new-file --recursive base/modules-2.0.0/insmod/insmod.c ./modules-2.0.0/insmod/insmod.c
|
||||
--- base/modules-2.0.0/insmod/insmod.c Mon Jun 10 06:42:25 1996
|
||||
+++ ./modules-2.0.0/insmod/insmod.c Thu Aug 29 09:56:53 1996
|
||||
@@ -253,6 +253,18 @@
|
||||
++n_stringpatches;
|
||||
}
|
||||
|
||||
+
|
||||
+void signal_klogd() {
|
||||
+ if ( fork() == 0 )
|
||||
+ {
|
||||
+ if ( execlp("klogd", "klogd", "-i", (char *) 0) < 0 )
|
||||
+ fprintf(stderr, "Failure in signaling klogd.\n");
|
||||
+ exit(0);
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -983,6 +995,8 @@
|
||||
symvalue(sp) + addr, symtype, symname(sp));
|
||||
}
|
||||
|
||||
+ signal_klogd();
|
||||
+
|
||||
if (nksyms > 0)
|
||||
free(ksymtab); /* it has done its job */
|
||||
|
||||
@@ -1292,6 +1306,7 @@
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
+ signal_klogd();
|
||||
return errors;
|
||||
}
|
||||
/* else recursive removal */
|
||||
@@ -1353,6 +1368,8 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ signal_klogd();
|
||||
|
||||
return errors;
|
||||
}
|
258
src/oops.c
258
src/oops.c
@ -1,258 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* oops.c - Dummy loadable module for testing klogd.
|
||||
*
|
||||
* Copyright (c) 2007 Martin Schulze <joey@infodrom.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Helpful documentation: http://www.tldp.org/LDP/lkmpg/2.6/html/
|
||||
*
|
||||
* SYNOPSIS
|
||||
*
|
||||
* echo TEXT > /proc/oops Emits TEXT via printk at log level
|
||||
* [<address+delta>] triggers klogd address decoding
|
||||
* echo level: info > /proc/oops Sets the log level to 'info'
|
||||
* echo oops > /proc/oops Creates a real oops, kills executing shell
|
||||
* cat /proc/oops Display current log level and last oops time
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#define MODNAME "oops"
|
||||
#define PROCNAME "oops"
|
||||
|
||||
MODULE_AUTHOR("Martin Schulze <joey@infodrom.org>");
|
||||
MODULE_DESCRIPTION("Oops module from klogd");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static DEFINE_MUTEX(oops_lock);
|
||||
|
||||
struct oops_t {
|
||||
unsigned long lastoops;
|
||||
int loglevel;
|
||||
};
|
||||
static struct oops_t oops_data;
|
||||
|
||||
static int procflag = 0;
|
||||
|
||||
struct code {
|
||||
char *name;
|
||||
int level;
|
||||
};
|
||||
|
||||
struct code priorities[] = {
|
||||
{ "emerg", 0 },
|
||||
{ "panic", 0 }, /* DEPRECATED */
|
||||
{ "alert", 1 },
|
||||
{ "crit", 2 },
|
||||
{ "err", 3 },
|
||||
{ "error", 3 }, /* DEPRECATED */
|
||||
{ "warning", 4 },
|
||||
{ "warn", 4 }, /* DEPRECATED */
|
||||
{ "notice", 5 },
|
||||
{ "info", 6 },
|
||||
{ "debug", 7 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
void oops_decode_level(char *line)
|
||||
{
|
||||
struct code *prio;
|
||||
char *p;
|
||||
|
||||
if (strncmp(line, "level:", 6))
|
||||
return;
|
||||
|
||||
for (p = (char *)(line) + 6; *p == ' ' || *p == '\t'; p++)
|
||||
;
|
||||
|
||||
for (prio = priorities; prio->name; prio++)
|
||||
if (!strcmp(p, prio->name)) {
|
||||
oops_data.loglevel = prio->level;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine will create a real and ugly oops
|
||||
*/
|
||||
static void oops(void)
|
||||
{
|
||||
unsigned long *p = (unsigned long *)828282828;
|
||||
*p = 5;
|
||||
}
|
||||
|
||||
static int oops_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "oops_proc_open().\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
oops_proc_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
struct code *prio;
|
||||
char *level = NULL;
|
||||
char s[70];
|
||||
int size;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "oops_proc_read(%d).\n", nbytes);
|
||||
#endif
|
||||
|
||||
if (procflag) {
|
||||
procflag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (prio = priorities;
|
||||
prio->name && prio->level != oops_data.loglevel;
|
||||
prio++)
|
||||
;
|
||||
level = prio->name;
|
||||
|
||||
if (oops_data.lastoops == 0)
|
||||
size = sprintf(s, "Log level: %s\nLast oops: none\n", level);
|
||||
else {
|
||||
unsigned long now = get_seconds();
|
||||
unsigned long delta = now - oops_data.lastoops;
|
||||
size = sprintf(s, "Log level: %s\nLast oops: %lu (%lu second%s ago)\n",
|
||||
level, oops_data.lastoops,
|
||||
delta, delta == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
if (size < nbytes)
|
||||
nbytes = size;
|
||||
|
||||
if (copy_to_user(buf, s, nbytes))
|
||||
return -EFAULT;
|
||||
|
||||
*ppos += nbytes;
|
||||
|
||||
procflag++;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int
|
||||
oops_proc_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "oops_proc_release().\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
oops_proc_write(struct file *file, const char __user *buf,
|
||||
size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
char input[100];
|
||||
int len;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "oops_proc_write(%d).\n", nbytes);
|
||||
#endif
|
||||
|
||||
len = nbytes >= sizeof(input) ? sizeof(input) - 1 : nbytes;
|
||||
|
||||
if (copy_from_user(input, buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
input[len] = '\0';
|
||||
if (input[len - 1] == '\n')
|
||||
input[len - 1] = '\0';
|
||||
|
||||
if (!strncmp(input, "level:", 6))
|
||||
oops_decode_level(input);
|
||||
else if (!strcmp(input, "oops")) {
|
||||
oops_data.lastoops = get_seconds();
|
||||
oops();
|
||||
} else
|
||||
printk("<%d>%s\n", oops_data.loglevel, input);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static const struct file_operations oops_proc_operations = {
|
||||
.read = oops_proc_read,
|
||||
.release = oops_proc_release,
|
||||
.write = oops_proc_write,
|
||||
.open = oops_proc_open,
|
||||
};
|
||||
|
||||
void oops_proc_add(void)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
mutex_lock(&oops_lock);
|
||||
|
||||
entry = create_proc_entry(PROCNAME, 0, NULL);
|
||||
|
||||
if (entry) {
|
||||
entry->proc_fops = &oops_proc_operations;
|
||||
}
|
||||
|
||||
mutex_unlock(&oops_lock);
|
||||
}
|
||||
|
||||
void oops_proc_remove(void)
|
||||
{
|
||||
mutex_lock(&oops_lock);
|
||||
|
||||
remove_proc_entry(PROCNAME, NULL);
|
||||
|
||||
mutex_unlock(&oops_lock);
|
||||
}
|
||||
|
||||
int oops_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Loading module " MODNAME ".\n");
|
||||
|
||||
oops_data.lastoops = 0;
|
||||
oops_data.loglevel = 5;
|
||||
|
||||
oops_proc_add();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oops_cleanup(void)
|
||||
{
|
||||
oops_proc_remove();
|
||||
|
||||
printk(KERN_INFO "Removing module " MODNAME ".\n");
|
||||
}
|
||||
|
||||
module_init(oops_init);
|
||||
module_exit(oops_cleanup);
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -153,10 +153,8 @@ static SIMPLEQ_HEAD(, allowedpeer) aphead = SIMPLEQ_HEAD_INITIALIZER(aphead);
|
||||
static int allowaddr(char *s);
|
||||
void untty(void);
|
||||
static void parsemsg(const char *from, char *msg);
|
||||
#ifndef KLOGD
|
||||
static int opensys(const char *file);
|
||||
static void printsys(char *msg);
|
||||
#endif
|
||||
static void logmsg(struct buf_msg *buffer);
|
||||
static void fprintlog_first(struct filed *f, struct buf_msg *buffer);
|
||||
static void fprintlog_successive(struct filed *f, int flags);
|
||||
@ -255,15 +253,6 @@ int main(int argc, char *argv[])
|
||||
int pflag = 0, bflag = 0;
|
||||
int ch;
|
||||
|
||||
#ifdef KLOGD
|
||||
/*
|
||||
* When building with klogd enabled this works around filtering
|
||||
* of LOG_KERN messages in parsemsg(). Otherwise it needs to be
|
||||
* actively enabled to allow logging of remote kernel messages.
|
||||
*/
|
||||
KeepKernFac = 1;
|
||||
#endif
|
||||
|
||||
while ((ch = getopt(argc, argv, "46Aa:b:dHFf:km:nP:p:r:sTv?")) != EOF) {
|
||||
switch ((char)ch) {
|
||||
case '4':
|
||||
@ -381,13 +370,11 @@ int main(int argc, char *argv[])
|
||||
.pe_mode = 0666,
|
||||
});
|
||||
|
||||
#ifndef KLOGD
|
||||
/* Attempt to open kernel log pipe */
|
||||
if (opensys(_PATH_KLOG))
|
||||
warn("Kernel logging disabled, failed opening %s", _PATH_KLOG);
|
||||
else
|
||||
kern_console_off();
|
||||
#endif
|
||||
|
||||
if (!Foreground) {
|
||||
chdir("/");
|
||||
@ -480,7 +467,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KLOGD
|
||||
/*
|
||||
* Read /dev/klog while data are available, split into lines.
|
||||
*/
|
||||
@ -533,7 +519,6 @@ static int opensys(const char *file)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void unix_cb(int sd, void *arg)
|
||||
{
|
||||
@ -2018,9 +2003,7 @@ void die(int signo)
|
||||
free(pe);
|
||||
}
|
||||
|
||||
#ifndef KLOGD
|
||||
kern_console_on();
|
||||
#endif
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#include <netdb.h> /* struct addrinfo */
|
||||
#ifdef __linux__
|
||||
#include <sys/klog.h> /* When building w/o klogd */
|
||||
#include <sys/klog.h>
|
||||
#endif
|
||||
#include <sys/param.h> /* MAXHOSTNAMELEN */
|
||||
#include <sys/socket.h>
|
||||
@ -147,11 +147,8 @@
|
||||
(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
|
||||
|
||||
/*
|
||||
* When building without klogd on Linux systems we use these klogctl(2)
|
||||
* commands to control kernel log messages to console.
|
||||
* klogctl(2) commands on Linux to control kernel logging to console.
|
||||
*/
|
||||
#define SYSLOG_ACTION_CLOSE 0
|
||||
#define SYSLOG_ACTION_OPEN 1
|
||||
#define SYSLOG_ACTION_CONSOLE_OFF 6
|
||||
#define SYSLOG_ACTION_CONSOLE_ON 7
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user