Время проверки, время использования, связанные с доступом (), faccessat(), stat(), lstat(), fstat(), open() и fopen()

Я не часто пишу здесь, поэтому терпите меня, пока я пытаюсь решить, как решить эту проблему.

Я обновляю кодовую базу, которая не менялась в течение 10 - 20 лет. Кодекс был написан без соблюдения передового опыта и многими авторами, иногда с неполным пониманием соглашений о безопасности, или, возможно, даже до того, как эти соглашения стали обычной практикой. Компилятор, используемый в этом коде, это C++98 или C++03, но не более новый. Код также кросс-платформенный между Linux и Windows.

Все это говорит о том, что мне нужна помощь некоторых ветеранов C++, которые понимают, как правильно использовать access (), stat () и open (), и их извращения в том, что касается проблем TOCTOU.

Вот пример блока кода, иллюстрирующего проблему TOCTOU:

#ifdef WIN32
    struct _stat buf;
#else
    struct stat buf;
#endif //WIN32

    FILE *fp;
    char data[2560];

    // Make sure file exists and is readable
#ifdef WIN32
    if (_access(file.c_str(), R_OK) == -1) {
#else
    if (access(file.c_str(), R_OK) == -1) {
#endif //WIN32

        /* This is a fix from a previous 
           Stack-based Buffer Overflow
           issue.  I tried to keep the original
           code as close to possible while
           dealing with the potential security
           issue, as I can't be certain of how
           my change might effect the system. */

        std::string checkStr("File ");
        checkStr += file.c_str();
        checkStr += " Not Found or Not Readable";
        if(checkStr.length() >= 2560)
            throw checkStr.c_str();

        char message[2560];
        sprintf(message, "File '%s' Not Found or Not Readable", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
        }

    // Get the file status information
#ifdef WIN32
    if (_stat(file.c_str(), &buf) != 0) {
#else
    if (stat(file.c_str(), &buf) != 0) {
#endif //WIN32

        /* Same story here. */

        std::string checkStr("File ");
        checkStr += file.c_str();
        checkStr += " No Status Available";
        if(checkStr.length() >= 2560)
            throw checkStr.c_str();

        char message[2560];
        sprintf(message, "File '%s' No Status Available", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
        }

    // Open the file for reading
    fp = fopen(file.c_str(), "r");
    if (fp == NULL) {
        char message[2560];
        sprintf(message, "File '%s' Cound Not be Opened", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
    }

    // Read the file
    MvString s, ss;
    while (fgets(data, sizeof(data), fp) != (char *)0) {
        s = data;
        s.trimBoth();
        if (s.compare( 0, 5, "GROUP" ) == 0) {
            //size_t t = s.find_last_of( ":" );
            size_t t = s.find( ":" );
            if (t != string::npos) {
                ss = s.substr( t+1 ).c_str();
                ss.trimBoth();
                ss = ss.substr( 1, ss.length() - 3 ).c_str();
                group_list.push_back( ss );
            }
        }
    }

    // Close the file
    fclose(fp);
}

Как вы можете видеть, предыдущий разработчик (и) хотел убедиться, что пользователь имеет доступ к "файлу", статистическому "файлу", а затем открыл его без повторного доступа () - без и re-stat (). -ing "файл" после fopen()- это. Я понимаю, почему это проблема TOCTOU, но я не уверен, как ее исправить.

Из того, что я исследовал, open () предпочтительнее, чем fopen () и fstat (), а не stat (), но где подходит lstat ()? и если я делаю статистику, мне вообще нужен access () или faccessat()?

И в дополнение к этому, это должно быть совместимо с компилятором Windows, и я обнаружил, что статьи говорят, что fopen () лучше, потому что он кроссплатформенный, а open () нет, что делает open () потенциально непригодным; это также, кажется, то же самое для вариаций stat () и access (), но я не уверен.

Если вы зашли так далеко, спасибо, что прочитали все это, и я приветствую любую критику по поводу поста и помощь.

0 ответов

Другие вопросы по тегам