BUG: невозможно обработать пейджинговый запрос ядра на ffffffffffffffff - PullRequest
0 голосов
/ 05 марта 2019

В моем драйвере ядра есть обработчик ioctl, который читает и записывает ioctl. У меня также есть приложение пользовательского пространства, которое использует этот IOCTL для записи / чтения данных.

Когда я использую этот ioctl в своем приложении пользовательского пространства, он вызывает OOPS ядра с "BUG: unable to handle kernel paging request at ffffffffffffffff"

Фрагмент пользовательского пространства:

typedef struct abc_T {
    uint8_t size;
    uint8_t addr;
    uint8_t data[64];
} abc_T;

// Read
int abc_read(uint8_t addr, uint8_t size, uint8_t * data) {
     abc_T abc = {};
     int fd;
     int retval = 0;
     abc.size = size;
     abc.addr = addr;
     fd = open("/dev/"ABC_DEV, O_RDWR);

     if (fd >=0) {
       retval = ioctl(fd, READ_ABC, &abc);
       if (retval == 0)
           memcpy(data, abc.data, size);
     }
     close(fd);
     return retval;
}

// Write
int abc_write(uint8_t addr, uint8_t size, uint8_t * data) {
     abc_T abc = {};
     int fd;
     int retval = 0;
     abc.size = size;
     abc.addr = addr;
     memcpy(abc.data, data, size);
     fd = open("/dev/"ABC_DEV, O_RDWR);

     if (fd >=0) {
       retval = ioctl(fd, WRITE_ABC, &abc);
     }
     close(fd);
     return retval;
}

Ядро:

static int ABC_ioctl(struct file * file, uint cmd, ulong arg)
{
ABC_T abc;
int retval;

if (copy_from_user(&abc, (void *)arg,
                        sizeof(ABC_T)) != 0) {
    return -EFAULT;
}

switch(cmd) {
    case READ_ABC:
    retval = read_func(&abc);
    if (retval == 0) {
        if (copy_to_user((void *)arg, &abc,
                     sizeof(ABC_T)) != 0) {
                retval = -EFAULT;
        } else {
            retval = 0;
        }
    }
    break;
case WRITE_ABC:
    ret_val = write_func(&abc);
    break;
return retval;
}
Error: 
BUG: unable to handle kernel paging request at ffffffffffffffff
IP: [<ffffffffffffffff>] 0xfffffffffffffffe
PGD 1e0f067 PUD 1e11067 PMD 0 
Oops: 0010 [#1] PREEMPT SMP 
...
Call Trace:
 [<ffffffff8117a8b8>] ? vfs_write+0x198/0x1b0
 [<ffffffff8118ccc0>] ? SyS_ioctl+0x80/0x90
 [<ffffffff8117b139>] ? SyS_write+0x49/0xa0
 [<ffffffff819af419>] ? system_call_fastpath+0x16/0x1b
Code:  Bad RIP value.
RIP  [<ffffffffffffffff>] 0xfffffffffffffffe
...

Не уверен, что не так в этом. Может кто-нибудь, пожалуйста, помогите?

Обновление: с размером массива 32 в abc_T я не вижу проблемы. Но когда я изменяю размер массива на 64, я вижу проблему. Любая помощь будет оценена.

Обновление 2: при размере массива 64 в abc_T, если чтение / запись size равно <= 32, проблем не возникает, только когда <code>size для чтения / записи больше 32, наблюдается сбой ,

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

С учетом этих обновлений:

Обновление: с размером массива 32 в abc_T я не вижу проблемы. Но когда я изменяю размер массива на 64, я вижу проблему. Любая помощь будет оценена.

Обновление 2: с размером массива 64 в abc_T, если размер чтения / записи <= 32, нет проблем, только когда размер для чтения / записи больше чем 32, сбой видно. </p>

Вы, вероятно, превышаете пространство, выделенное для стека вызовов ядра.

Код такой

 abc_T abc = {};

выделяет abc_T объект в стеке вызовов, который крайне ограничен внутри ядра. Вы, вероятно, должны использовать kmalloc():

abc_T *abc = kmalloc( sizeof( *abc ), GFP_KERNEL );

Вам нужно проверить результат и освободить всю память, выделенную с помощью kfree():

kfree( abc );
0 голосов
/ 05 марта 2019

Я не могу быть уверен, что это ваша проблема, но у вас есть некоторые проблемы в вашем коде

In

int abc_read(uint8_t addr, uint8_t size, uint8_t * data) {
     abc_T abc = {};
     int fd, retval;
     abc.size = size;
     abc.addr = addr;
     fd = open("/dev/"ABC_DEV, O_RDWR);

     if (fd >=0) {
     retval = ioctl(fd, READ_ABC, &abc);
     if (retval == 0)
         memcpy(data, abc.data, size);

     }
return retval;
}

, если open не удается retval никогда не устанавливается, но вы его возвращаете, поведение не указано в ABC_ioctl, поскольку вы используете возвращаемое значение

Мы не видим конца abc_write, возвращаете ли вы значение, если open не удается?

PS Сначала я предположил, что вы делаете memcpy , даже если открытие не удается, пожалуйста, позаботьтесь о отступе (я изменил ваш вопрос, чтобы изменить его)


Может быть, посмотрите на Как использовать ioctl для чтения и записи в chardev?

...