...
| Code Block | ||
|---|---|---|
| ||
if (!fgets(file namefilename, sizeof(file namefilename), stdin)) { /* handle error */ } if (open(file namefilename, O_WRONLY) == -1) { /* handle error */ } |
...
| Code Block | ||
|---|---|---|
| ||
#ifdef O_NOFOLLOW #define OPEN_FLAGS O_NOFOLLOW | O_NONBLOCK #else #define OPEN_FLAGS O_NONBLOCK #endif /* ... */ struct stat orig_st; struct stat open_st; int fildes; int flags; if (!fgets(file namefilename, sizeof(file namefilename), stdin)) { /* handle error */ } if ((lstat(file namefilename, &orig_st) != 0) || (!S_ISREG(orig_st.st_mode))) { /* handle error */ } /* A TOCTOU race condition exists here, see below */ if ((fildes = open(file namefilename, OPEN_FLAGS | O_WRONLY)) == -1) { /* handle error */ } if (fstat(fildes, &open_st) != 0) { /* handle error */ } if ((orig_st.st_mode != open_st.st_mode) || (orig_st.st_ino != open_st.st_ino) || (orig_st.st_dev != open_st.st_dev)) { /* file was tampered with */ } /* Optional: drop the O_NONBLOCK now that we are sure * this is a good file */ if ((flags = fcntl(fildes, F_GETFL)) == -1) { /* handle error */ } if ((fcntl(fildes, F_SETFL, flags & ~O_NONBLOCK) != 0) { /* handle error */ } /* operate on file */ |
The above code does contain an intractable TOCTOU race condition; where an attacker could alter the file referenced by file name filename following the call to lstat() but before the call to open(). The switch will be discovered after the file is opened, but opening the file cannot be prevented in the case where this action itself causes undesired behavior.
...
| Wiki Markup |
|---|
\[[Garfinkel 96|AA. C References#Garfinkel 96]\] Section 5.6, "Device Files" \[[Howard 02|AA. C References#Howard 02]\] Chapter 11, "Canonical Representation Issues" \[[ISO/IEC 9899:-1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.19.4, "Operations on Files" \[[Open Group 04|AA. C References#Open Group 04]\] [{{open()}}|http://www.opengroup.org/onlinepubs/009695399/functions/open.html] |
...