据我了解系统控制变量,kernel.printk
中的第一个值是内核消息必须小于要写入控制台的数量。因此,如果是4
,则只有dmesg
才会显示由此生成的消息:
printk(KERN_INFO "This is a kernel message.");
消息在控制台上显示的唯一时间是KERN_ERR
,KERN_CRIT
,KERN_INFO
或KERN_EMERG
。即使内核模块出现问题,我也希望上面的消息不会出现在我的屏幕上。
我正在尝试的一件事是系统调用拦截。有些人完美无瑕,其他人则没有。但有几次,来自我标记为KERN_INFO
的不成功内核模块的消息阻塞了我的控制台,没有给我足够的时间来卸载消息。搞砸了这些代码行中的某个地方:
…
#define INODE_IS_DEVICE(inode) (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode))
#define INODE_IS_RAW(inode) (imajor(inode) == RAW_MAJOR)
#define INODE_IS_RAW_DEVICE(inode) (INODE_IS_DEVICE(inode) || INODE_IS_RAW(inode))
#define TEST_OPEN_FLAGS(flags) ((flags & O_WRONLY) || (flags & O_RDWR))
…
struct inode *current_inode;
…
struct inode* get_inode_from_pathname(const char pathname) {
struct path path;
kern_path(pathname, LOOKUP_FOLLOW, &path);
return path.dentry->d_inode;
}
asmlinkage int (*real_open)(const char* __user, int, int);
asmlinkage int custom_open(const char* __user file_name, int flags, int mode) {
current_inode = get_inode_from_pathname(file_name);
printk(KERN_INFO "intercepted: open(\"%s\", %X, %X)\n", file_name, flags, mode);
if (INODE_IS_RAW_DEVICE(inode) && TEST_OPEN_FLAGS(flags)) {
printk(KERN_INFO "Intercepted call to write to block device %s.\n", file_name);
}
return real_open(file_name, flags, mode);
}
…
void hack(void) {
make_rw((unsigned_long)sys_call_table);
real_open = (void*)*(sys_call_table + __NR_open);
*(sys_call_table + __NR_open) = (unsigned_long)custom_open;
make_ro((unsigned_long)sys_call_table);
}
void restore(void) {
make_rw((unsigned_long)sys_call_table);
*(sys_call_table + __NR_open) = (unsigned_long)real_open;
make_ro((unsigned_long)sys_call_table);
}
make_rw
和make_ro
的代码与找到here的代码相同。编译此代码没有给我带来任何错误,但加载模块会导致消息被显示在控制台上以及某种类型的崩溃或错误。请注意,当custom_open
中的代码块替换为
printk(KERN_INFO "intercepted: open(\"%s\", %X, %X)\n", file_name, flags, mode);
if (file_name == "/dev/sda" && TEST_OPEN_FLAGS(flags)) {
printk("Intercepted call to write to block device.");
return -EPERM;
}
return real_open(file_name, flags, mode);
一切都按照我想要的方式运作。用custom_open
替换print(KERN_INFO "i_mode of %s: %hu\n", file_name, current_inode->i_mode);
的控制流语句会产生完全相同的问题。
我不确定这里会产生什么错误。任何见解?
答案 0 :(得分:0)
内核变量DEFAULT_MESSAGE_LOGLEVEL决定内核的默认日志级别。要知道它的当前值是什么,请检查内核配置文件中CONFIG_DEFAULT_MESSAGE_LOGLEVEL的值。
这将为您提供KERN_INFO来到终端的原因。
答案 1 :(得分:0)
注意,当替换
custom_open
内的代码块时 与printk(KERN_INFO "intercepted: open(\"%s\", %X, %X)\n", file_name, flags, mode); if (file_name == "/dev/sda" && TEST_OPEN_FLAGS(flags)) { printk("Intercepted call to write to block device."); return -EPERM; } return real_open(file_name, flags, mode);
一切都按我想要的方式运作。
你错了。您没有看到上述代码的输出并不意味着printk
没有输出到控制台;很可能printk
永远不会执行,因为函数参数file_name
很可能不会指向字符串文字"/dev/sda"
的内存位置 - 请记住,比较字符串,strcmp
将被使用。