我的Linux发行版是RHEL7,内核版本是3.10.0。
从minimum_console_loglevel文档中,我知道了打印头的定义:
查询printk的当前日志级别:
[root@localhost kernel]# cat /proc/sys/kernel/printk
7 4 1 7修改当前控制台日志级别:
[root@localhost kernel]# echo 0 > /proc/sys/kernel/printk
[root@localhost kernel]# cat /proc/sys/kernel/printk
0 4 1 7根据我的理解,minimum_console_loglevel是1,因此将console_loglevel修改为0应该失败。但从猫的输出来看,它似乎是成功的。
来自printk.c代码:
case SYSLOG_ACTION_CONSOLE_LEVEL:
error = -EINVAL;
if (len < 1 || len > 8)
goto out;
if (len < minimum_console_loglevel)
len = minimum_console_loglevel;
console_loglevel = len;
/* Implicitly re-enable logging to console */
saved_console_loglevel = -1;
error = 0;
break;我还认为不应该修改console_loglevel值。
发布于 2015-07-10 05:34:27
你看错代码了。/proc/sys/kernel/printk由kernel/sysctl.c提供。printk 看起来像这样的定义
{
.procname = "printk",
.data = &console_loglevel,
.maxlen = 4*sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},这定义了一个名为printk的文件,它控制一个由4个元素组成的int数组。关键的是,处理程序函数proc_dointvec是一个对整数数组进行操作的泛型函数,它不验证其参数。
因此,作为根用户,您可以编写任何想要/proc/sys/kernel/printk的垃圾数字,内核将很高兴地接受它们。演示:
root@ubuntu:/proc/sys/kernel# echo '-989897 42 -2147483648 0' > printk
root@ubuntu:/proc/sys/kernel# cat printk
-989897 42 -18446744071562067968 0(第三个实际上是我刚刚发现的一个有趣且可能无害的虫子.)
从printk.h中可以看到,四个日志级参数直接从这个四元素数组派生出来:
extern int console_printk[];
#define console_loglevel (console_printk[0])
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])那么,那么,您发布的代码是做什么的呢?它实现了syslog syscall,正如函数的名称(do_syslog)所指出的。正如手册页所指出的
SYSLOG_ACTION_CONSOLE_LEVEL (8)
The call sets console_loglevel to the value given in len,
which must be an integer between 1 and 8 (inclusive). The
kernel silently enforces a minimum value of
minimum_console_loglevel for len. See the log level section
for details. The bufp argument is ignored.我们可以看到,syslog系统调用还允许您设置控制台日志级别,但它实际上检查这些值是否有效。让我们用一个简单的测试程序进行测试(注意,glibc调用函数klogctl而不是syslog,因为用户空间syslog函数做了其他事情):
#include <sys/klog.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define SYSLOG_ACTION_CONSOLE_LEVEL 8
int main(int argc, char **argv) {
if(klogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL, atoi(argv[1])) < 0) {
perror("klogctl");
} else {
printf("klogctl succeeded\n");
}
return 0;
}运行它(在将printk重置回7 4 1 7之后):
root@ubuntu:/tmp# ./test 1 ; cat /proc/sys/kernel/printk
klogctl succeeded
1 4 1 7
root@ubuntu:/tmp# ./test 0 ; cat /proc/sys/kernel/printk
klogctl: Invalid argument
1 4 1 7因此您可以看到,syslog (通过klogctl调用)实际上检查了参数的有效性。
https://stackoverflow.com/questions/31310629
复制相似问题