Linux Kernel (Ядро линукса) (часть 2)


Анализ символьных ссылок

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

Если, например, /foo/bar является символьной ссылкой, указывающей на ./dir (то есть содержащей этот путь), то путь /foo/bar/file должен быть интерпретирован ядром как ссылка на файл dir/filе/. В этом примере ядро выполнит две операции анализа. Первая обработает /foo/bar. Когда ядро обнаружит, что bar является именем символьной ссылки, оно должно будет прочитать ее содержимое и интерпретировать его как самостоятельный путь. Вторая операция анализа пути начнется с каталога, до которого дошла первая операция, и продолжится, пока не будет определен последний элемент пути в символьной ссылке. Затем первая операция анализа возобновляется с элемента каталога, достигнутого второй операцией, с компонентом, следующим за символьной ссылкой в оригинальном пути.

Ситуацию осложняет то обстоятельство, что путь, включенный в символьную ссылку, может содержать другие символьные ссылки. Вы, возможно, подумали, что код ядра, разрешающий символьные ссылки, сложен для понимания, но это не так. На самом деле, код вполне прост, потому что рекурсивен.
Однако неконтролируемая рекурсия потенциально опасна. Например, предположим, что символьная ссылка указывает сама на себя. Естественно, анализ пути, содержащего такую символьную ссылку, может породить бесконечный поток рекурсивных вызовов, что быстро приведет к переполнению стека ядра. Поле link count дескриптора текущего процесса служит для предотвращения этой проблемы. Оно увеличивается перед каждым рекурсивным вызовом и уменьшается сразу после него. Если будет предпринята попытка шестой вложенной операции анализа, вся операция прерывается с кодом ошибки. Таким образом, уровень вложенности символьных ссылок не может быть больше 5.

Более того, поле totai iink count дескриптора текущего процесса отслеживает количество символьных ссылок (даже невложенных), по которым проследовала операция анализа оригинального пути. Если этот счетчик дойдет до 40, операция анализа прерывается. Без такого счетчика злонамеренный пользователь смог бы создать патологический путь, содержащий много последовательных символьных ссылок, и подвесить” работу ядра с помощью очень длинной операции анализа пути.

В принципе, код работает следующим образом: после того, как функция link path waiko прочитает объект элемент каталога”, связанный с компонентом пути, она проверит, есть ли у соответствующего индексного дескриптора собственный метод foiiow iink. Если это так, значит, индексный дескриптор является символьной ссылкой, которая должна быть интерпретирована прежде, чем операция анализа оригинального пути будет продолжена.

В ЭТОМ Случае фуНКЦИЯ link_path_walkO ВЫЗЫВаеТ фунКЦИЮ do_follow_ link , передавая ей адрес dentry объекта элемент каталога”, представляющего символьную ссылку, и адрес nd структуры nameidata. В свою очередь, функция do foiiow iink выполняет следующие действия:
1. Убеждается, что current->iink_count меньше 5. В противном случае возвращает КОД ошибки -ELOOP.
2. Убеждается, что current->totai_iink_count меньше 40. В противном случае возвращает код ошибки -eloop.
3. Вызывает cond resched для переключения процессов, если этого требует текущий процесс (флаг tif need resched в дескрипторе thread info текущего процесса установлен).
4. Увеличивает счетчики current->link_count, current->total_link_count И nd->depth.
5. Обновляет время обращения к объекту индексный дескриптор”, связанному с символьной ссылкой, требующей интерпретации.
6. Вызывает специфичную для файловой системы функцию, реализующую метод foiiow iink, передавая ей параметры dentry и nd. Эта функция извлекает путь, содержащийся в индексном дескрипторе символьной ссылки, и сохраняет этот путь в соответствующем элементе массива nd-> saved_names.
7. Вызывает функцию vfs foiiow iinkO, передавая ей адрес nd и адрес
пути В массиве nd->saved_names.
8. Если метод put iink объекта индексный дескриптор” определен, выполняет его, освобождая таким образом временные структуры данных, выделенные методом foiiow iink.
9. Уменьшает значения полей current->link_count И nd->depth.
10. Возвращает код ошибки, возвращенный функцией vfs foiiow iinkO
(ноль, если ошибок не было).

Со своей стороны, функция vfs foiiow iinkO выполняет следующие действия:
1. Проверяет, является ли косой чертой первый символ пути, содержащегося в символьной ссылке. Если это так, значит, обнаружен абсолютный путь, и нет необходимости держать в памяти информацию о предыдущем пути.
Тогда функция вызывает path_release ДЛЯ структуры nameidata, тем са- мым освобождая объекты, полученные на предыдущих шагах анализа. Затем она устанавливает поля dent г у и mnt структуры данных так, чтобы они соответствовали корневому каталогу текущего процесса.
2. Вызывает функцию iink_path_waik для обработки пути символьной ссылки, передавая путь и nd в качестве параметров.
3. Возвращает значение, полученное от link path waik.

Когда do_foiiow_iink() заканчивает выполнение, в поле dentry локальной переменной next находится адрес объекта "элемент каталога”, на который указывает символьная ссылка. Это сделано специально для вызвавшей функции link path waik , которая теперь может переходить к следующему шагу.

Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | Следующая страница




Возможно, Вас также заинтересует:

ОС Knoppix - это Linux без про...

ВведениеЕсли вы цените свое время, умеете считать деньги и знаете стоимость информации, то эта книга...

Linux Kernel (Ядро линукса) (ч...

Спин-блокировкаСпин-блокировка необходима в многопроцессорной системе, потому что могут возникнуть...

Linux Kernel (Ядро линукса) (ч...

Копирование при записи В системах Unix первых поколений создание процесса было реализовано довольно...

Linux Kernel (Ядро линукса) (ч...

Буферы блоков и головы буферовУ каждого буфера есть дескриптор голова буфера, имеющий тип buffer...