неудачники
Самое что меня больше всего вывело из себя это даже не то что COM порт не работал, а то что ядро об этом даже никак не сообщало - на лицо полное отсутствие контроля за правильностью выполнения кода и проверки значений возвращаемых функциями внутри модуля, который выполняется на уровне ядра!
порт нормально открывается через open(...)
порт нормально принимает настройки через ioctl(...)
при записи данных через write(...) ядро говорит что все отлично и все данные переданы
Но! При этом ни на внешнее устройство никаких данных не проходит ни от внешнего устройства ...
при чтении порта по read(...) ничего не происходит, не смотря на то что устройство довольно активно шлет данные, что видно по звуковой и световой индикации на самом устройстве. При проверке по select(...) никаких принятых данных нету ...
А вообще про Linux ... помните Нервный выкладывал exploit? Я его тогда на досуге не только протестил на разных дистрах, но и слегка развинтил что бы понять как он работает ...
Так вот, представьте себе, что в ядре, в обработчике системного вызова sys_send, который отвечает за передачу данных в сокет, в некотором месте происходит вызов кода по таблице указателей.
В принципе само по себе это не страшно при нормальной организации проверок в коде и контролем за границами массивов, но ... при определенном стечении обстоятельств (которое и моделируется эксплойтом) вызов происходит по указателю, который не был инициализирован (или может вообще не находится в пределах таблицы?), т.е. в нем записан ноль!
Само по себе это не приводило бы к проблемам если бы в коде стояла проверка указателей на допустимость значений перед их использованием - ядро просто должно было ругнуться по null pointer exception и убить процесс, но ... вместо этого происходит нормальный переход на адрес 0.
Опять таки и это не вызвало бы никаких проблем в нормальной системе с нормальным управлением памятью ... ядро должно было просто обнаружить передачи управления в пространство памяти находящееся вне ядра и вызвать exception по segmentation fault и так же просто убить процесс, но ... и этого в Linux не происходит.
В результате управление передается на адрес 0, при этом уровень выполнения кода остается уровнем ядра (Ring 0).
Адрес 0 соответственно предварительно пропатчен, через другую известную дырочку, что и приводит к вызову кода пользователя с привилегиями ядра.
А вызванный код просто просматривает таблицу состояния процесса, обычно не доступную процессу пользователя на запись, где заменяет идентификаторы текущего пользователя на нули - идентификаторы пользователя root.
Потом имитируется нормальное завершение обработчика системных вызовов ядра и порождается дочерний процесс, который от текущего вместе с таблицой состояний наследует и привелегии root.
Вот и все ...
А в чем причина? А причин целых две:
Во первых не желание гражданина Торвальдса заниматься такими вопросами как архитектура ядра и управление распределением памяти, в результате чего при переходе в код ядра, при вызове приложениями системных вызовов (Syscall-ов), ядро просто назначает всю оперативную память как два больших сегмента - кода и данных, начинающихся с адреса 0 и имеющих размер в 4 гигабайта (Flat mode) и имеющих высший уровень привелегий. Причем похоже это как в первой версии Linux было сделано, так в будующем никаких изменений в этом вопросе и не планируется.
А во вторых неумение или не желание программистов, занимающихся разработкой/доработкой кода ядра грамотно организовывать свой код и заморачиваться такими мелочами как нормальное проектирование кода. Зачем усложнять себе жизнь лишней работой если пипл и так хавает? Ониж все сплошь такие великие программисты что ошибок в коде не могут делать по определению ...
P.S. Прошу прощения за такой длинный пост ... и за то что может кого далекого от разработки слишком грузанул, но извините ... наболело просто ... не смог удержаться и не высказать свое мнение.