c - stat(), fstat(), lstat(), and fopen(); how to write TOCTOU protected system independent code -


i've been dealing problem few weeks updating 20 year code needs system independent (work on both linux , windows). involves time-of-check, time-of-use (toctou) issues. made thread here, didn't go far, , after ruminating on while , searching deeper problem, think understand question bit better. maybe can ask bit better too...

from i've read, code needs check if file exists, if accessible, open file, operations , close file. seems best way call lstat(), call fopen(), call fstat() (to rule out toctou), , operations , closing file.

however, i've been lead believe lstat() , fstat() posix defined, not c standard defined, ruling out use system agnostic program, in same way open() shouldn't used cross-compatibility. how implement this?

if at first post, can see developer 20 years ago used c preprocessor cut code cross-compatible parts, if did that, wouldn't know replace lstat() or fstat() (their windows counterparts).

edit: added abreviated code post; if unclear please go original post

#ifdef win32     struct _stat buf; #else     struct stat buf; #endif //win32      file *fp;     char data[2560];      // make sure file exists , readable #ifdef win32     if (_access(file.c_str(), r_ok) == -1) { #else     if (access(file.c_str(), r_ok) == -1) { #endif //win32          char message[2560];         sprintf(message, "file '%s' not found or not readable", file.c_str());         throw message;         }      // file status information #ifdef win32     if (_stat(file.c_str(), &buf) != 0) { #else     if (stat(file.c_str(), &buf) != 0) { #endif //win32          char message[2560];         sprintf(message, "file '%s' no status available", file.c_str());         throw message;         }      // open file reading     fp = fopen(file.c_str(), "r");     if (fp == null) {         char message[2560];         sprintf(message, "file '%s' cound not opened", file.c_str());         throw message;     }      // read 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 file     fclose(fp); } 

the reliable way check whether file exists , can opened try opening it. if opened, ok. if not opened, can think spending time analyze went wrong.

the access() function formally asks different question think; asks 'can real user id or real group id access file', program use effective user id or effective group id access file. if program not running suid or sgid, , not launched program running suid or sgid — , that's normal case — there's no difference. question different.

the use of stat() or lstat() doesn't seem helpful. in particular, lstat() tells whether start @ symlink, code doesn't care that.

both access() , stat() calls provide toctou windows of vulnerability; file removed after reported present, or created after reported absent.

you should call fopen() , see whether works; code simpler , more resistant toctou problems. might need consider whether use open() controls (o_excl, etc), , convert file descriptor file pointer (fdopen()).

all of applies unix side.

the details different, on windows side, still best off trying open file , reacting appropriately failure.

in both systems, make sure options provided open function appropriate.


Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -