사용자 정의 모듈을 로드한 후 커널이 중단됩니다.

사용자 정의 모듈을 로드한 후 커널이 중단됩니다.

나는 기본적으로 주어진 인터페이스(아래 코드)의 모든 패킷에 메시지를 인쇄하는 간단한 커널 모듈을 가지고 있습니다. 어떤 커널을 사용하여 컴파일하고 실행하더라도 시스템이 실행되는 동안 몇 초 동안 중단됩니다. Linux 자체에서는 어떤 메시지도 받지 못하지만 VMWare에서는 게스트 OS가 CPU를 정지시켰다고 말합니다. 모듈이 오류 없이 컴파일되고 로드됩니다. 어떤 아이디어가 있나요? 어떻게 디버깅할까요? Journalctl은 아무것도 표시하지 않습니다. 어떤 도움이라도 대단히 감사하겠습니다. 저는 이것에 대해 매우 익숙하지 않으며 디버깅 방법을 모릅니다.

가상 머신 로그:

2024-02-01T11:57:03.994Z In(05) vcpu-0 MsgHint: msg.monitorevent.halt
2024-02-01T11:57:03.994Z In(05)+ vcpu-0 The CPU has been disabled by the guest operating system. Power off or reset the virtual machine.
2024-02-01T11:57:03.994Z In(05)+ vcpu-0 ---------------------------------------```

커널 모듈 소스 코드:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/inet.h>

static struct nf_hook_ops netfilter_ops;
static char *interface = "ens33"; 
module_param(interface, charp, 0);

static unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) {
    char source[16], dest[16];

    if (!skb) {
        return NF_ACCEPT;
    }

    if (strcmp(state->in->name, interface) == 0 || strcmp(state->out->name, interface) == 0) {

        struct iphdr *ip_header = ip_hdr(skb);
        if (!ip_header) {
            return NF_ACCEPT;
        }


        snprintf(source, 16, "%pI4", &ip_header->saddr);
        snprintf(dest, 16, "%pI4", &ip_header->daddr);

        printk(KERN_INFO "Packet logged on %s: Source IP: %s, Destination IP: %s\n", interface, source, dest);
    }
    return NF_ACCEPT;
}

static int __init my_module_init(void) {
    netfilter_ops.hook = hook_func;
    netfilter_ops.pf = PF_INET;
    netfilter_ops.hooknum = NF_INET_PRE_ROUTING;
    netfilter_ops.priority = NF_IP_PRI_FIRST;

    nf_register_net_hook(&init_net, &netfilter_ops);
    printk(KERN_INFO "Kernel module initialized on interface %s\n", interface);
    return 0;
}

static void __exit my_module_exit(void) {
    nf_unregister_net_hook(&init_net, &netfilter_ops);
    printk(KERN_INFO "Kernel module removed\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("foo bar baz");
MODULE_DESCRIPTION("Netfilter packet logging module");
MODULE_VERSION("0.1");

답변1

글쎄요, 제가 직접 답을 찾은 것 같습니다. 문제는 후크 메소드가 호출될 때 상태->인 또는 상태->아웃 중 하나만 설정할 수 있다는 것입니다(분명히). 수정 후 관련 줄은 다음과 같습니다.

if ((state->in && strcmp(state->in->name, interface) == 0) || (state->out && strcmp(state->out->name, interface) == 0)) {

관련 정보