copy_from_user предупреждение о том, что размер некорректно доказуем? - PullRequest
1 голос
/ 03 апреля 2012

Я обнаружил предупреждение при компиляции модуля ядра, что не могу обойти его.

Сначала взгляните на этот упрощенный код:

#define READ_CHUNK 100u
static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char command[READ_CHUNK];
    unsigned long left = count;
    while (left > 0)
    {
        unsigned int amount = left<READ_CHUNK?left:READ_CHUNK;    
        if (copy_from_user(command, buf, amount))
            return -EFAULT;
        buf += amount;
        left -= amount;
        /* process buffer */
    }
    return count;
}

Предупреждение Iget выглядит следующим образом:

предупреждение: вызов метода copy_from_user_overflow объявлен с предупреждением атрибута: размер буфера copy_from_user () недопустимо корректен

Как видите, этосовершенно неправильно.amount данных, которые я читаю, вполне приемлемыЯ нашел эту ссылку , говорящую, что min может использоваться в последнем параметре, чтобы заставить gcc замолчать, но это не сработало для меня (я написал:

if (copy_from_user(command, buf, min((unsigned long)amount, count)))

безрезультатно).

Кто-нибудь знает, как сообщить gcc, что это круто, и это не должно волновать?


Другое место, где это происходит, - что-то вродеследующее:

static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char *read_buffer = vmalloc(count * sizeof(*read_buffer));
    if (read_buffer == NULL)
        return -ENOMEM;
    if (copy_from_user(read_buffer, buf, count))
    {
        vfree(read_buffer);
        return -EFAULT;
    }
    /* process buffer */
    vfree(read_buffer);
    return count;
}

В этом случае gcc также выдает мне то же предупреждение, хотя оно, безусловно, верно.


Это точная ошибка:

In file included from /usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess.h:571:0,
                 from <my source file>:7:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h: In function ‘copy_from_user’:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h:212:26: warning: call to ‘copy_from_user_overflow’ declared with attribute warning: copy_from_user() buffer size is not provably correct

Версия ядра: 2.6.35.9, исправленная с помощью rtai (как вы можете видеть)

1 Ответ

2 голосов
/ 03 апреля 2012

В первом примере попробуйте заменить

min((unsigned long)amount, count)

с

min((unsigned long)READ_CHUNK, count)

Теперь можно доказать, что размер копии не будет превышать 100 байт при самом времени компиляции и, следовательно, убедить gcc, что мы никогда не перезапишем целевой буфер command, который также составляет 100 байт.

Во втором примере ни read_buffer, ни count не известны во время компиляции. Если вы не хотите, чтобы эта ошибка вас утомила, вам необходимо отправить оцениваемые во время компиляции параметры (целевой буфер и размер копии) на copy_from_user

Если вы проверите основное ядро ​​linux, вы вряд ли найдете примеры, в которых они записывают данные из пространства пользователя в недопустимый буфер внутри ядра. Так что, я думаю, если ваш код должен быть абсолютно безопасным, вам нужно избавиться от неправильного использования буфера

PS : узнайте, как gcc реализует ограниченный механизм защиты от переполнения буфера , который может предотвратить некоторые атаки переполнения буфера.

...