Предупреждение copy_from_user о том, что размер недоказуемо правильный?

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

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

#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;
}

Предупреждение, которое я получаю, следующее:

предупреждение: вызов «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 (как видите)


person Shahbaz    schedule 03.04.2012    source источник
comment
Можете ли вы также сказать нам, в каком файле выдается это предупреждение? Какая у вас версия ядра и другие подобные детали?   -  person Pavan Manjunath    schedule 03.04.2012
comment
@PavanManjunath, я сейчас дома, но я свяжусь с тобой завтра утром   -  person Shahbaz    schedule 04.04.2012


Ответы (1)


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

min((unsigned long)amount, count)

с участием

min((unsigned long)READ_CHUNK, count)

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

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

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

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

person Pavan Manjunath    schedule 03.04.2012
comment
Хотя это должно быть min((unsigned long)READ_CHUNK, amount), потому что мне нужно прочитать amount, но все же это не решает проблему со вторым случаем, когда память распределяется динамически и, следовательно, фиксированного размера, такого как READ_CHUNK, не существует! - person Shahbaz; 04.04.2012
comment
Кстати, я попробовал то, что вы сказали (min og READ_CHUCK и количество), и все равно получаю то же предупреждение. - person Shahbaz; 04.04.2012
comment
Предупреждение исчезает, если вы жестко задаете размер копии? Скажите, например, 50 (‹100) - person Pavan Manjunath; 04.04.2012
comment
Это действительно странно! Я использовал размер копии READ_CHUNK и даже плоскость 5, но все равно выдает то же предупреждение. У меня есть только один copy_from_user, поэтому он не может быть где-то еще. - person Shahbaz; 04.04.2012
comment
Ну нет, на самом деле, это ушло с оптимизацией и т. Д. - person Shahbaz; 06.07.2012