Эмулятор ядра OS Windows

...
  • Jurgen wrote: Mon Aug 14, 2023 1:10 am Есть какие то предположения у разработчиков ядра?
    У dunkaist спросите. Он хорошо в ядре разбирается. Я бы помог, но ассемблер не знаю. Сложен слишком для меня.
  • И ещё, когда в конце года выпустишь новую версию, выложи исходники. Только надо менять лицензию, а то тебя Майки достанут. Ведь в лицензии MASM написано, что использовать его в проектах под GNU GPL нельзя. Либо MIT, либо BSD, либо свою писать.
  • И да. С KPG я согласен. Почему бы, не реализовать поддержку приложений из Windows 3.11?
  • Jurgen wrote: Mon Aug 14, 2023 1:10 am Столкнулся с проблемой отладки. При достижении определенного размера проги, отладчик выдает ошибку (см. скрин) и отказывается работать.
    Запускаю в mtdbg, отладчик coldbg выдает такую же ошибку.

    Похоже размер моей отлаживаемой проги достиг какого-то предела (лимита) в недрах ядра.
    Глянул исходники ядра, но не нашел явных ограничений по размеру отлаживаемой проги. Размер проги 207Кбт.
    У меня не воспроизвелось, давай минимальный рабочий пример приложения.
  • Отбой, нашел причину.
    При трассировке ядра (источника сообщений об исключениях sys32.inc) выяснилось, что уже после вызова функции 70,7 происходит нарушение доступа к памяти.
    Но, так как процесс грузится как отлаживаемый, то сообщение об исключении идет к отлаживаемому процессу, а не в Board и не вызывает ошибку после вызова функции 70,7. Это ведет к заблуждению пользователя.

    Причиной сбоя доступа к памяти оказалось ошибочное размещение метки в программе.

    Месяца два назад мне нужно было добавить метку для командной строки I_PARAM. Так как в примерах в WebSVN не нашел как его ставить, то сделал это вот так:

    db 'MENUET01' ; 8-байтный идентификатор MenuetOS
    dd 1 ; версия заголовка (1 либо 2, см. док-ю)
    dd START ; адрес первой команды
    dd I_END ; размер программы
    dd MEM ; количество памяти
    dd STACKTOP ; адрес вершины стэка
    dd I_PARAM ; адрес буфера для параметров командн. строки
    dd 0 ; зарезервировано

    ;.......
    ;.......
    I_END:
    MEM:
    I_PARAM rb 100h ; <-- НЕПРАВИЛЬНОЕ МЕСТОПОЛОЖЕНИЕ!!!!!! :(

    Оказывается метка I_PARAM должна быть расположена перед меткой MEM:

    Еще прикол в том, что эта ошибка не дает о себе знать, пока размер программы не приблизится к верхней границе страницы памяти округленной до 1000h, что создает эффект якобы ограничения (лимита) размера проги. :)
  • Сейчас делаю интеграцию network функций 75... в ws2_32.dll винды и столкнулся с такой проблемой.
    Как только запустил работу винды с сокетами у меня через минуту стала падать система Колибри из-за нехватки памяти в ядре.

    Стал выяснять причину и обнаружил следующее:
    в функции 75,1 при закрытии сокета не освобождается память сокета типа IP_TCP, если не было коннекта или интернет соединения.

    Если вы для эксперимента в бесконечном цикле откроете сокет типа IP_TCP функцией 75, а потом сразу закроете, то через минуту грохнется система Колибри от нехватки памяти. :?

    По логике, если ты открыл сокет типа IP_TCP то незачем его сразу закрывать - делаем соответствующие операции и т.д.
    Однако у винды свой изврат:
    1. Создает два сокета. Один сокет подсоединяет на прослушку а другой остается пустой.
    2. В асинхронном режиме (без ожидания) проверяет наличие соединения первым сокетом . Если нет соединения он закрывает второй пустой сокет.
    3. Создает новый пустой сокет и возврат на п.2 и так по бесконечному циклу.

    В итоге,чтобы не падала система Колибри, я у себя сделал правки в системный файл socket.inc.
    Однако я не особо силен в интернет технологиях, поэтому и написал этот пост, чтобы узнать мнение авторов функций 75, правильно ли я сделал. :roll:

    Короче, раньше было так (см. ниже скрин):
    У меня создавался сокет по протоколу IP_PROTO_TCP и когда он сразу закрывался, то внутри функции 75,1 после проверки на SS_ISCONNECTED (см. socket.inc строка 767) поток просто выходит из процедуры без освобождения памяти, так как вызов функции socket_free закомментирован. (Наверно, по особым соображениям авторов)

    Оригинал socket.inc
    socket оригинал.jpg (84.27 KiB)
    Оригинал socket.inc Viewed 10358 times


    Вот мои правки файла socket.inc (см. скрин). Однако, я не уверен что нужно после проверки условий всегда вызывать функцию socket_free, как показано на скрине. :?:

    Сейчас у меня Колибри не падает, но посмотрим что дальше будет с интернетом.

    Изменения в socket.inc
    socket edit.jpg (120.05 KiB)
    Изменения в socket.inc Viewed 10358 times



    №№№№№№№№№№№№№№№№
    P.S:
    После просмотра алгоритма работы функций 75... у меня есть рацпредложение авторам этих функций.
    Предлагаю в качестве ID номеров сокетов выдавать адреса структур данных сокета.
    Эти адреса всегда будут уникальны в системе, т.к. никакая другая функция не получит этот адрес пока он не будет освобожден.
    Если нужно чтобы ID номер сокета был положительным на выходе, то можно просто автоматом сбрасывать 31-ый бит в адресе, а потом восстановить.
    В итоге не нужно проверять списки активных сокетов и упрощается алгоритм работы с данными.
    №№№№№№№№№№№№№№№
  • Как и обещал ранее, сообщаю текущее положение с проектом на конец этого года.
    Инфа идет в последовательности, что пришлось делать по ходу реализации проекта с начала этого года:

    1.) Чтобы окно нотепада могло перемещаться за пределы экрана как у винды, я изменил принцип создания окна.
    Сначала создается прозрачное окно на весь экран и уже внутри этого прозрачного окна рисуется окно нотепада, что позволило перетаскивать окно нотепада за пределы экрана.

    2.) При доводке функциональности меню нотепада простые пункты меню были сделаны.
    Но когда начал реализовывать пункт меню Файл-Открыть то столкнулся с тем, что винда начала задействовать сервисы, драйверы и систему безопасности.
    В начале я попытался обойтись созданием новых потоков для сервисов и отключить вызовы драйверов, но чем дальше в лес тем проблемнее. :?

    Поэтому было решено пойти классическим путем запуска системы винды начиная с первого исполняемого файла, которое запускается в пользовательском режиме, убрав некоторые необязательные. (Winlogon Userinit)
    Была выбрана такая схема последовательности запуска винды:
    lsass.exe → services.exe → notepad.exe (или рабочий стол explorer.exe)

    3.) Далее пришлось решать вопрос с базовой поддержкой запуска драйверов сразу, а не потом, как планировалось. После перебора вариантов остановился на таком.
    WCore запускает драйверы в пользовательском режиме. Чтобы не столкнуться с исключениями, из-за применения привилегированных ассемблерных инструкций, основные базовые три драйвера ( ntoskrnl.exe, win32k.sys, hal.sys) по факту не запускаем, а замыкаем все их внешние функции на себя.
    Для обеспечения работы драйверов пришлось дополнительно разрабатывать функции ntoskrnl.exe. Хорошо, что эти функции в большинстве случаев функционально повторяют функции ntdll

    В итоге lsass.exe бодренько загрузил более десятка системных драйверов, а список функций этих трех драйверов составил более 100кБт в теле WCore.

    Конечно, может потом случиться такая ситуация, что в будущем какой нибудь сторонний драйвер применит привилегированные инструкции. Как вариант, можно будет диспетчером исключений ловить эти события и подменять эти инструкции. Как говорится, будем посмотреть. :)


    4.) Далее разрабатывался механизм межпроцессорных коммуникаций, а также функции работы портов и каналов были переписаны с применением именованной памяти.


    5.) Далее пришлось решать вопрос с обработкой фреймов исключений в селекторе fs:0.
    По стандарту винды, при вызове программируемого исключения функцией NtRaiseException, делается перебор фреймов в списке по адресу fs:0 каждого отдельного потока.
    В нашем случае в этом fs:0 будет список фреймов исключений от разных потоков с пересортицей и мусором, так как селектор не разделен между потоками.

    После перебора вариантов остановился на таком:
    а) По ИД потока получаем пределы стека потока
    б) Начиная от текущей позиции в стеке и поднимаясь по стеку получаем фреймы исключений и обрабатываем их пока не произойдет переход по какому-то фрейму.


    6.) Далее обнаружилось, что некоторые сервисы и модули намеренно выделяют недостаточный размер стека при создании потока и при возникновении исключения в этом потоке (из-за переполнении стека), винда должна на лету автоматически изменить стек на другой стек большего размера.
    Пока предварительно разрабатывается свой диспетчер исключений для обработки таких ситуаций.


    7.) Далее при отладке запуска файла services.exe возникла такая ситуация, что для корректной работы этого файла нужно заново переписывать функции, которые ранее уже мной переписаны и отлажены, под особенности коммуникации services.exe с сервисами. :roll:
    Я не согласился с этим и поэтому, после изучения алгоритма работы services.exe, реализуется самостоятельная загрузка сервисов из списка в реестре.

    Теперь схема последовательности запуска винды пока выглядит так:
    lsass.exe → (Запуск сервисов из списка в реестре) → notepad.exe (или рабочий стол explorer.exe)


    8.) Сейчас идет процесс отладки запусков сервисов и параллельно начата реализация функционала:
    *по работе с интернетом ( ws2_32.dll)
    *по удаленному вызову процедур ( rpcrt4.dll)


    Выкладываю здесь архив на всякий случай - в нем весь черновик разработки.
    Attachments
    WinCore.zip (1.26 MiB)
    Downloaded 56 times
  • Сколько времени у тебя на это ушло? Я хочу оценить скорость разработки чтобы понимать насколько я медленный в более простой задаче.
  • Vaicheslav97 wrote: Wed Dec 20, 2023 9:10 pm Сколько времени у тебя на это ушло? Я хочу оценить скорость разработки чтобы понимать насколько я медленный в более простой задаче.
    Старт реализации проекта с сентября 2021 года
  • Этот пост будет продолжением темы поста от дек 17, 2023
    6.) Далее обнаружилось, что некоторые сервисы и модули намеренно выделяют недостаточный размер стека при создании потока и при возникновении исключения в этом потоке (из-за переполнении стека), винда должна на лету автоматически изменить стек на другой стек большего размера.
    Пока предварительно разрабатывается свой диспетчер исключений для обработки таких ситуаций.

    Ниже предлагаются варианты (алгоритмы) действий для пользователя и для ядра системы Колибри, при обработке исключений переполнения стека.
    Эти предлагаемые изменения не должны конфликтовать с текущей версией обработчика исключений.


    ;""""""""""""""""""""""""""""""""""""""""
    Действие пользователя
    Если пользователь (приложение) желает обрабатывать исключения переполнения стека, то он создает в теле программы дополнительную область памяти для аварийного\резервного стека с размером, достаточным для обработки данного исключения.

    Алгоритм действий пользователя:
    1. Создает в заголовке программы дополнительное поле с меткой. (Например EXCEPT_STACKTOP)
    2. Для метки EXCEPT_STACKTOP выделяется область памяти.
    3. Ставит флаг 12 в маске обработки исключений стека в функции 68,24
    4. При возникновении исключения с кодом 12 в аварийном стеке будет представлена нижеследующая инфа (см структуру EXCEPT_STACK)
    struct except_stack.jpg
    struct except_stack.jpg (45.11 KiB)
    Viewed 6682 times

    5. Обработчик приложения делает то, что нужно и при завершении обработки этого исключения сбрасывает (обнуляет) бит занятости аварийного стека. (структура EXCEPT_STACK.LockAccess)


    Ниже показан пример установки метки для аварийного\резервного стека:
    header_app.jpg
    header_app.jpg (105.13 KiB)
    Viewed 6682 times
    Пример выделения памяти для аварийного\резервного стека:
    end app info.jpg
    end app info.jpg (90.95 KiB)
    Viewed 6682 times

    Продолжение следует......
  • Продолжение темы

    ;"""""""""""""""""""""""""""""""""""""""""""""
    Алгоритм ядра системы Колибри
    При возникновении исключения со стеком, по логике должно генерироваться исключение 12. Однако, из-за настроек (системы или процессора), при переполнении стека чаще всего генерируется исключение 14 (page fault).
    У меня генерируется исключение 14 даже при явном применении команд типа push pushad со стеком. :shock:
    Поэтому, при возникновении исключения 14, предлагаю сделать в ядре дополнительные проверки для корректного определения причины исключения.

    Принцип проверки:
    Перед базовым адресом стека всегда будет незанятая область памяти в 1000h и поэтому, если обращение к памяти было в пределах этого размера, то значит была попытка обратиться к несуществующей памяти стека.


    Ниже предлагается:
    1. Внедрить в файл sys32.inc (после метки IRetToUserHook:) код дополнительной проверки причины исключения. (см ниже)
    2. Внести изменение в структуре APP_HEADER_01_ (добавить дополнительное поле - except_stack_top) в taskman.inc (см ниже)

    Изменение в структуре APP_HEADER_01_
    struct app_header.jpg
    struct app_header.jpg (48.6 KiB)
    Viewed 6675 times


    Код дополнительной проверки после метки IRetToUserHook:
    except_stack.jpg
    except_stack.jpg (218.43 KiB)
    Viewed 6675 times
    except_stack2.jpg
    except_stack2.jpg (222.56 KiB)
    Viewed 6675 times


    Если не будет возражений, то я планирую через месяц внести этот код в SVN, а также прописать в справочнике по функциям sysfuncr.txt у функции 68,24 дополнительную инфу по исключениям


    №№№№№№№№№№№№№
    Примечание по коду проверки исключения 14

    Библиотеки винды используют два варианта увеличения стека через исключение:
    1. Простое переполнение в ходе использования стека
    2. Динамическое выделение области памяти в стеке размером более чем в 1000h

    Ниже показан пример процедуры динамического выделения памяти в стеке в модуле dmserver.dll
    stack dmserver_dll.jpg
    stack dmserver_dll.jpg (73.05 KiB)
    Viewed 6675 times

    Так вот, при выделения памяти в стеке размером более чем 1000h, мой код может не определить это исключение, так как разница между адресом в регистре esp и адресом в регистре cr2 может составить более 1000h.

    Для 100% определения исключений в стеке, нужно дополнительно определить по адресу в ESP базовый адрес памяти стека. И уже по базе памяти стека вычислять разницу с регистром cr2.

    Я пока не нашел в ядре Колибри функцию определения базы памяти по его адресу. Видимо потом придется прописывать дополнительный код.
    №№№№№№№№№№№
  • Jurgen wrote: Sun Nov 12, 2023 5:30 am Сейчас делаю интеграцию network функций 75... в ws2_32.dll винды и столкнулся с такой проблемой.
    Как только запустил работу винды с сокетами у меня через минуту стала падать система Колибри из-за нехватки памяти в ядре.
    You got the basics right.
    The reason socket_free is commented out is because stack is still unfinished. :(
    There are some problems in the current design with thread-safety (locking) and possible use-after-free cases..
    "Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction." Albert Einstein
  • hidnplayr wrote: Wed Jan 31, 2024 11:28 pm ...
    There are some problems in the current design with thread-safety (locking) and possible use-after-free cases..
    For causes of the use-after-free.

    Сan be using fixed or dynamically signature (currentID) in the socket data.
    When creating a socket, write the signature.
    Before closing a socket, del the signature.
    After received the socket from a user, check signature of the socket. If there isnt signature, then the socket isnt valid.
  • Jurgen wrote: Fri Feb 02, 2024 7:15 am
    hidnplayr wrote: Wed Jan 31, 2024 11:28 pm ...
    There are some problems in the current design with thread-safety (locking) and possible use-after-free cases..
    For causes of the use-after-free.

    Сan be using fixed or dynamically signature (currentID) in the socket data.
    When creating a socket, write the signature.
    Before closing a socket, del the signature.
    After received the socket from a user, check signature of the socket. If there isnt signature, then the socket isnt valid.
    Except this signature cannot be in the socket structure itself, because that in itself is also 'use after free' ;)
    "Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction." Albert Einstein
  • Who is online

    Users browsing this forum: No registered users and 13 guests