Description
Proposal Details
On *BSD and Solaris systems, open(2)
and mkdir(2)
will not create a file with the sticky bit set. The FreeBSD sticky(8) manpage lists this as a bug. I don't know the historical reasons for this behavior.
#8383 reported this as a bug in os.OpenFile
and os.Mkdir
, and subsequently CL 1673 changed OpenFile
to set the sticky bit after creation when the file mode includes ModeSticky
. (A later CL added the same behavior for Mkdir
.)
This operation is racy: When creating a file with ModeSticky
, we:
- Check to see if the file exists.
- Open the file (possibly creating it).
- If the file did not exist, stat it to find its current mode.
- If the file did not exist, chmod the file to add the sticky bit.
If the target file is created between steps 1 and 2, then we may chmod a file we did not create. I think this is of minimal concern.
If the target file, or some part of its path, is replaced with a symlink between steps 2 and 4, however, we will chmod the target of the link, which could be anything. This is difficult to exploit: It requires that a privileged process be creating a file with the sticky bit set in a location that is writable by an attacker. If an exploitable scenario exists, however, it should be fairly straightforward to convert to local privilege escalation.
We can avoid the race in OpenFile
by using File.Chmod
to chmod the actual file opened.
Avoiding the race in Mkdir
is harder, because mkdir(2)
doesn't return a handle to the new directory. We could work around it with a multi-phase dance of opening the parent directory, using mkdirat(2)
to create the new directory, and then using openat(2)
to open the newly-created directory. This still leaves a race condition--we might be opening a directory different than the one we just created--but at least we'll be certain that we're chmodding a directory in the exact same location as the one we created.
I propose that working around the OS behavior in this case is a mistake, and that rather than putting in complicated workarounds we should remove the behavior introduced by CL 1673, with a GODEBUG to reenable the original behavior, race conditions and all.
Metadata
Metadata
Assignees
Type
Projects
Status