diff --git a/.gitignore b/.gitignore index d362713..b87b711 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,6 @@ config.sub configure depcomp install-sh -klogd.service libtool ltmain.sh missing diff --git a/Makefile.am b/Makefile.am index 7e2b854..a3205be 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 # diff --git a/configure.ac b/configure.ac index a35f029..f521903 100644 --- a/configure.ac +++ b/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 < -.\" Copyright 2018-2019 Joachim Nilsson -.\" -.\" 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 , Greg Wettstein -made major improvements. Martin Schulze fixed some -bugs and took over maintenance. Later -.An Joachim Nilsson Aq Mt troglobit@gmail.com -picked up maintenance at GitHub. diff --git a/man/syslog.conf.5 b/man/syslog.conf.5 index 30bbb16..1411ade 100644 --- a/man/syslog.conf.5 +++ b/man/syslog.conf.5 @@ -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 . diff --git a/man/syslogd.8 b/man/syslogd.8 index 30169d4..8c67fc7 100644 --- a/man/syslogd.8 +++ b/man/syslogd.8 @@ -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 , diff --git a/src/.gitignore b/src/.gitignore index e6d3441..cb28dd0 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,11 +1,8 @@ *.o *.lo .libs/* -klogd logger syslogd -syslog_tst -tsyslogd libcompat.la libsyslog.la libsyslog.pc diff --git a/src/Makefile.am b/src/Makefile.am index bbbfd8a..d7b07d0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/klogd.c b/src/klogd.c deleted file mode 100644 index ead591d..0000000 --- a/src/klogd.c +++ /dev/null @@ -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 - * - * 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 -#include -#include -#include -#include -#include "klogd.h" -#include "ksyms.h" -#include -#include -#include -#include - -#define __LIBRARY__ -#include -#include -#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 : "[]", - * 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: - */ diff --git a/src/klogd.h b/src/klogd.h deleted file mode 100644 index f6a7b08..0000000 --- a/src/klogd.h +++ /dev/null @@ -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 - * - * 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 -#include -#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_ */ diff --git a/src/ksym.c b/src/ksym.c deleted file mode 100644 index c4284be..0000000 --- a/src/ksym.c +++ /dev/null @@ -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 - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 1997-2007 Martin Schulze - * - * 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 -#include -#include - -#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 - -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: - */ diff --git a/src/ksym_mod.c b/src/ksym_mod.c deleted file mode 100644 index cc052c2..0000000 --- a/src/ksym_mod.c +++ /dev/null @@ -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 - * Copyright (c) 1996 Enjellic Systems Development - * Copyright (c) 1998-2007 Martin Schulze - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "module.h" -#include -#include -#include -#include - -#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 - -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: - */ diff --git a/src/ksyms.h b/src/ksyms.h deleted file mode 100644 index 6157ad6..0000000 --- a/src/ksyms.h +++ /dev/null @@ -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 - * 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_ */ diff --git a/src/module.h b/src/module.h deleted file mode 100644 index 11b23a3..0000000 --- a/src/module.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * SPDX-License-Identifier: GPL-2.0-or-later - * - * module.h - Miscellaneous module definitions - * - * Copyright (c) 1996 Richard Henderson - * Copyright (c) 2004-7 Martin Schulze - * - * 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_ */ diff --git a/src/modutils.patch b/src/modutils.patch deleted file mode 100644 index 4dff7f3..0000000 --- a/src/modutils.patch +++ /dev/null @@ -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; - } diff --git a/src/oops.c b/src/oops.c deleted file mode 100644 index 313f1db..0000000 --- a/src/oops.c +++ /dev/null @@ -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 - * - * 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 - * [] 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 -#include -#include -#include -#include -#include - -#define MODNAME "oops" -#define PROCNAME "oops" - -MODULE_AUTHOR("Martin Schulze "); -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: - */ diff --git a/src/syslogd.c b/src/syslogd.c index 5a4d56e..ecc3aa4 100644 --- a/src/syslogd.c +++ b/src/syslogd.c @@ -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); } diff --git a/src/syslogd.h b/src/syslogd.h index 4ea0de8..15e7b28 100644 --- a/src/syslogd.h +++ b/src/syslogd.h @@ -36,7 +36,7 @@ #include /* struct addrinfo */ #ifdef __linux__ -#include /* When building w/o klogd */ +#include #endif #include /* MAXHOSTNAMELEN */ #include @@ -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