2010-05-26 3 views
1

Я хотел был бы безопасно смоделировать open с O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW и O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW на системах, которые не поддерживают O_NOFOLLOW. Я могу несколько добиться того, о чем я прошу:Что такое хороший способ моделирования O_NOFOLLOW на системах без этого флага?

struct stat lst; 
if (lstat(filename, &lst) != -1 && S_ISLNK(lst.st_mode)) { 
    errno = ELOOP; 
    return -1; 
} 

mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, mode); 

, но затем я представляю состояние гонки и, возможно, проблему безопасности.

Я думал о том, может создать фиктивный файл только пользователь будучи в состоянии писать, вроде как touch ИНГ filename, делая lstat чек, а затем с помощью chmod после того как я закончу писать (исправить биты режима файла), но я мог бы игнорировать что-то важное (например, если файл в filename существует, не является обычным файлом или уже является символической ссылкой).

Как вы думаете?

ответ

4

Ваше предложение по-прежнему имеет состояние гонки:

  • Мэллори создает ссылку, он хочет, чтобы вы следовали;
  • Вы open() ссылка с O_CREAT;
  • Mallory заменяет ссылку на обычный файл;
  • Вы выполняете свой тест lstat(), который проходит (не ссылку);
  • Мэллори снова заменяет обычный файл ссылкой.

Вы можете исправить это за не- O_TRUNC случае, вызвав fstat() на вашем дескриптора открытого файла, а также lstat() на пути, и обеспечить, чтобы .st_dev и .st_ino члены одинаковы.

Однако это не сработает, если вы используете O_TRUNC - к тому времени, как вы обнаружили обман, уже слишком поздно - Мэллори уже побуждал вас обрезать один из ваших важных файлов.

Я считаю, что традиционный способ устранить отверстие без поддержки O_NOFOLLOW является:

  • Создайте временный каталог с режимом 700. Ошибка (или повторная попытка), если mkdir() сбой из-за существующей директории;
  • Создайте новый файл во временном каталоге;
  • Использовать rename() для физического перемещения временного файла на целевое имя;
  • Удалить временный каталог.