Комментарии 26
static ssize_t fw_device_read(struct file* filp, char __user *buffer, size_t length, loff_t* offset) { printk("Reading from device, return total number of messages\n"); return sprintf(buffer, "%u", accepted_num + dropped_num); }
При использовании printk строка формата должна начинаться с одного из макросов KERN_*, определяющих уровень важности сообщения, или с KERN_CONT, если нужно продолжить с последним использованным уровнем важности.
Но это несущественная ошибка, в отличие от sprintf в пользовательский буфер.
Что будет, если пользователь передаст в параметре buffer невалидный пользовательский адрес?
Или что будет, если пользователь передаст в параметре buffer виртуальный адрес где-нибудь в области данных ядра?
В первом случае приложение будет завершено с SIGSEGV и сообщением ядра о недопустимом обращении ядра к виртуальному адресу, хотя достаточно было бы одного SIGSEGV.
Во втором случае память ядра будет перезаписана вашей строкой, что вряд ли закончится хорошо.
Для безопасного копирования данных в/из пространства пользователя есть функции copy_to_user и copy_from_user, а так же strlen_user/strnlen_user/strncpy_from_user.
Кроме того, вы проигнорировали параметр length, из-за чего в следующем фрагменте пользовательского кода происходит переполнение буфера msg:
int all_msg() { char msg[1] = {0}; int fd = open("/dev/device_fw", O_RDONLY); if (fd<0) { printf("Device access error, fd = %d\n", fd); return fd; } if(read(fd, &msg, 1)>0){ printf("Accepted packets number: %s\n", msg); } else { printf("Nothing to read\n"); } close(fd); return 0; }
static ssize_t fw_device_write(struct file *fp, const char *buff, size_t length, loff_t *ppos)
Второй параметр этой функции тоже имеет атрибут __user.
Правильность использования атрибута __user можно проверить, передав параметр C=1 команде make собирающей модуль.
+5
Вы совершенно правы, но я показывал концепт. Надюесь, что если люди будут писать продакшн код, то обо всех этих конечно позаботятся :) А что будет — вы все сами ответили.
-3
я показывал концепт.
Моё мнение — код, приводимый в качестве примера должен быть настолько близок к идеалу, насколько возможно, как по содержанию, так и по форме. Потому что, по сравнению с «продакшн кодом» который где-то просто работает, из этого кода существенно большее количество людей извлечёт что-то для себя, начиная от использованных приёмов и заканчивая скопипащенными строчками.
+4
Очень надеюсь, что люди, которые пишут код на С, да и впринципе на языках где нужно «вручную» управлять памятью, будут достаточно умны чтобы не копипастить этот код. Но так как, за всех сказать не могу, то соглашусь, что, есть тут недочет, вызванный ленью, что не может быть оправданием. Я обязательно учту это в будущем и постараюсь «починить» тут, если будет время, спасибо!
0
Как по мне, достаточно в начале статьи оговорить, что код не для продакшена и проверки отсуствуют
0
по уму, стоило бы все правильно написать, но когда писал, не думал, что где-то сидит гипотетический человек, который не умеет программировать и которому доверят писать что-то важное в Linux, из этой темы и что он додумается просто селать копи-паст, и не будет знать о проблемах кода для неучебных целей, и эта программа выйдет попадет к кому-то и что-то сломает ему)) честно говоря я и сейчас не думаю, что такой человек есть) но все же стоит писать «как надо»)
0
Да, наверное сказалась моя неопытность в написнии статей, первый раз. Еще раз спасибо — постраюсь исправить.
0
НЛО прилетело и опубликовало эту надпись здесь
Kernel module на Rust?
0
НЛО прилетело и опубликовало эту надпись здесь
мы не используем goto в программировании, потому что это очень сильно портит понимание, содержание, читаемость кода
Каким таким загадочно-непостижимым образом явное указание перехода на определенную метку может испортить понимание, содержание и читаемость кода???? Не понимаю…
Второе. Для того чтобы программа заработала(а не делала вид, что она что-то там делает) программист должен учесть все возможные ситуации при работе с программой, как то — ввод символьных данных вместо цифровых, длина вводимой строки, и т.д. и т.п. То есть он должен понимать что он делает и для чего. И тогда «дыр» в программах будет гораздо меньше. Хотя я совершенно не понимаю как можно писать программу(например) для работы с электронной почтой, а потом использовать её для доступа к файлам с паролями. Как по мне это очень сильно постараться нужно так сделать. Ну в смысле накосячить.
Как говориться «Проверьте свою программу на ошибки. Если в вашей программе их нет, то проверьте программу еще раз. Если снова ошибки не найдены, то вы плохой программист»
0
Каким таким загадочно-непостижимым образом явное указание перехода на определенную метку может испортить понимание, содержание и читаемость кода???? Не понимаю…
Вы серьезно? Там ссылочка для вас на термин спагетти-код.
Второе. Это уже обсуждалось. Просто take it easy. Это всего лишь учебные статьи начального уровня. Комплекст статей. Блин, если есть человек, которому доверили писать kernel device и он не знает, что input и size надо проверять, то пусть его просто уволят, а он идет учиться программировать. Цель статьи — не учить его программировать.
0
А в чем же тогда цель статьи? Несколько перефразируя Портоса «Я пишу потому что… я пишу!»? Уж если и писать то только так чтобы было лучше всех, ну или почти всех. И описывать уникальный и неповторимый опыт создания чего-то(программы, автомобиля, велосипеда, самолёта...) Как по мне так уж если писать только для галочки и абы как то уж лучше совсем не писать. В последнее время стало считаться ээээ… хорошим тоном, что ли, написать небрежно и не полно о чем бы то ни было. И потом страшно гордиться этим. Ярчайшим примером правильно написанной статьи я считаю серию статей Ю.Зальцмана в журнале «Информатика и Образование» «Архитектура и ассемблер БК». Я по его статьям учился программировать на ассемблере. Научился быстро и легко. Потому как говорил один из философов «Кто ясно мыслит, тот ясно излагает». Хотелось бы чтобы все авторы стремились к этому.
0
Цель всех шести статей, дать человеку, который находится на начальном уровне, например студентам старших курсов, возможность углубиться в тему операционных систем, сетей, разработки под Линукс, сети и немного безопасности. Дать возможность сделать это на живой примере, пройдя этап за этап. Например, в одном ЛС, у меня спрашивали по части 1.1 про эксперементы, которые можно провести в подобной виртуальной среде, а потом сказали, что уже начали пробовать сами разные вещи. Я считаю, что это лучшим образом говорит о цели статей. Я же, следующими частями, расширяю поле для учебы и подобных эксперементов.
Это прекрасно! Я вас с этим поздравляю, хотя навернека, после этих статей еще есть куда расти. Напомнию, что цели моих статей НЕ входит учеба программированию. И если с человеком выше, я еще был согласен, что надо бы переписать часть кода, то вот сейчас я все больше убеждаюсь, что все наоборот прекрасно.
Ярчайшим примером правильно написанной статьи я считаю серию статей Ю.Зальцмана в журнале «Информатика и Образование» «Архитектура и ассемблер БК». Я по его статьям учился программировать на ассемблере.
Это прекрасно! Я вас с этим поздравляю, хотя навернека, после этих статей еще есть куда расти. Напомнию, что цели моих статей НЕ входит учеба программированию. И если с человеком выше, я еще был согласен, что надо бы переписать часть кода, то вот сейчас я все больше убеждаюсь, что все наоборот прекрасно.
0
Из таких статей очень неплохо можно оценить общую мысль и концепцию. Придираться к учебным пособиям, что они недостаточно приближены к реальности это даже хз как — суть академических примеров показать вырожденный случай и общую концепцию, не отвлекаясь на незначимые вещи.
0
да-да-да… Хотелось бы чтобы Вас обучали парашютному спорту по таким пособиям, ээээ… недостаточно приближенным к реальности… Было бы ооочень любопытно посмотреть на сам процесс… Результат будет однозначным.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Создание и тестирование Firewall в Linux, Часть 1.3. Написание char device. Добавление виртуальной файловой системы…