리눅스 커널 모듈에서 character device로 통신할때 copy_to_user function 호출하면 OS 재부팅이 되네요.

linux

꼭 해결이 안되더라도 이쪽에 조언 가능하신 분 있으시면 연락주세요. 점심&커피&술 모두 가능합니다.

프로그램 기능 설명
1. 공유기에서 HTTP 패킷을 캡쳐해서 해당 조건에 맞는 패킷은 통과하고 아닌 경우 다른 서버로 리다이렉트
2. 캡쳐한 패킷에서 User-Agent 값 추출

uname -a  결과
Linux dlinkrouter 2.6.36.4brcmarm #1 SMP Fri Jun 2 02:28:10 KST 2017 armv7l GNU/Linux


 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>

#undef __KERNEL__
#include <linux/netfilter_ipv4.h>
#define __KERNEL__

#include <linux/ip.h>
#include <linux/tcp.h>


#define NAC_MAJOR 60
#define NAC_NAME "nac"


static struct nf_hook_ops nfho;
struct file_operations nac_fops;
char * ndb_name[81];
char * ndb_code[81];


int ndb[255];



char * strlwr(char * s) {
char *t = s;

if (!s) {
return 0;
}

while ( *t != '\0' ) {
if (*t >= 'A' && *t <= 'Z' ) {
*t = *t + ('a' - 'A');
}
t++;
}

return s;
}

unsigned int hook_func( unsigned int hooknum, struct sk_buff * skb, const struct net_device * in, const struct net_device * out, int (*okfn)(struct sk_buff *)) {

    struct iphdr    * iph;
    struct tcphdr  * tcph;
    unsigned char  * http_port = "\x00\x50";
    char            * data;
char * ua_data;
int data_len;
char * tok;
int i;
int loop1;
int loop2;
char source[16];
int ip;
.
.
.
    소스코드 생략
.
.
.

    return NF_ACCEPT;
}

int nac_open(struct inode *inode, struct file *filp) {
return 0;
}

int nac_release(struct inode *inode, struct file *filp) {
return 0;
}

ssize_t nac_write( struct file *filp, const char *buf, size_t count, loff_t *fpos) {
return 0;
}

ssize_t nac_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) {

char * msg ;
sprintf(msg, "123456789\0");

copy_to_user(buf,(char *)msg,sizeof(msg));

return sizeof(msg);

}

int init_module() {
    int result;
int i;

nac_fops.owner = THIS_MODULE;
nac_fops.open = nac_open;
nac_fops.release = nac_release;
nac_fops.write = nac_write;
nac_fops.read = nac_read;


    nfho.hook  = (nf_hookfn *) hook_func;
    nfho.hooknum    = NF_IP_POST_ROUTING;
    nfho.pf    = PF_INET;
    nfho.priority  = NF_IP_PRI_FIRST;

    result = nf_register_hook(&nfho);
register_chrdev(NAC_MAJOR,NAC_NAME,&nac_fops);



    if(result)
    {
        printk(KERN_INFO "firewall : erreur nf_register_hook !\n");
        return 1;
    }

    printk(KERN_INFO "firewall : module charge.\n");

    return 0;
}


void cleanup_module() {
    nf_unregister_hook(&nfho);
unregister_chrdev(NAC_MAJOR,NAC_NAME);
    printk(KERN_INFO "firewall : module decharge.\n");
}

심상택 6년전 질문


답변 2

일주일이 지난 글이라서 이미 해결됐을수도 있지만 답글이 없길래 남겨봅니다.

우선 어디까지가 pseudo code 인지 모르겠지만 copy_to_user 앞에 코드는 충분히 문제를 일으킬만 합니다.

char * msg;
sprintf(msg, "123456789\0");

copy_to_user(buf,(char *)msg, sizeof(msg));
return sizeof(msg);

메모리가 할당되지 않은 포인터에 값을 넣는 것도 문제고, 뒤에서 sizeof에 포인터를 지정한 것도 문제고..
차라리 char msg[256]; 으로 하시면 낫지 않을까 싶습니다. 아니면 kernel에서 제공하는 kmalloc 사용하셔도 되고요.

백재연 6년전 답변

0

답변 작성하다 보니까 코드 하이라이트까지는 아니더라도 markdown 정도는 제공되어야 하지 않나 싶은 생각이 살짝 들었습니다... 혹시 *이미* 방법이 있나요?

백재연 6년전 답변

1

답변작성

목록보기