LINUX.ORG.RU

поток ядра созданный kthread_create() не может создать или открыть файл используя filp_open()

 


0

2

Доброго времени суток,изучаю vfs,знаю что это не хороший тон, с кода ядра создавать писать читать и удалять файлы,но я хочу научиться это делать

я написал код,когда я в onload() открывал файл и делал set_fs(),то файл создавался ,но ругался supervisor,но когда я это сделал в kernel thread ,то файл не создаётся хотя есть его структура file :)

я не могу понять почему callback функции могут,а потоки ядра не могут?

Я даже начал думать может поток имеет uid не рута или gid не рута и из за этого он не может создать файл с правами ,но когда я вывел в лог креденшелы потока то там был всё в ноль(в рут)

Потом я начал думать может поток не имеет fs или files в task_struct ,но и они есть ,указатели не нулевые.

вот моё логирование:

[ 173.839495] kmodule: onload [ 173.839496] before run main [ 173.839615] kmodule: Complete init module [ 173.839698] 1 [ 173.839700] 2 [ 173.839701] 3 [ 173.839702] 4 [ 173.839707] kmodule: struct file:00000000f6821bf4, s8 *buf:0000000004d4437e,size_t size_buf:1024,*f_pos:00000000005817e6 [ 173.839708] 5 [ 173.840182] 6 [ 173.840185] 7 [ 173.840186] 8

Мой код:

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/sched/signal.h> #include <linux/types.h> #include <linux/kthread.h> #include <linux/slab.h> //#include <linux/kallsyms.h>

MODULE_LICENSE(«GPL»);

struct module_struct { s8 *buf; size_t size_buf; struct file *f; mm_segment_t oldfs; } module_data;

void strrev(unsigned char *str) { int i; int j; unsigned char a; unsigned len = strlen((const char *)str); for (i = 0, j = len - 1; i < j; i++, j–) { a = str[i]; str[i] = str[j]; str[j] = a; } }

int itoa(int num, unsigned char* str, int len, int base) { int sum = num; int i = 0; int digit; if (len == 0) return -1; do { digit = sum % base; if (digit < 0xA) str[i++] = ‘0’ + digit; else str[i++] = ‘A’ + digit - 0xA; sum /= base; }while (sum && (i < (len - 1))); if (i == (len - 1) && sum) return -1; str[i] = ‘\0’; strrev(str); return 0; }

static int module_main(void *local_data) { module_data.oldfs = get_fs(); set_fs(KERNEL_DS);

module_data.f = filp_open("kernel_log.dump",O_RDWR | O_CREAT,0);

if(IS_ERR(module_data.f))
{
    printk(KERN_ALERT "kmodule: cannot create kernel file log\n");
    set_fs(module_data.oldfs);
    kfree(module_data.buf);
    return -EPERM;
}

printk(KERN_INFO "1\n");
struct task_struct *task;

printk(KERN_INFO «2\n»);

s8 *pnum = kmalloc(256,GFP_KERNEL);

printk(KERN_INFO «3\n»);

if(pnum == NULL) 
{
    printk(KERN_ALERT "kmodule: cannot alloc kern mem\n");
    filp_close(module_data.f,NULL);
	    kfree(module_data.buf);
	    set_fs(module_data.oldfs);
    return -ENOMEM;
}

printk(KERN_INFO «4\n»);

strcat(module_data.buf,
"kernel dump,dumped by kmodule kernel process\n");

/* for_each_process(task) { strcat(module_data.buf,«process_name: «); strcat(module_data.buf,task->comm); strcat(module_data.buf,» pid: «); itoa(task->pid,pnum,256,10); strcat(module_data.buf,pnum); strcat(module_data.buf,» \n»); vfs_write(module_data.f,module_data.buf,module_data.size_buf,&module_data.f->f_pos); memset(module_data.buf,0,module_data.size_buf); } */

printk(KERN_INFO "kmodule: struct file:%p, s8 *buf:%p,size_t size_buf:%lld,*f_pos:%p\n",module_data.f,module_data.buf,module_data.size_buf,&module_data.f->f_pos);

printk(KERN_INFO "5\n");

if(vfs_write(module_data.f,module_data.buf,module_data.size_buf,&module_data.f->f_pos) < 0) 
{
printk(KERN_ALERT "kmodule: cannot write data\n");
kfree(pnum);
    set_fs(module_data.oldfs);
return -EPERM;
}

printk(KERN_INFO «6\n»);

if(filp_close(module_data.f,NULL) < 0) {

    kfree(pnum);
    set_fs(module_data.oldfs);
printk(KERN_ALERT "kmodule cannot close file\n");
return -EAGAIN;

}

kfree(pnum);

printk(KERN_INFO «7\n»);

set_fs(module_data.oldfs);

printk(KERN_INFO «8\n»);

return 0;

}

static int __init onload(void) {

printk(KERN_INFO "kmodule: onload\n");

module_data.buf = kmalloc(1024,GFP_KERNEL);
module_data.size_buf = 1024;

if(module_data.buf == NULL) 
{
    printk(KERN_ALERT "kmodule: cannot alloc kernel mem\n");
return -ENOMEM;
}


    
printk(KERN_INFO "before run main\n");

if(kthread_run(module_main,NULL,"module_main") == NULL) 
{
    printk(KERN_ALERT "kmodule: cannot create main thread\n");

// filp_close(module_data.f,NULL); // set_fs(module_data.oldfs); kfree(module_data.buf); return -EPERM; }

printk(KERN_INFO "kmodule: Complete init module\n");

return 0;

}

static void __exit unload(void) { printk(KERN_INFO «kmodule: unload\n»); kfree(module_data.buf); }

module_init(onload); module_exit(unload);

Оформил бы ты свой код согласно правилам, а то читать для глаз больно.

Посмотри на «include/linux/fs.h», там есть прототипы функций для работы с файлами: kernel_read/write_[file]*

Если уж пытаться писать в файл из ядра, то используй его API для этого, оно само сделает всю магию с переключением DS. И его основная идея заключается в том, что если есть ненулевой *file, то можно выйти на его файловые операции. e.g.

   file->f_op->write();
Dennis7 ()
Ограничение на отправку комментариев: только для зарегистрированных пользователей