Файл: Debian Таненбаум Бос.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Операционные системы

Добавлен: 29.10.2018

Просмотров: 48213

Скачиваний: 190

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

10.6. Файловая система UNIX   

871

каталогом) и получает обратно описатель файла для него. Он создает в своих таблицах 
r-узел для удаленного файла и докладывает об этом уровню VFS, который помещает 
в свои таблицы v-узел для файла, указывающий на r-узел. Мы видим, что и в этом случае 
у каждого открытого файла (или каталога) есть v-узел, указывающий на r-узел или i-узел.

Вызывающей стороне выдается дескриптор удаленного файла. Этот дескриптор файла 
отображается на v-узел при помощи таблиц уровня VFS. Обратите внимание на то, что 
на сервере не создается никаких записей в таблицах. Хотя сервер готов предоставить 
описатели файлов по запросу, он не следит за состоянием описателей файлов. Когда 
описатель файла присылается серверу для доступа к файлу, сервер проверяет описатель 
и использует его (если описатель достоверный). При проверке достоверности может 
проверяться ключ аутентификации, содержащийся в заголовках вызова удаленной 
процедуры RPC (если включена система безопасности).

Когда дескриптор файла используется в последующем системном вызове (например, 
read), то уровень VFS находит соответствующий v-узел и по нему определяет, является 
он локальным или удаленным, а также какой i-узел или r-узел его описывает. Затем он 
посылает серверу сообщение, содержащее описатель, смещение в файле (хранящееся 
на стороне клиента, а не сервера) и количество байтов. Для повышения эффективности 
обмен информацией между клиентом и сервером выполняется большими порциями — 
как правило, по 8192 байта (даже если запрашивается меньшее количество байтов).

Когда сообщение с запросом прибывает на сервер, оно передается там уровню VFS, 
который определяет локальную файловую систему, содержащую запрошенный файл. 
Затем уровень VFS обращается к этой файловой системе, чтобы прочитать и вернуть 
байты. Эти данные затем передаются клиенту. После того как уровень VFS клиента 
получил запрошенную им порцию данных размером 8 Кбайт, он автоматически по-
сылает запрос на следующую порцию, чтобы она была под рукой, если понадобится. 
Эта функция, называемая опережающим чтением (read ahead) , позволяет значительно 
увеличить производительность.

При записи проходится аналогичный путь от клиента к серверу. Данные также переда-
ются порциями по 8 Кбайт. Если системный вызов write подает менее 8 Кбайт данных, 
то данные просто накапливаются локально. Только когда вся порция в 8 Кбайт готова, 
она посылается серверу. Однако если файл закрывается, то все его данные немедленно 
посылаются серверу.

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

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

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


background image

872  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

ется на 3 с, а для блоков каталога — на 30 с. Таким образом, риск несколько снижается. 
Кроме того, при каждом открытии кэшированного файла серверу посылается сообще-
ние, чтобы определить, когда в последний раз был модифицирован этот файл. Если 
последняя модификация произошла после того, как была сохранена в кэше локальная 
копия файла, то эта копия из кэша удаляется, а с сервера доставляется новая копия. На-
конец, каждые 30 с истекает таймер кэша и все «грязные» (модифицированные) блоки 
кэша посылаются на сервер. Хотя такая схема и далека от совершенства, подобные «за-
платки» позволяют использовать эту систему для большинства практических случаев.

Версия NFS 4

Версия 4 файловой системы Network File System была спроектирована для упрощения 
(по сравнению со своей предшественницей) некоторых операций. В отличие от описан-
ной ранее NFSv3, версия NFSv4 является файловой системой с сохранением состояния. 
Это позволяет выполнять операции open с удаленными файлами, поскольку сервер NFS 
поддерживает все файловые структуры (в том числе указатель файла). Поэтому для 
операций чтения не нужно указывать абсолютный диапазон, их можно выполнять 
с предыдущего положения указателя файла. Это приводит к более коротким сообще-
ниям, а также к возможности группировать операции NFSv3 в сетевые транзакции.

Имеющееся в NFSv4 сохранение состояния облегчает интеграцию всех описанных 
ранее протоколов NFSv3 в один согласованный протокол. Нет необходимости под-
держивать отдельные протоколы для монтирования, кэширования, блокировки и без-
опасных операций. NFSv4 также лучше работает с семантиками файловых систем как 
в Linux, так и в Windows.

10.7. Безопасность в Linux

Linux (как клон MINIX и UNIX) была многопользовательской системой почти с само-
го начала. Это значит, что безопасность и контроль над информацией были встроены 
в систему на очень ранней стадии. В следующих разделах мы рассмотрим некоторые 
аспекты безопасности операционной системы Linux  .

10.7.1. Фундаментальные концепции

Сообщество пользователей операционной системы Linux состоит из зарегистриро-
ванных пользователей, каждый из которых имеет уникальный UID  (User ID — иден-
тификатор пользователя ). UID представляет собой целое число в пределах от 0 до 
65 535. Идентификатором владельца помечаются файлы, процессы и другие ресурсы. 
По умолчанию владельцем файла является пользователь, создавший этот файл (хотя 
есть способ сменить владельца).

Пользователи могут организовываться в группы, которые также нумеруются 16-бит-
ными целыми числами, называемыми GID  (Group ID — идентификатор группы ). На-
значение пользователя в группу выполняется вручную системным администратором 
и заключается в создании нескольких записей (в системной базе данных), в которых 
содержится информация о том, какой пользователь к какой группе принадлежит. 
Пользователь может одновременно принадлежать к нескольким группам. Чтобы не 
усложнять вопрос, мы более не станем обсуждать эту возможность.


background image

10.7. Безопасность в Linux   

873

Основной механизм безопасности в операционной системе Linux прост. Каждый про-
цесс несет на себе UID и GID своего владельца. Когда создается файл, он получает 
UID и GID создающего его процесса. Файл также получает набор разрешений доступа, 
определяемых создающим процессом. Эти разрешения определяют доступ к этому 
файлу для владельца файла, для других членов группы владельца файла и для всех 
прочих пользователей. Для каждой из этих трех категорий определяется три вида до-
ступа: чтение, запись и исполнение файла, что обозначается буквами rw и x (readwrite
execute) соответственно. Возможность исполнять файл, конечно, имеет смысл только 
в том случае, если этот файл является исполняемой двоичной программой. Попытка 
запустить файл, у которого есть разрешение на исполнение, но который не является 
исполняемым (то есть он не начинается с соответствующего заголовка), закончится 
ошибкой. Поскольку существуют три категории пользователей и три бита для каждой 
категории, все режимы доступа к файлу можно закодировать 9 битами. Некоторые 
примеры этих 9-битных чисел и их значения показаны в табл. 10.14.

Таблица 10.14. Примеры режимов защиты файлов

Двоичное

Символьное

Разрешенный доступ

111000000

rwx------

Владелец может читать, писать и исполнять

111111000

rwxrwx---

Владелец и группа могут читать, писать и исполнять

110100000

rw-r-----

Владелец может читать и писать, группа может читать

110100100

rw-r--r--

Владелец может читать и писать, все остальные могут читать

111101101

rwxr-xr-x

Владелец имеет все права, все остальные могут читать 
и исполнять

000000000

---------

Ни у кого нет доступа

000000111

------rwx

Только у посторонних есть доступ (странно, но допустимо)

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

Пользователь, UID которого равен 0, является особым пользователем и называется 
суперпользователем 

 (superuser или root ). Суперпользователь может читать и писать 

все файлы в системе независимо от того, кто ими владеет и как они защищены. Про-
цессы с UID = 0 также имеют возможность использовать небольшую группу защи-


background image

874  

 Глава 10. Изучение конкретных примеров: Unix, Linux и Android 

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

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

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

/dev/lp

 может быть суперпользователь (root) или специальный поль-

зователь — демон принтера. При этом режим доступа к файлу может быть установлен 
равным rw-------, чтобы все остальные пользователи не могли напрямую обращаться 
к принтеру. В противном случае при одновременной печати на принтере из нескольких 
процессов получился бы полный хаос.

Тот факт, что файлом 

/dev/lp

 владеет демон и этот файл имеет режим доступа rw-------

означает, что больше никто не может использовать принтер. Такой способ, конечно, 
позволяет множеству невинных деревьев избежать преждевременной смерти, однако 
время от времени пользователям бывает необходимо что-то напечатать. В действитель-
ности существует более общая проблема управляемого доступа ко всем устройствам 
ввода-вывода и другим системным ресурсам.

Эта проблема была решена с помощью добавления к перечисленным выше 9 битам 
нового бита защиты, бита SETUID  . Когда выполняется программа с установленным 
битом SETUID, то рабочим UID (effective UID) этого процесса становится не UID 
вызвавшего его пользователя, а UID владельца исполняемого файла. Когда процесс 
пытается открыть файл, то проверяется его рабочий UID , а не действительный UID. 
Таким образом, если программой, обращающейся к принтеру, будет владеть демон 
с установленным битом SETUID, то любой пользователь сможет запустить ее и полу-
чить полномочия демона (например, права доступа к 

/dev/lp

), но только для запуска 

этой программы (которая может ставить задания в очередь на принтер).

В операционной системе UNIX есть множество важных программ, владельцем которых 
является суперпользователь, но у них установлен бит SETUID. Например, программе 
passwd, позволяющей пользователям менять свои пароли, требуется доступ на запись 
в файл паролей. Если разрешить изменять этот файл кому угодно, то ничего хорошего 
не получится. Вместо этого есть программа, владельцем которой выступает root, и у 
файла этой программы установлен бит SETUID. Хотя у этой программы есть полный 
доступ к файлу паролей, она изменит только пароль вызвавшего ее пользователя и не 
даст доступа к остальному содержимому файла.

Помимо бита SETUID есть также еще и бит SETGID, который работает аналогично 
и временно предоставляет пользователю рабочий GID программы. Однако на практике 
этот бит используется редко.


background image

10.7. Безопасность в Linux   

875

10.7.2. Системные вызовы безопасности в Linux

Лишь небольшое число системных вызовов относятся к безопасности . Самые важные 
системные вызовы перечислены в табл. 10.15. Чаще всего используется системный вы-
зов chmod. С его помощью можно изменить режим защиты файла. Например, оператор

s = chmod("/usr/ast/newgame", 0755);

устанавливает для файла 

newgame

 режим доступа rwxr-xr-x, что позволяет запускать 

эту программу всем пользователям (обратите внимание на то, что 0755 представляет 
собой восьмеричную константу, что удобно в данном случае, так как биты защиты 
группируются по три). Изменять биты защиты могут только владелец файла и супер-
пользователь.

Таблица 10.15. Некоторые системные вызовы, относящиеся к безопасности. Если 
произошла ошибка, то код возврата s равен –1; uid и gid — это, соответственно, UID 
и GID. Параметры должны быть понятны без пояснений

Системный вызов

Описание

s=chmod(path, mode)

Изменить режим защиты файла

s=access(path, mode)

Проверить разрешение доступа к файлу, используя 
действительные UID и GID

uid=getuid( )

Получить действительный UID

uid=geteuid( )

Получить рабочий UID

gid=getgid( )

Получить действительный GID

gid=getegid( )

Получить рабочий GID

s=chown(path, owner, group)

Изменить владельца и группу

s=setuid(uid)

Установить UID

s=setgid(gid)

Установить GID

Системный вызов access проверяет, будет ли разрешен определенный тип доступа при 
заданных действительных UID и GID. Этот системный вызов нужен, чтобы избежать 
появления брешей в системе безопасности в программах с установленным битом 
SETUID, владельцем которых является root. Такие программы могут выполнять любые 
действия, поэтому им иногда бывает необходимо определить, разрешено ли вызвавше-
му их пользователю выполнение определенных действий. Программа не может просто 
попытаться получить требуемый доступ, так как любой доступ ей будет обязательно 
предоставлен. При помощи вызова access программа может определить, разрешен ли 
доступ реальному UID и реальному GID.

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

10.7.3. Реализация безопасности в Linux

Когда пользователь регистрируется в системе, то программа login (которая имеет 
SETUID root) запрашивает у пользователя его имя и пароль. Затем она хэширует 
пароль и ищет его в файле паролей 

/etc/passwd

, чтобы определить, соответствует ли