Если вы хотите запретить чтение, вы можете просто пропустить явную настройку поля .read
для struct file_operation
. Если структура определена как static
и, следовательно, инициализирована как 0
, все поля, которые явно не переопределены, по умолчанию будут иметь значение NULL
, а ядро просто ничего не сделает и вернет ошибку (я полагаю, -EINVAL
) всякий раз, когда пользовательский код пытается вызвать read
на ваш открытый файл.
В качестве альтернативы, если вы хотите вернуть пользовательскую ошибку, вы можете определить фиктивную функцию, которая возвращает только ошибку (например, return -EFAULT;
).
Как вы думаете, правильно ли я записываю ключ в буфер?
Это неправильно по нескольким причинам.
Во-первых, ваш copy_from_user()
слепо доверяет пользователю count
, так что это приводит к переполнению буфера ядра для переменной temp
, что довольно плохо. Сначала вам нужно проверить и/или ограничить размер. Вы также не проверяете возвращаемое значение copy_from_user()
, которое вам следует (и это не int
, а скорее unsigned long
).
static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
char temp[128];
memset(temp, 0, 128);
if (count > 128)
count = 128; // or alternatively return -EINVAL or another error
if (copy_from_user(temp, buf, count))
return -EFAULT;
return count;
}
Теперь код имеет больше смысла, однако переменная temp
определена только локально внутри функции, и поэтому будет потеряна после возврата из функции, вы не сможете использовать ее в других функциях работы с файлами. Если вы хотите сделать это, вы можете использовать filp->private_data
, поле struct file
, предназначенное именно для этой цели.
Вы должны создать и инициализировать буфер на open
, а затем освободить его в своей функции release
примерно так:
static int hello_proc_open(struct inode *ino, struct file *filp)
{
void *buf = kmalloc(128, GFP_KERNEL);
if (!buf)
return -ENOMEM;
filp->private_data = buf;
// ... whatever else you need to do
return 0;
}
static int hello_proc_release(struct inode *ino, struct file *filp)
{
kfree(filp->private_data);
// ... whatever else you need to do
return 0;
}
Затем в вашем write
вы можете напрямую использовать буфер после приведения его к правильному типу:
static ssize_t key_proc_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
char *temp = filp->private_data;
memset(temp, 0, 128);
if (count > 128)
count = 128; // or alternatively return -EINVAL or another error
if (copy_from_user(temp, buf, count))
return -EFAULT;
return count;
}
Наконец, я вижу, что вы используете:
.llseek = seq_lseek,
.release = single_release,
Не делайте этого. Вам не нужно использовать предопределенные операции. Не смешивайте пользовательские функции, созданные вами, с другими каноническими функциями, такими как, например, используемые для файлов последовательности. Файлы последовательности предполагают выполнение некоторой инициализации и демонтажа, либо вы используете все операции с файлами семейства seq_
, либо делаете это вручную самостоятельно ИЛИ не используете функции. В вашем случае подходит последний вариант.
Вы можете просто установить .release
на hello_proc_release()
, показанное выше, и оставить .llseek
не установленным (по умолчанию NULL
).
person
Marco Bonelli
schedule
16.04.2021
EPERM
. - person Barmar   schedule 17.04.2021open()
может проверять, указывают ли ониO_RDONLY
,O_WRONLY
илиO_RDWR
, и возвращать ошибку для неверного направления. - person Barmar   schedule 17.04.2021key_proc_read
, которая возвращает ошибку, и используйте.read = key_proc_read
- person Barmar   schedule 17.04.2021key_proc_open
, которая проверяет открытый режим. - person Barmar   schedule 17.04.2021