...
This noncompliant code example opens the file specified by the string file_name for read/write access and then writes user-supplied data to the file.
| Code Block |
|---|
|
char *file_name = /* something */;
char *userbuf = /* something */;
unsigned int userlen = /* length of userbuf string */;
int fd = open(file_name, O_RDWR);
if (fd == -1) {
/* handle error */
}
write(fd, userbuf, userlen);
|
...
| Wiki Markup |
|---|
Some systems provide the O_NOFOLLOW flag to help mitigate this problem. The flag will be required by the forthcoming POSIX.1-2008 standard, and so will become more portable over time \[[Austin Group 2008|AA. Bibliography#Austin Group 08]\]. If the flag is set and the supplied {{file_name}} is a symbolic link, then the open will fail. |
| Code Block |
|---|
|
char *file_name = /* something */;
char *userbuf = /* something */;
unsigned int userlen = /* length of userbuf string */;
int fd = open(file_name, O_RDWR | O_NOFOLLOW);
if (fd == -1) {
/* handle error */
}
write(fd, userbuf, userlen);
|
...
This compliant solution uses the lstat-fopen-fstat idiom illustrated in recommendation FIO05-C. Identify files using multiple file attributes.
| Code Block |
|---|
|
char *file_name = /* some value */;
struct stat orig_st;
if (lstat( file_name, &orig_st) != 0) {
/* handle error */
}
if (!S_ISREG( orig_st.st_mode)) {
/* file is irregular or symlink */
}
int fd = open(file_name, O_RDWR);
if (fd == -1) {
/* handle error */
}
struct stat new_st;
if (fstat(fd, &new_st) != 0) {
/* handle error */
}
if (orig_st.st_dev != new_st.st_dev ||
orig_st.st_ino != new_st.st_ino) {
/* file was tampered with during race window */
}
/* ... file is good, operate on fd ... */
|
...
One way to deal with hard links is simply to disallow opening of any file with two or more hard links. The following code snippet, when inserted into the previous example, will identify if a file has multiple hard links.
| Code Block |
|---|
|
if (orig_st.st_nlink > 1) {
/* file has multiple hard links */
}
|
...