Какой хороший способ симулировать O_NOFOLLOW на системах без этого флага?

StackOverflow https://stackoverflow.com/questions/2917395

Вопрос

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

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

Это было полезно?

Решение

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

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

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

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

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

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