информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеСтрашный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Можете меня штрафовать, но я спрошу 12.02.02 18:31  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Почему нельзя писать по нулю ?
Только не бейте ногами !
Итак:
mov eax, 0
mov [eax], 3

Последняя инструкция эквивалентна mov DS:[eax], 3
Все было бы прекрасно, если бы DS содержал 0 селектор, тогда бы исключение было бы понятным, но DS содержит не нулевой селектор. А в сегменте я могу смещатся на столько на сколько мне позволяет его длинна. Хоть на 0, хоть на 1. Мы же не в реальном режиме, где эти адреса забиты под прерывания.
Итак, почему эксептион ?
Поставим вопрос по другому 12.02.02 23:12  
Автор: PS <PS> Статус: Elderman
Отредактировано 12.02.02 23:22  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
Каким макаром обеспечивается прерывание в моем примере,
> mov eax, 0
> mov [eax], 3

Я знаю только такие способы,
1 В селекторе индекс равен 0
2 Обращение к ридонли для записи (и наоборот)
3 Обращение не из того кольца

Теперь
char* p = 0;
*p = 3;

Генерится приведеный мной ассемблерный код. DS уже установлена и не подходит не под один из 3х пунктов (индекс !=0, для записи и чтения, в том же кольце).
Вся разница в нормальной и не нормальной программе только в строчке mov eax, XXX (вот тут я правда не уверен)
Так каким образом обеспечивается прирывание ?

PS
А с наездом на реальный я конечно погорячился. может подсознательно вспомнил РК на КР580ВМ80, где сразу безвозврано попадал на вектора прерываний... (или это было в спектруме...)
Поставим вопрос по другому 13.02.02 12:52  
Автор: ih8u <i hate you> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Микропроцессорный комплект 580 РУЛЕЗ!!!!!!!!!!!!!!!!
Поставим вопрос по другому 13.02.02 11:07  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Каким макаром обеспечивается прерывание в моем примере,
> > mov eax, 0
> > mov [eax], 3
>
> Я знаю только такие способы,
> 1 В селекторе индекс равен 0
> 2 Обращение к ридонли для записи (и наоборот)
> 3 Обращение не из того кольца

4. Защита страницы на уровне процессора. Твой процесс не имеет прав обращаться к нулевой странице памяти. При попытке обращения процессор генерирует исключительную ситуацию, ядро ее обрабатывает и в твоей проге вылезает эксепшн.
Т.е. 13.02.02 11:51  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Логический адрес, в моем примере преобразуется в КОРРЕКТЫЙ линейный, но на этом не заканчивается и линейный преобразуется в физический, а т.к. винда и возможно линукс скорей всего в дескрипторах ставят нули, то линейный адрес тоже получается 00000000, и он не может преобразоваться в физический.
А что бы остановится на линейном, и оставить его как физический мне надо писать свою "операционку", в которой не будет страниц.
Так ?

Можно сказать, что есть два защищеных режима: с сегментной и со страничной адресацией. Так ?
почитал бы ты доки по процам что-ли 13.02.02 12:55  
Автор: z0 <z0> Статус: Member
Отредактировано 13.02.02 13:05  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> Логический адрес, в моем примере преобразуется в КОРРЕКТЫЙ
> линейный, но на этом не заканчивается и линейный
> преобразуется в физический, а т.к. винда и возможно линукс
> скорей всего в дескрипторах ставят нули, то линейный адрес
> тоже получается 00000000, и он не может преобразоваться в
> физический.

неправильно.

вот правильный ответ:
в режиме защиты адреса (бит 0 = 1 в CR0) логический адрес является КОРРЕКТНЫМ если он не выходит за предел адреса (limit+granularity_bit) установленный в соответствующем сегментному индексу дескрипторе.

перед проверкой логического адреса на КОРРЕКТНОСТЬ процессор выполнит проверку дескриптора - 1) индекс дескриптора (селектор)(сегмент) не может быть равен 0; 2) права доступа на дескриптор должны СООТВЕТСТВОВАТЬ (тут много нюансов) правам кода т.е. правам дескриптора CS; 3) операция с памятью должна допускаться типом данного дескриптора; 4) переходные эффекты (чтение dword по адресу fffffffe etc (не у всех процов))
в случае ошибки генерируется GeneralProtectionFault или (при стековых командах но не всегда) StackFault или Double/TripleFault

к логическому адресу прибавляется база дескриптора и получается линейный адрес - он же физический если бит 1f = 0 в CR0

если установлен режим страничного преобразования адреса (бит 1f = 1 в CR0) то происходит преобразование линейного адреса в физический по двухуровневой таблице страниц. при этом на каждом уровне происходит проверка страницы на доступность (бит юзер/супервизор) и присутствие в памяти (бит present)
по неприсутствию всегда генерится PageFault но надо помнить что у нее приоритет ОЧЕНЬ низкий и до нее часто генерится еще что-нибудь
по недоступности тоже всегда должна генериться PageFault но тут есть процессорозависимые нюансы

> А что бы остановится на линейном, и оставить его как
> физический мне надо писать свою "операционку", в которой не
> будет страниц.
> Так ?

ОС с соответствием физического и линейного адреса - DOS без EMM/QEMM etc, Novel NetWare 2.x 3.x 4.x
причем в досе поскольку RealMode то таблиц страниц и самих страниц естественно нету, а в новеле есть и то и другое но таблицы страниц так построены что преобразуют линейный в физический БЕЗ ИСКАЖЕНИЯ

>
> Можно сказать, что есть два защищеных режима: с сегментной
> и со страничной адресацией. Так ?

есть режим защиты адреса (ProtectedMode) для которого существует возможность включить режим страничной переадресации (PagingEnabled)

ЗЫ: пропущено много тонкостей естественно
почитал бы ты доки по процам что-ли 14.02.02 01:42  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> по неприсутствию всегда генерится PageFault но надо помнить
> что у нее приоритет ОЧЕНЬ низкий и до нее часто генерится
> еще что-нибудь

Ага, именно эта исключительная ситуация используется менеджером виртуальной памяти для переключения существующих страниц физической памяти и/или подкачки страниц из файла подкачки.
Может еще раз... 13.02.02 13:17  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Вообще то я считал, что логический это сегмент:смещение
линейный - преобразованый логический
физический - либо логический, либо преобразованый логический

> вот правильный ответ:
> в режиме защиты адреса (бит 0 = 1 в CR0) логический адрес
> является КОРРЕКТНЫМ если он не выходит за предел адреса
> (limit+granularity_bit) установленный в соответствующем
> сегментному индексу дескрипторе.
>
> перед проверкой логического адреса на КОРРЕКТНОСТЬ
> процессор выполнит проверку дескриптора - 1) индекс
> дескриптора (селектор)(сегмент) не может быть равен 0;

Селектор в моем примере не 0.
2) права доступа на дескриптор должны СООТВЕТСТВОВАТЬ (тут
> много нюансов) правам кода т.е. правам дескриптора CS;

Соответствуют

3)> операция с памятью должна допускаться типом данного
> дескриптора;
Допускается

4) переходные эффекты (чтение dword по адресу
> fffffffe etc (не у всех процов))
> в случае ошибки генерируется GeneralProtectionFault или
> (при стековых командах но не всегда) StackFault или
> Double/TripleFault
>
> к логическому адресу прибавляется база дескриптора и
> получается линейный адрес - он же физический если бит 1f =
> 0 в CR0
>
Может к смещению ?
Хорошо, прибавили. Получили... что ? Мы в виндах.

> если установлен режим страничного преобразования адреса
> (бит 1f = 1 в CR0) то происходит преобразование линейного
> адреса в физический по двухуровневой таблице страниц. при
> этом на каждом уровне происходит проверка страницы на
> доступность (бит юзер/супервизор) и присутствие в памяти
> (бит present)
> по неприсутствию всегда генерится PageFault но надо помнить
> что у нее приоритет ОЧЕНЬ низкий и до нее часто генерится
> еще что-нибудь
> по недоступности тоже всегда должна генериться PageFault но
> тут есть процессорозависимые нюансы
>

Так на каком этапе проц генерит эксептион в примере
mov eax, 0
mov [eax], 1

?????
Может еще раз... 14.02.02 01:54  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Вообще то я считал, что логический это сегмент:смещение
> линейный - преобразованый логический
> физический - либо логический, либо преобразованый
> логический

Здесь надо учитывать, что значение в сегментном регистре в реальном и защищенном режимах сильно отличаются: в реальном там хранится сегмент памяти в пределах 1М памяти, а в защищенном - селектор, т.е. смещение в локальной/глобальной таблице дескрипторов.

> > перед проверкой логического адреса на КОРРЕКТНОСТЬ
> > процессор выполнит проверку дескриптора - 1) индекс
> > дескриптора (селектор)(сегмент) не может быть равен 0;

Если честно, не вижу причин, почему бы ему не мочь быть равным нулю. Особенно если таблица дескрипторов локальная.

> Так на каком этапе проц генерит эксептион в примере
> mov eax, 0
> mov [eax], 1

Именно здесь! Делается попытка записи в память в нулевой странице процесса.

>
> ?????
Может еще раз... 14.02.02 14:50  
Автор: z0 <z0> Статус: Member
Отредактировано 14.02.02 15:38  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> Здесь надо учитывать, что значение в сегментном регистре в
> реальном и защищенном режимах сильно отличаются: в реальном
> там хранится сегмент памяти в пределах 1М памяти, а в
> защищенном - селектор, т.е. смещение в локальной/глобальной
> таблице дескрипторов.

значения-то сами могут и не отличаться а вот смысл их конечно разный

>
> > > перед проверкой логического адреса на
> КОРРЕКТНОСТЬ
> > > процессор выполнит проверку дескриптора - 1)
> индекс
> > > дескриптора (селектор)(сегмент) не может быть
> равен 0;
>
> Если честно, не вижу причин, почему бы ему не мочь быть
> равным нулю. Особенно если таблица дескрипторов локальная.

хорошо поправлю себя: старшие 14 битов сегмента/селектора
ты же наверняка знаешь что равный нулю сегмент/селектор относится именно к GDT

по поводу твоего слова "особенно" - вспоминаются дебаты на каком-то западном форуме - фравии что-ли - по поводу ИСПОЛЬЗОВАНИЯ нулевого индекса в GDT. честно сказать кроме того что это удобное место для хранения 8 байт полезной информации я для себя ничего не использовал - да, есть процессорозависимые глюки но и только
я так понимаю интел сделал селектор 0 по аналогии с сишным нулевым указателем - чтобы было чем загрузить неиспользуемый сегментный регистр
Может еще раз... 14.02.02 16:45  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> > Здесь надо учитывать, что значение в сегментном
> регистре в
> > реальном и защищенном режимах сильно отличаются: в
> реальном
> > там хранится сегмент памяти в пределах 1М памяти, а в
> > защищенном - селектор, т.е. смещение в
> локальной/глобальной
> > таблице дескрипторов.
>
> значения-то сами могут и не отличаться а вот смысл их
> конечно разный

Ага, именно это я и хотел сказать.

> по поводу твоего слова "особенно" - вспоминаются дебаты на
> каком-то западном форуме - фравии что-ли - по поводу
> ИСПОЛЬЗОВАНИЯ нулевого индекса в GDT. честно сказать кроме
> того что это удобное место для хранения 8 байт полезной
> информации я для себя ничего не использовал - да, есть
> процессорозависимые глюки но и только
> я так понимаю интел сделал селектор 0 по аналогии с сишным
> нулевым указателем - чтобы было чем загрузить
> неиспользуемый сегментный регистр

Это не совсем очевидно, но мне тоже на ум ничего другого не приходит.
...И еще вопрос. 13.02.02 18:54  
Автор: Chingachguk <Chingachguk> Статус: Member
Отредактировано 13.02.02 18:56  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> Так на каком этапе проц генерит эксептион в примере
> mov eax, 0
> mov [eax], 1 <<< Тута.
> ?????

Вообще-то z0 все уже написал.
Просто хотел дополнить и спросить. Если посмотреть, как выполняется самая простая прога под вин, то вот что видать:

- код начинается ВСЕГДА с смещения 401000h.(возможно, это зависит от компилятора(я имею в виду +1000h));
- если выполнить инструкцию вида:

mov al,ds:[400000h] ; все работает OK

Но вот если выполнить эту:

mov al,ds:[400000h-1] ; То возникает исключение 0Eh - PageFault.

Итак, доступ куда нам дает селектор в ds. Смотрим:

ldt ds ; Выдать описалово на локальный дескриптор(в ds):

Sel ... Base Limit DPL Attr
0167 ... 0000 0000FFFF 3 P RW ED

Я полагаю, используется страничное преобразование линейного адреса.
В данном случае 400000h - это не минимальный физ. адрес, по которому можно читать/писать (это не так, ибо, например Base+Limit меньше+бит гранулярности вроде выставлен).
Пусть используются 4-х килобайтные страницы, тогда физический адрес формируется вроде так:

Биты 12-21 используются как индекс в таблице "базовых" физических адресов, оттуда берем базу, смещение берем(уже в ней) из битов 0-11, биты >=22 - индекс в каталоге страниц.

Я правильно понял ? Ж)
Может еще раз... 13.02.02 14:14  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> Вообще то я считал, что логический это сегмент:смещение
> линейный - преобразованый логический
> физический - либо логический, либо преобразованый
> логический

ну это конечно вопрос терминологии
давай придерживаться чего-то
например:
ЛОГИЧЕСКИЙ - смещение внутри сегмента
ЛИНЕЙНЫЙ - смещение внутри адресного пространства процессора
ФИЗИЧЕСКИЙ - адрес на шине процессора

> Может к смещению ?
> Хорошо, прибавили. Получили... что ? Мы в виндах.

значит прибавили 0

> Так на каком этапе проц генерит эксептион в примере
> mov eax, 0
> mov [eax], 1
>
> ?????

1) CPU: DS <> 0 CPU: Ok
2) CPU: PL (DS) >= PL (CS) CPU: Ok
3) CPU: DS writable CPU: Ok
4) CPU: eax < segment_size CPU: Ok
5) CPU: segment_size-eax >= operator_size CPU: Ok
eax=eax+0 пропускаем вижу что тебе это понятно
6) CPU: page_table_directory(eax).[bit_present] CPU: Ok
7) CPU: page_table_directory(eax).[bit_user] CPU: Ok
8) CPU: page_table(page_table_directory(eax)).[bit_present] CPU: No
9) CPU: exception(PageFault, Address)
10) OS: check_page_user_rights(Process, Address) OS:NoAccess
11) OS: RaiseException(AccessViolation, Process, Address)
12) OS: Kill(Process)

то что от ОС зависит - это для виндов (смотрел в НТ)
для линуха может ты нам расскажешь
думаю приблизительно так же
в linux точно также 13.02.02 16:04  
Автор: ukv Статус: Незарегистрированный пользователь
<"чистая" ссылка> <обсуждение закрыто>
И в виндах, и в линуксе изрядная часть защиты сделана не на уровне сегментов, а на уровне страниц. Сегментация фактически подавляется. Неявно предполагается, что приложение работает в flat-модели, ds и cs адресуют все 4 Гб одного и того же виртуального адресного пространства. На уровне страничной организации в этом пространстве будут в основном лакуны - и в частности нулевая страница. Неприсутствие нулевой страницы в памяти - просто черта операционок - для отлова ошибок обращения по нулевому указателю. Ну а из тех страниц, которые в адресном пространстве есть - некоторые могут быть защищены от записи (и тогда, например, можно отображать одну физическую копию ядра в адесное пространство всех процессов сразу). С точки зрения сегментов все выглядит нормально - сегмент есть (на все 4Гб), и запись в него вроде бы разрешена, а модифицировать ядро не получится - не позволит менеджер страниц.
почему нельзя? 12.02.02 21:56  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> Мы же не в реальном режиме, где эти адреса забиты под
> прерывания.
> Итак, почему эксептион ?

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

code32 segment use32 para private 'code'
assume cs:code32
assume ds:data32
entry_point:
call check_OS
cmp eax,WIN9X
jne exit
call goto_ring0
call set_page0_present_and_user
call goto_ring3
mov eax,0
mov [eax],3 ; no exception
call goto_ring0
call restore_all_hacked_above
call goto_ring3
exit:
push dword 0
call ExitProcess

code32 ends

data32 segment use32 para private 'data'
db 'some data here'
data32 ends

end entry_point

почему нельзя? можно...
Можете меня штрафовать, но я спрошу 12.02.02 21:45  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Почему нельзя писать по нулю ?
> Только не бейте ногами !
> Итак:
> mov eax, 0
> mov [eax], 3
>
> Последняя инструкция эквивалентна mov DS:[eax], 3
> Все было бы прекрасно, если бы DS содержал 0 селектор,
> тогда бы исключение было бы понятным, но DS содержит не
> нулевой селектор. А в сегменте я могу смещатся на столько
> на сколько мне позволяет его длинна. Хоть на 0, хоть на 1.
> Мы же не в реальном режиме, где эти адреса забиты под
> прерывания.
> Итак, почему эксептион ?

Чтобы легче было отлавливать ошибки в программах, связанные с неинициализированными указателями, Винда запрещает обращение к адресам из первой страницы адресного пространства процесса.
Все указатели сегментов указывают на одно и то же адресное пространство. Т.е. CS:0 и DS:0 указывают на одну и ту же ячейку памяти, которая находится по адресу 0.
Из-за этого ЛЮБЫЕ обращения процесса к адресам в первой странице, не важно, что это за обращение: выполнение кода, стек, данные - возникает исключение Access violation.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach