E
E
egorggegor2021-02-03 16:45:34
linux
egorggegor, 2021-02-03 16:45:34

Why does the system freeze when writing to /proc/?

There is the following code, it describes a file in /proc/, when you try to write something to this file, the system hangs and stops responding. Maybe someone knows what the problem is?

#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/slab.h>

MODULE_DESCRIPTION("Process Setting Module");
MODULE_LICENSE("GPL");

/*PROC макросы*/
#define PROC_CONFIG_FILE_NAME	"process_sched_add"

/*Стандартные макросы*/
#define BASE_10 		10

/*Состояния процессов*/
enum process_state {
    
    eCreated        =    0, /*Процесс сощдан*/
    eRunning        =    1, /*Процесс выполняется*/
    eWaiting        =    2, /*Процесс в состоянии ожидания*/
    eBlocked        =    3, /*Процесс заблокирован*/
    eTerminated     =    4  /*Процесс завершен*/
};

/*Enum для выполнения функций*/
enum execution {

  eExecFailed 	= 	-1, /*Выполнение функции завершилось неудачно*/
  eExecSuccess 	=	 0  /*Выполнение функции завершилось успешно*/
};

/*PROC FS директива объекта*/
static struct proc_dir_entry *proc_sched_add_file_entry;


/*Прототипы  внешних  функций очереди процессов*/
extern int add_process_to_queue(int pid);
extern int remove_process_from_queue(int pid);
extern int print_process_queue(void);
extern int get_first_process_in_queue(void);
extern int remove_terminated_processes_from_queue(void);
extern int change_process_state_in_queue(int pid, int changeState);

/*Функция вызывается, когда читается файл process_sched_add.
 /proc/process_sched_add_module - это файл только для записи  */
static ssize_t process_sched_add_module_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
  
  printk(KERN_INFO "Process Scheduler Add Module read.\n");
  printk(KERN_INFO "Next Executable PID in the list if RR Scheduling: %d\n", get_first_process_in_queue());
  return 0;
}

/*Функция вызывается, когда записывается файл process_sched_add.
 /proc/process_sched_add_module - это файл только для записи*/
static ssize_t process_sched_add_module_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
  int ret;
  long int new_proc_id;	
  
  printk(KERN_INFO "Process Scheduler Add Module write.\n");
  printk(KERN_INFO "Registered Process ID: %s\n", buf);
  
  ret = kstrtol(buf,BASE_10,&new_proc_id);
  if(ret < 0) {
    return -EINVAL;
  }
  
    /*Добавление процесса в очередь процессов*/
  ret = add_process_to_queue(new_proc_id);
    /*Проверка на то, успешно ли добавлен процесс в очередь процессов*/
  if(ret != eExecSuccess) {
    printk(KERN_ALERT "Process Set ERROR:add_process_to_queue function failed from sched set write method");
    return -ENOMEM;
  }

  return count;
}

/*Функция, которая вызывается, когда process_sched_add был открыт.
 /proc/process_sched_add_module - это файл только для записи*/
static int process_sched_add_module_open(struct inode * inode, struct file * file)
{
  printk(KERN_INFO "Process Scheduler Add Module open.\n");
  
  return 0;
}

/*Функция, которая вызывается, когда process_sched_add был закрыт.
 /proc/process_sched_add_module - это файл только для записи*/
static int process_sched_add_module_release(struct inode * inode, struct file * file)
{
  printk(KERN_INFO "Process Scheduler Add Module released.\n");
  return 0;
}

/*Файловые операции связанные с process_sched_add*/
static struct file_operations process_sched_add_module_fops = {
  .owner =	THIS_MODULE,
  .read =		process_sched_add_module_read,
  .write =	process_sched_add_module_write,
  .open =		process_sched_add_module_open,
  .release =	process_sched_add_module_release,
};

/*Функция инициализации модуля ядра. Вызывается при запуске модуля ядра*/
static int __init process_sched_add_module_init(void)
{
  printk(KERN_INFO "Process Add to Scheduler module is being loaded.\n");
  
    /*PROC FS создается с разрешениями RD&WR с именем process_sched_add*/
  proc_sched_add_file_entry = proc_create(PROC_CONFIG_FILE_NAME,0777,NULL,&process_sched_add_module_fops);
    /*Проверка на успешность создания process_sched_add*/
  if(proc_sched_add_file_entry == NULL) {
    printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",PROC_CONFIG_FILE_NAME);
    return -ENOMEM;
  }
   
  return 0;
}

/*Функция очистки модуля ядра. Вызывается при удалении модуля ядра*/
static void __exit process_sched_add_module_cleanup(void)
{
  
  printk(KERN_INFO "Process Add to Scheduler module is being unloaded.\n");
    /*PROC FS объект был удален*/
  proc_remove(proc_sched_add_file_entry);
}
module_init(process_sched_add_module_init);
module_exit(process_sched_add_module_cleanup);

Answer the question

In order to leave comments, you need to log in

1 answer(s)
J
jcmvbkbc, 2021-02-04
@jcmvbkbc

static struct file_operations process_sched_add_module_fops = {
…
proc_create(PROC_CONFIG_FILE_NAME,0777,NULL,&process_sched_add_module_fops);

I think this is the main mistake: proc_create takes a pointer to a struct proc_ops, not a file_operations. The compiler should have said something at this point, don't you read its warnings?
static ssize_t process_sched_add_module_write(struct file *file, const char *buf, size_t count, loff_t *ppos)

And here you lost the annotation __userof the parameter buf. This buffer comes from the userspace, for this reason you cannot access it directly with the kstrtol.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question