П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 176978 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 74138 раз(а).

Учебник HTML.
Просмотров 73315 раз(а).

Руководство по PHP5.
Просмотров 44196 раз(а).

Хостинг через призму DNS.
Просмотров 50882 раз(а).

Подборка текстов стандартных документов.
Просмотров 44368 раз(а).

Учебник PHP - Самоучитель
Просмотров 50614 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 51031 раз(а).

Внешние атаки...
Просмотров 41344 раз(а).

Учебник PHP.
Просмотров 36570 раз(а).

SSI в примерах.
Просмотров 27442 раз(а).






 
 
| Добавить в избранное | Сделать стартовой Project.Net.Ru | Помощь




Возможное усовершенствование

Проблема, которая обсуждалась выше, основана на возможности изменить характеристики объекта в промежуток времени между двумя операциями, не трогая остального. В предыдущей ситуации изменение не касалось самого файла. Между прочим, обычному пользователю, было бы достаточно сложно изменить или даже прочитать файл /etc/shadow. Фактически, изменение касалось связи между существующей файловой записью в дереве имен и самим файлом, как физической сущностью. Вспомним, что большинство системных команд (rm, mv, ln и т.д.) воздействуют на имя файла, а не на его содержимое. Даже если вы удаляете файл (используя rm и системный вызов unlink()), по-настоящему сожержимое его удаляется, когда последняя физическая связь - последняя жесткая ссылка - будет удалена.

Ошибка, которая была сделана в предыдущей программе, происходит из-за того, что мы полагали, что ассоциация между именем файла и его содержимым неизменна, или, как минимум, постоянна в промежуток времени между операциями stat() и fopen(). Примера жесткой ссылки достаточно, чтобы удостовериться, что это соответствие совсем не постоянно. Приведем пример, используя такой тип ссылок. В директории, которая принадлежит нам, мы создаем новую ссылку на системный файл. Естественно, владелец и права доступа к файлу сохраняются. Опция -f команды ln заставляет сделать ссылку даже если имя уже существует:

$ ln -f /etc/fstab ./myfile
$ ls -il /etc/fstab myfile
8570 -rw-r--r--   2 root  root  716 Jan 25 19:07 /etc/fstab
8570 -rw-r--r--   2 root  root  716 Jan 25 19:07 myfile
$ cat myfile
/dev/hda5   /                 ext2    defaults,mand   1 1
/dev/hda6   swap              swap    defaults        0 0
/dev/fd0    /mnt/floppy       vfat    noauto,user     0 0
/dev/hdc    /mnt/cdrom        iso9660 noauto,ro,user  0 0
/dev/hda1   /mnt/dos          vfat    noauto,user     0 0
/dev/hda7   /mnt/audio        vfat    noauto,user     0 0
/dev/hda8   /home/ccb/annexe  ext2    noauto,user     0 0
none        /dev/pts          devpts  gid=5,mode=620  0 0
none        /proc             proc    defaults        0 0
$ ln -f /etc/host.conf ./myfile
$ ls -il /etc/host.conf myfile 
8198 -rw-r--r--   2 root  root   26 Mar 11  2000 /etc/host.conf
8198 -rw-r--r--   2 root  root   26 Mar 11  2000 myfile
$ cat myfile
order hosts,bind
multi on
$

Опция -i команды /bin/ls выводит номер индексного дескриптора в начале строки. Мы видим, что одно имя указывает на различные физические индексные дескрипторы. Между прочим, ясно, что обе команды "cat", обрабатывая одно и то же имя файла, выводят два совершенно различных результата, тем не менее никакие изменения не вносились в эти файлы между двумя операциями.

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

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

Итак мы имеем наше решение! Мы можем открыть файл, а затем проверять права доступа, изучая характеристики дескриптора, а не какого-то имени файла. Это можно сделать используя системный вызов fstat() (работает так же как и stat()), который проверяет файловый дескриптор, а не путевое имя. Чтобы получить доступ к содержимому файла, используя дескриптор, мы будем использовать функцию fdopen() (которая работает так же как и fopen()), так как она использует дескриптор, а не имя файла. Вот какая получается программа:

1    /* ex_02.c */
2    #include <fcntl.h>
3    #include <stdio.h>
4    #include <stdlib.h>
5    #include <unistd.h>
6    #include <sys/stat.h>
7    #include <sys/types.h>
8
9     int
10    main (int argc, char * argv [])
11    {
12        struct stat st;
13        int fd;
14        FILE * fp;
15
16        if (argc != 3) {
17            fprintf (stderr, "использование : %s файл сообщение\n", argv [0]);
18            exit(EXIT_FAILURE);
19        }
20        if ((fd = open (argv [1], O_WRONLY, 0)) < 0) {
21            fprintf (stderr, "Невозможно открыть %s\n", argv [1]);
22            exit(EXIT_FAILURE);
23        }
24        fstat (fd, & st);
25        if (st . st_uid != getuid ()) {
26            fprintf (stderr, "%s не владелец !\n", argv [1]);
27            exit(EXIT_FAILURE);
28        }
29        if (! S_ISREG (st . st_mode)) {
30            fprintf (stderr, "%s не является обычным файлом\n", argv[1]);
31            exit(EXIT_FAILURE);
32        }
33        if ((fp = fdopen (fd, "w")) == NULL) {
34            fprintf (stderr, "Невозможно открыть\n");
35            exit(EXIT_FAILURE);
36        }
37        fprintf (fp, "%s", argv [2]);
38        fclose (fp);
39        fprintf (stderr, "Запись сделана\n");
40        exit(EXIT_SUCCESS);
41    }

Теперь, после строки 20, никакое изменение имени файла (удаление, переименование, создание ссылки) не окажет влияния на поведение нашей программы; содержимое исходного физического файла будет сохранятся.

Назад | Содержание | Вперед



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
 





Copyright © 2005-2016 Project.Net.Ru