If you don't mind having temp directories, the easy workaround is to make a directory with a unique name. That is an all or nothing operation even on NFS.
Another much more complicated trick you can use if you don't have O_EXCL is to open, lstat the file, then fstat the descriptor, and compare the results. There's still a race condition of course, but now you detect it. You should only continue if they have the same device and inode number, are empty, and have a link count of 1. If they don't check out you close the file and try another name. The bad thing there is that some device files can be affected by just being open()ed (kind of a bug really). The other problem is that you probably only need this for NFS and I'm not sure how it interacts with attribute caching, though it should work locally. (This technique can also be used to open files owned by another user and verify they didn't change out from under you.)
Some systems also have O_NOFOLLOW which will help against symlinks (but not hardlinks, though it's hard to think of an attack with those).
And above all, if you use an unpredictable filename with enough characters it will make things far more difficult statistically for the attacker, to the point the race condition is only of a theoretical concern (similar to concern over MD5 checksum collisions). Use of rand() with time() or getpid() for a seed wouldn't cut it of course :)
Copyright © 2018, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds