Каков хороший способ имитации O_NOFOLLOW в системах без этого флага? - PullRequest
1 голос
/ 27 мая 2010

Я бы хотел безопасно смоделировать open с O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW и O_CREAT | O_WRONLY | O_APPEND | 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 ing filename, выполнить проверку lstat, а затем использовать chmod после завершения записи исправьте биты режима файла), но я мог пропустить что-то важное (например, если файл в filename существует, не является обычным файлом или уже является символической ссылкой).

Что вы думаете?

1 Ответ

4 голосов
/ 27 мая 2010

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

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

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

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

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

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