Что мешает сборочной программе привести к сбою операционной системы? [закрыто]

18

Прежде всего, я новичок, поэтому, если этот вопрос звучит глупо, пожалуйста, укажите неверные предположения.

Из того, что я понимаю, работа операционной системы заключается в управлении оборудованием и программным обеспечением, которое работает в ОС. Кроме того, насколько я понимаю, программы сборки позволяют управлять оборудованием практически напрямую. В программе сборки можно читать и записывать данные в регистры, а также читать и записывать данные в ОЗУ.

Учитывая эту свободу связываться с регистрами и оперативной памятью, не будет ли возможность программам сборки влиять на операционную систему? Предположим, ОС использует регистр A для хранения важной информации, и предположим, что я запускаю собранную программу на этой ОС. Если программа успешно записывает мусор в регистр A, операционная система обязательно будет затронута.

Вопросов:

  1. Можно ли связываться с регистром А, как описано выше?

  2. Если нет, что мешает программам сборки изменять регистры, используемые ОС?

Flux
источник
13
умные программисты ...
Тони Стюарт Sunnyskyguy EE75
Сейчас существует много компьютерных архитектур, которые были в прошлом, а также было разработано много операционных систем. Какую архитектуру / ОС вы имеете в виду? На некоторых (старых) архитектурах не было возможности остановить программу от того, что она делала после запуска, это правильно. Но современные аппаратные средства / ОС имеют встроенные аппаратные средства, которые отдают только часть памяти для программы в «нормальном» режиме (не суперпользователя), и она не может получить доступ к памяти за пределами этого предела. Регистры можно использовать бесплатно, поскольку ОС не хранит никакой полезной информации в регистрах, просто в памяти / на диске.
cyclone125
2
В микропроцессоре ваша программа работает в «пользовательском режиме», операционные системы - в «системном режиме». Например, если программа пользовательского режима выполнила команду остановки, машина не остановится. Остановка будет захвачена, и операционная система будет вызвана. Что касается ОЗУ, ОС будет устанавливать среду для программы в режиме пользователя, чтобы через аппаратное обеспечение управления памятью то, что пользовательская программа видит как адрес ОЗУ X, не было бы адресом ОЗУ X.
Джордж Уайт
1
@flux Я обновил свой комментарий. Ответ будет таким: нет «общего» ответа на ваш вопрос, поскольку существуют / были разные архитектуры / ОС компьютеров. Это может быть по-разному.
cyclone125
2
... Давным-давно я писал в сыром машинном коде. Да ха !!! :-)
Рассел МакМэхон

Ответы:

33

В конце концов, все программы являются машинным кодом, независимо от того, был ли исходный язык ассемблером или языком высокого уровня.

Важно то, что существуют аппаратные механизмы, которые ограничивают возможности конкретного процесса, в том числе «связывание» с регистрами, которые могут повлиять на другие программы или саму операционную систему.

Это началось с простого различия между режимами работы «пользователь» и «супервизор» и с тех пор превратилось в архитектуру безопасности с несколькими «кольцами» привилегий.


Вот очень общий пример, чтобы сделать его немного более конкретным:

  • В «режиме пользователя» процесс не может получить доступ к памяти, которая не была назначена его идентификатору процесса. Память, выделенная другим процессам, и сама операционная система заблокированы. Это включает в себя значения регистров, используемых этими другими процессами. Это обеспечивается аппаратным обеспечением MMU.

  • Следовательно, в «режиме пользователя» процесс не может получить доступ к регистрам управления MMU.

  • И очевидно, что в «пользовательском режиме» процесс не может изменить режим на «режим супервизора», кроме как через очень четко определенный механизм, который включает в себя вызов функции операционной системы.

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

Дэйв Твид
источник
2
Если я правильно понимаю, то, что вы говорите: у некоторых процессоров есть «режим пользователя» и «режим супервизора». Операционная система работает в «режиме супервизора» и переводит процессор в «пользовательский режим» для запуска моей программы вымышленной сборки. В «режиме пользователя» существуют регистры и адреса ОЗУ, к которым программа сборки не может получить доступ из-за преднамеренного проектирования оборудования.
Flux
3
По сути, этот ответ описывает современные архитектуры типа i386 с MMU и защищенным режимом. Но, чтобы быть правдой, существует много старых (i8080, MOS 6502 и т. Д.), А также современных более простых (AVR, ARM Cortex-M и т. Д.) Архитектур, которые не имеют этих функций и если используется какая-либо ОС (например, старая). CP / M, современные FreeRTOS, ChibiOS и т. Д.) Ничто не может остановить программу от того, что она делает.
cyclone125
2
@Flux Архитектура i386 (и выше) предоставляет подробности для изучения. Архитектура x86 имеет не только адреса памяти, которые можно защитить, но и адреса ввода-вывода. (Для доступа к памяти и доступа к вводу-выводу используются разные инструкции.) В i386 + есть три адреса памяти. Сегментированный / основанный на селекторе адрес использует регистр селектора, который ссылается на запись таблицы (GDT или LDT), чтобы отобразить пару в один 32-битный линейный адрес. Затем таблицы подкачки преобразуют 32-разрядный линейный адрес в 36-разрядный физический адрес (P-II.) Защита существует на обоих этапах преобразования.
Джон
4
@flux ваше резюме верно. Программа в защищенной системе памяти с подходящей многозадачной ОС не должна быть способна привести к сбою системы при наличии какого-либо потока инструкций. Даже недействительные - те, которые попадают в специальный обработчик.
pjc50
Хотя существует несколько колец (по крайней мере, в x86), очень и очень редко можно использовать больше двух.
лес
10

Многие многозадачные операционные системы используют структуру данных, называемую Блок управления процессом (PCB), для решения проблемы перезаписи регистра. Когда вы запускаете свой код, ОС создает новый процесс, чтобы отслеживать его. Печатная плата содержит информацию о вашем процессе и место, выделенное для хранения содержимого регистра. Допустим, процесс A в настоящее время выполняется на процессоре, а ваш код находится в процессе B. То, что происходит, когда вы запускаете свой код, выглядит примерно так:

  1. Данные о состоянии процесса А (содержимое регистра, счетчик программ и т. Д.) Копируются на его печатную плату.

  2. Данные о состоянии процесса B копируются с его печатной платы в регистры процессора

  3. Процесс B работает на процессоре до его завершения или прерывания

  4. Данные о состоянии процесса B копируются обратно на его печатную плату

  5. Данные о состоянии процесса А копируются обратно в ЦП, и он продолжает работать

Если операционная система работает как процесс A, то вы можете увидеть, как сохранение ее регистров перед запуском вашей программы, а затем копирование их обратно в ЦП после завершения вашей программы предотвращает взаимодействие пользовательских программ с тем, что происходит в других процессах.

Чтобы пользовательские процессы не записывали поверх данных ОС в память, большинство платформ используют сегментацию памяти. По сути, используя виртуальную память, адресное пространство, которое видит процесс, может быть сопоставлено с любым произвольным диапазоном физических адресов. Пока физическое пространство памяти процессов не перекрывается, один процесс не может перезаписать данные другого.

Конечно, разные ОС делают вещи по-разному, так что это не будет применяться в каждом случае. Кроме того, на большинстве платформ процессы ОС работают в режиме, отличном от пользовательских процессов, и здесь есть некоторые сложности.

jtst
источник
4

Зависит от того, на какой платформе вы говорите.

  • На более простом процессоре процессор просто выполняет любые инструкции, которые программа ему сообщает.

  • На более сложном процессоре есть (как минимум) два режима. В одном режиме процессор делает все, что программа говорит ему делать. В другом режиме сам процессор отказывается выполнять определенные инструкции.

Что мешает программе разбить всю систему? С процессором первого типа ответ - «ничего». С базовым процессором одна мошенническая программа действительно может привести к сбою всей системы. Все ранние 8-битные домашние компьютеры и многие из 16-битных попадают в эту категорию.

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

Очевидно, что допускать сбой всей системы из-за одной программы-мошенника - это плохо. (Существуют также серьезные последствия для безопасности, позволяющие мошеннической программе получать доступ к любым данным, которые она хочет.) Чтобы избежать этого, вам нужно две вещи:

  1. Процессор, который фактически имеет защитное аппаратное обеспечение (т. Е. Его можно настроить на отказ от выполнения определенных инструкций).

  2. ОС, которая на самом деле использует эти средства, чтобы защитить себя. (Нет смысла иметь чип с защитной схемой, если ОС никогда его не использует!)

Почти любую современную настольную ОС, которую вы можете назвать (Windows, Linux, Mac OS, BSD ...), это ОС защищенного режима, работающая на процессоре с аппаратным обеспечением защиты. Если вы занимаетесь разработкой встраиваемых систем на каком-то 8-битном микроконтроллере, у него, вероятно, нет защитного оборудования. (Или любая ОС, если уж на то пошло ...)

MathematicalOrchid
источник
1

В. Что мешает сборочной программе привести к сбою операционной системы?

А. Ничего

Однако многие очень умные программисты на протяжении многих лет очень старались сделать его все более и более сложным. К сожалению, для каждого умного программиста есть много, много других, которые между ними более креативны, более амбициозны, а иногда просто счастливее умных. Каждый раз, когда умный программист говорит, что никто не должен, не мог или не мог бы что-то сделать, кто-то там найдет способ сделать это. Microsoft Windows (в качестве примера) существует уже почти 35 лет, и у нас все еще есть BSoD (Blue Screens of Death), которые являются всего лишь инструкциями, которые приводили к краху операционной системы.

Начнем с небольшой терминологии. Все, что работает на компьютере, выполняется в машинном коде. Бит, который читает нажатия клавиш или движение указателя мыши, бит, который изменяет цвет пикселя на дисплее или считывает байт из файла, и бит, который вычисляет, попала ли ваша пуля в плохого парня или бит, который решает если ваша заявка на получение кредитной карты будет принята, все они выполняются в виде последовательности инструкций машинного кода. Некоторые работы настолько распространены и выполняются так часто, что имеет смысл собрать инструкции, необходимые для их выполнения, и заставить всех использовать эту сборку. Куча этих заданий, которые позволяют или помогают другим использовать компьютер, обычно называют операционной системой, но между ними и любыми другими программами нет ничего особенного. Все они являются просто последовательностями инструкций машинного кода.

Что делает операционные системы более сложными (и поэтому подверженными сбоям), так это то, что они должны учитывать вещи, о которых вам обычно не нужно думать. Возьмите простую работу в качестве примера. Я хочу написать сообщение в конец файла. На языке высокого уровня вы бы написали что-то вроде:

  with open("myFile.txt", "w+") as f:
      # do some really clever things
      f.write("Goodbye cruel world!")

Позволяет игнорировать все детали о том, как осуществляется доступ к физическим состояниям и как они изменяются, или как они интерпретируются как биты и байты, или как эти байты передаются в и из памяти и ЦП, и доверять тому, что все обрабатывается программами, которые предоставляет ОС за кулисами. Давайте просто подумаем о том, как вы добавляете в конец файла. 1) Узнайте, где находится конец файла, 2) напишите что-нибудь в этой позиции. Что возможно могло пойти не так? На самом деле, довольно много. Подумайте о том, что еще происходит на компьютере, пока вы делаете умные вещи. Если что-либо еще, сделанное кем-либо еще (включая саму операционную систему), каким-либо образом изменяет файл, над которым вы работаете, то эта действительно простая работа внезапно становится намного более сложной. Файл длиннее, файл короче. Файл больше не существует. Диск заполнен,

Пол Смит
источник