Я пытаюсь выделить некоторую память для символа* следующим образом.
static ssize_t memo_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos){
ssize_t retval = -ENOMEM;
printk("write function\n");
if((data = kmalloc(strlen(buf), GFP_KERNEL)) == NULL)
printk("kmalloc fail\n");
if(copy_from_user(data, buf, strlen(buf))){
retval = -EFAULT;
goto out;
}
*f_pos += strlen(buf);
retval = strlen(buf);
out:
return retval;
}
'данные' объявляются в заголовочном файле как
char *data;
Когда я вызываю функцию записи, 'kmalloc сбой' строка не достигнута, который приводит меня верить kmalloc, за которым следуют, однако данные не отображены, когда я пытаюсь читать из переменной 'данных' снова.
Более смутно, если я избавляюсь от бита kmalloc в целом, данные могут быть считаны с драйвера. Хотя проблема затем - это, сопровождается загрузкой других данных, потому что у меня нет возможности к memset () им.
Я использую kmalloc правильно? По-видимому, нет. Как я должен делать это?
Кроме того, моя функция чтения следующие.
static ssize_t memo_read(struct file *f, char __user *buf,
size_t count, loff_t *f_pos){
ssize_t retval = 0;
printk("read function\n");
printk("data = %s\n", data);
if(*f_pos >= strlen(data)){
printk("EOF\n");
goto out;
}
if(copy_to_user(buf, data, strlen(data))){
retval = -EFAULT;
goto out;
}
printk("copy_to_user success\n");
*f_pos += strlen(data);
retval = strlen(data);
out:
return retval;
}
Спасибо.
Вы должны использовать strlen_user ()
на указателе пользователей, вместо strlen ()
- и вы должны позвонить только один раз, и сохранить Результат вокруг (в противном случае у вас есть потенциальная эксплуатация ядра, потому что вторая нить пользователя может изменить буфер, пока вы работаете над этим).
В качестве альтернативы вы можете использовать STRNCPY_FROM_USER ()
.
Помимо этого KMALLOC
выглядит нормально.
(Но на самом деле, как Ephemient говорит, что вы должны переосмыслить весь ваш подход и использовать аргумент
, вместо того, чтобы лечить вход в виде строки).
Поскольку вы не можете полагаться на данные, записанные в файл, являющиеся Nul-завершающимися строками, вам нужно будет сохранить параметр длины data_Len
рядом с данными
. Тогда ваш прочитал
/ Написать
Реализации будет вдоль этих строк:
static char *data = NULL;
static size_t data_len;
static DEFINE_MUTEX(data_mutex);
static ssize_t memo_read(struct file *f, char __user *buf, size_t count, loff_t *f_pos
{
ssize_t retval = 0;
char *start;
mutex_lock(&data_mutex);
if (!data)
{
retval = -EINVAL; /* Or whatever you want to do here... */
goto out;
}
if (*f_pos >= data_len)
goto out; /* EOF */
start = data + *f_pos;
retval = data_len - *f_pos;
if (retval > count)
retval = count;
if (copy_to_user(buf, start, retval))
{
retval = -EFAULT;
goto out;
}
*f_pos += retval;
out:
mutex_unlock(&data_mutex);
return retval;
}
static ssize_t memo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
ssize_t retval = -ENOMEM;
mutex_lock(&data_mutex);
if (data)
kfree(data);
data = kmalloc(count, GFP_KERNEL);
if (!data)
goto out;
if (copy_from_user(data, buf, count))
{
kfree(data);
retval = -EFAULT;
goto out;
}
*f_pos = count;
retval = count;
data_len = count;
out:
mutex_unlock(&data_mutex);
return retval;
}
Как насчет карты / словаря? Последний я проверил, это выступление (1).
-121--3702273- Не забывайте KFREE (данные)
в ваших случаях ошибок ...
в любом случае BUF
является указателем на Пользовательская память, так что не звоните Стрелок (BUF)
. Вы должны copy_from_user
сначала. Почему нет
data = kmalloc(count);
copy_from_user(data, buf, count);
?
Ваш обработчик чтения предполагает, что данные
представляют собой строку NUL. Когда вы использовали массив, это, возможно, было верно случайно, но вы никогда не убедитесь, что это в вашем обработчике записи. Я предполагаю, что copy_to_user
не удается.
Вот рабочий пример модуля «Memo», который я записал только сейчас, используя kmalloc
:
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/uaccess.h>
static char *data;
static size_t len;
static ssize_t
memo_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
ssize_t copy_len = min(len - min(len, *ppos), count);
ssize_t retval;
if (copy_to_user(buf, data + *ppos, copy_len)) {
retval = -EFAULT;
goto out;
}
*ppos += copy_len;
retval = copy_len;
out:
return retval;
}
static ssize_t
memo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
ssize_t retval;
char *newdata;
newdata = kmalloc(count, GFP_KERNEL);
if (!newdata) {
retval = -ENOMEM;
goto out;
}
if (copy_from_user(newdata, buf, count)) {
retval = -EFAULT;
goto out;
}
kfree(data);
data = newdata;
newdata = NULL;
retval = len = count;
out:
kfree(newdata);
return retval;
}
static const struct file_operations memo_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = memo_read,
.write = memo_write,
};
static struct miscdevice memo_misc = { MISC_DYNAMIC_MINOR, "memo", &memo_fops };
static int __init memo_init(void)
{
int result;
result = misc_register(&memo_misc);
if (result < 0)
return -ENODEV;
return 0;
}
static void __exit memo_exit(void)
{
misc_deregister(&memo_misc);
kfree(data);
return;
}
module_init(memo_init);
module_exit(memo_exit);
MODULE_AUTHOR("ephemient");
MODULE_LICENSE("GPL");
Конечно, это отсутствует блокировка и другие меры предосторожности, но я надеюсь, что это поможет.