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 (как вы можете видеть)
1 ответ
В первом примере попробуйте заменить
min((unsigned long)amount, count)
с
min((unsigned long)READ_CHUNK, count)
Теперь можно доказать, что размер копии не будет превышать 100 байт во время самой компиляции, и, следовательно, убедить gcc, что мы никогда не перезапишем целевой буфер command
что также составляет 100 байтов.
Во втором примере ни read_buffer
ни count
известны во время компиляции. Если вы не хотите, чтобы эта ошибка вас беспокоила, вам нужно отправить оцениваемые параметры времени компиляции (целевой буфер и размер копии) в copy_from_user
Если вы проверите основное ядро linux, вы вряд ли найдете примеры, когда они записывают данные из пространства пользователя в недопустимый буфер внутри ядра. Так что, я думаю, если ваш код должен быть абсолютно безопасным, вам нужно покончить с неправильным использованием буфера
PS: Узнайте о том, как gcc реализует механизм защиты от переполнения буфера, который может предотвратить некоторые атаки переполнения буфера.