标签: kernel-module

如何在C/C++程序中加载内核模块

我正在使用 ds18b20 温度传感器,并且正在将一些 python 代码转换为 C++,以帮助更好地学习该语言。我遇到了一个问题,我需要加载 w1-gpio 和 w1-therm 模块。我在堆栈溢出上发现了很多内容,提到应该使用 init_module ,并且在同一个线程中,其他人提到要使用fork()side exec()。经过大量谷歌搜索和阅读手册页后,我找不到任何有关如何完成这些任务的示例。有人可以指出和/或举例说明如何使用这两种方法加载这两个模块吗?或者提供不涉及 system("modprobe w1-gpio") 的替代方案?

uname -a
Run Code Online (Sandbox Code Playgroud)

产生:

Linux raspberrypi 4.1.13-v7+ #826 SMP PREEMPT Fri Nov 13 20:19:03 GMT 2015 armv7l GNU/Linux
Run Code Online (Sandbox Code Playgroud)

c c++ python kernel-module raspberry-pi

2
推荐指数
1
解决办法
3420
查看次数

Linux 内核模块 - 创建目录

我在 Linux 内核模块中创建目录时遇到问题。

我想要的:在内核模块中创建一个目录。

这是我的实际代码:

struct file *fp = (struct file *) NULL;
fp = filp_open("/home/testdir", O_DIRECTORY|O_CREAT, S_IRUSR);
Run Code Online (Sandbox Code Playgroud)

但它创建一个文件而不是目录。

我尝试使用与上面相同的代码而不使用标志“O_DIRECTORY”:

struct file *fp = (struct file *) NULL;
fp = filp_open("/home/testdir", O_CREAT, S_IRUSR);
Run Code Online (Sandbox Code Playgroud)

并且结果与之前的结果类似。

我不明白这种行为。我究竟做错了什么?

编辑 1:我正在 Raspberry PI、Raspbian 上编码,内核版本:4.4.43-v7

c linux kernel-module linux-kernel

2
推荐指数
1
解决办法
3433
查看次数

为什么 cat 调用 read() 两次就足够了?

我是 Linux 内核模块的新手。我正在根据网络课程学习字符驱动程序模块。我有一个非常简单的模块来创建/dev/chardevexample,我有一个问题需要了解:

当我这样做时echo "hello4" > /dev/chardevexample,我会write按预期看到执行一次。但是,当我这样做时cat /dev/chardevexample,我看到读取执行了两次

我在我的代码和课程材料中都看到了这一点。第一次返回了所有数据read(),为什么还要cat再次调用呢?

到目前为止我所做的所有事情如下:

  1. insmod chardev.ko加载我的模块
  2. echo "hello4" > /dev/chardevexample。这是写入,我在 dmesg 中看到它只发生一次
  3. cat /dev/chardevexample。这是读取的内容,并且dmesg显示它发生了两次。
  4. 我做到了strace cat /dev/chardevexample,而且我确实看到函数调用被调用两次以进行读取。中间也有写

    read(3, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 4096
    write(1, "hello4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,    4096hello4) = 4096
    read(3, "", 131072)
    
    Run Code Online (Sandbox Code Playgroud)
  5. dmesg读取后(cat 命令)

    [909836.517402] DEBUG-device_read: To User  hello4 and bytes_to_do 4096 ppos 0 # Read #1 
    [909836.517428] DEBUG-device_read: Data send to app hello4, …
    Run Code Online (Sandbox Code Playgroud)

linux kernel kernel-module chardev

2
推荐指数
1
解决办法
1400
查看次数

制作驱动程序时禁用 KBUILD_CFLAGS 选项

我正在尝试从芯片实验室编译这个 UART -> USB驱动程序。它只在 Ubuntu 版本上进行了测试18.04 (Bionic),我的机器运行在21.10 (Impish). 显然,差异之一是最新版本在构建内核模块时启用了严格的指针转换检查:

\n

/lib/modules/$(uname -r)/build/Makefile

\n
# enforce correct pointer usage\nKBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)\n
Run Code Online (Sandbox Code Playgroud)\n

我想知道是否有办法禁用该特定标志,因为它阻止我编译驱动程序。我收到错误:

\n
.../vcp_driver_source/Linux_3.x.x_4.x.x_VCP_Driver_Source/cp210x.c:290:35: error: initialization of \xe2\x80\x98void (*)(struct usb_serial_port *)\xe2\x80\x99 from incompatible pointer type \xe2\x80\x98int (*)(struct usb_serial_port *)\xe2\x80\x99 [-Werror=incompatible-pointer-types]\n  290 |         .port_remove            = cp210x_port_remove,\n      |                                   ^~~~~~~~~~~~~~~~~~\n.../vcp_driver_source/Linux_3.x.x_4.x.x_VCP_Driver_Source/cp210x.c:290:35: note: (near initialization for \xe2\x80\x98cp210x_device.port_remove\xe2\x80\x99)\ncc1: some warnings being treated as errors\nmake[2]: *** [scripts/Makefile.build:277: .../vcp_driver_source/Linux_3.x.x_4.x.x_VCP_Driver_Source/cp210x.o] Error 1\nmake[1]: *** [Makefile:1874: .../vcp_driver_source/Linux_3.x.x_4.x.x_VCP_Driver_Source] Error 2\nmake[1]: Leaving directory \'/usr/src/linux-headers-5.15.23-76051523-generic\'\nmake: *** [Makefile:7: …
Run Code Online (Sandbox Code Playgroud)

c makefile kernel-module linux-kernel kbuild

2
推荐指数
1
解决办法
1290
查看次数

Syscall实现内核模块2.6

在做了一些阅读之后,我开始明白通过LKM添加新的系统调用在2.6中变得更难.似乎syscall表不再导出,因此在运行时插入新调用(不可能?).

我想要实现的目标如下.

我有一个正在执行特定任务的内核模块.此任务取决于应由用户土地过程提供的输入.此信息需要到达模块.为此,我将介绍一个新的系统调用,它在内核模块中实现,并可从用户域进程调用.

如果我必须重新编译内核以添加我的新系统调用,我还需要在内核模块之外编写实际的系统调用逻辑,对吗?

还有另一种方法吗?

干杯,eeknay

system-calls kernel-module linux-kernel

1
推荐指数
1
解决办法
505
查看次数

在linux内核中遍历进程树

我在内核模块中有以下代码,它在进程树中向上打印进程名称和uid直到init进程:

// recursivly walk the task's parent until we reach init

void parent_task_walk(struct task_struct *task) {

    struct task_struct *parent;
    char filename[MAX_FILE_LEN];

    if (task && task->mm) {

        parent = get_task_parent(task);

        printk("%s (uid:%d)", exe_from_mm(task->mm, filename, MAX_FILE_LEN),
            get_task_uid(task));

        if (parent && task->pid != 1) {
            printk(", ");
            parent_task_walk(parent);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

注意:我使用了一些引用真实内核函数的宏,因为这是针对内核模块跨越多个版本的.源代码在此文件中:https://github.com/cormander/tpe-lkm/blob/319e1e29ea23055cca1c0a3bce3c865def14d3d2/core.c#L61

输出最终看起来像这样:

/bin/bash (uid:500), /usr/sbin/sshd (uid:500), /usr/sbin/sshd (uid:0), /usr/sbin/sshd (uid:0), /sbin/init (uid:0)

这是一个递归函数.可以想象,当你启动200个bash shell然后触发事件时,事情会变得很糟糕.我不确定究竟发生了什么,但机器冻结了.内核耗尽了我假设的堆栈空间,去了OOM,然后自己开枪?

我想知道处理这种情况的最佳方法是什么.我看到几个选项:

1)在N个进程后停止遍历进程树

2)在一些字符数组(最终将被打印)已满后停止行走

3)使用a goto而不是递归函数,但仍然遵守选项#1和#2的新规则

4)使用一些你将为我阐述的非递归方法

这发生在内核空间,所以不是最好客的环境.任何人都可以指出最好的方法吗?

recursion kernel kernel-module linux-kernel

1
推荐指数
1
解决办法
3192
查看次数

使用kretprobes post handler获取syscall参数

我希望在这些系统调用返回后立即使用LKM跟踪sys_connect和sys_accept.我发现通过定义一个post处理程序,kprobes可以在探测到的系统调用返回时访问寄存器.

我的问题是我不知道如何从我在post处理程序中的数据中获取系统调用参数(即struct pt_regs).后处理程序的定义如下:

void post_handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags);
Run Code Online (Sandbox Code Playgroud)

architecture trace kernel kernel-module linux-kernel

1
推荐指数
1
解决办法
1041
查看次数

如何解决这个编译错误

尝试一些FreeBSD内核黑客攻击,我在一个简单的钩子示例中遇到了错误.代码如下

*注意 - 我添加了#include <sys/stat.h>尽可能多的建议,但继续得到相同的错误.

#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/sysproto.h>
#include <sys/stat.h>

static int mkdir_hook(struct thread *td, void *syscall_args) {

  struct mkdir_args *uap;
  uap = (struct mkdir_args *)syscall_args;
  char path[255];
  size_t done;
  int error;
  error = copyinstr(uap->path, path, 255, &done);
  if(error != 0)
    return (error);

  uprintf("hooked it\n");
  return (mkdir(td, syscall_args));
}

static int load(struct module *module, int cmd, void *arg) {
  int error = 0; …
Run Code Online (Sandbox Code Playgroud)

c kernel freebsd kernel-module

1
推荐指数
1
解决办法
1552
查看次数

netfilter-like内核模块获取源和目标地址

我阅读本指南来编写内核模块来进行简单的网络过滤.

首先,我不知道这意味着什么,以及入站和出站数据包(通过传输层)之间的区别是什么?

当数据包从线路进入时,它会从物理层,数据链路层,网络层向上传播,因此它可能无法通过netfilter中定义的功能来使skb_transport_header工作.

其次,我讨厌幻数,我想20用linux内核的实用程序(源文件)中的任何函数替换(典型IP头的长度).

任何帮助将不胜感激.

linux kernel-module linux-kernel

1
推荐指数
1
解决办法
1179
查看次数

如何使用Linux内核模块中的地址转储/列出所有内核符号?

在内核模块中,如何列出所有内核符号及其地址?不应重新编译内核。

我知道接口中的“ cat / proc / kallsyms”,但是如何使用诸如之类的函数直接从内核数据结构中获取它们kallsyms_lookup_name

kernel-module linux-kernel

1
推荐指数
1
解决办法
7526
查看次数