Hi,

I just ran into some inconsistencies wrt permissions and `os.Mkdir()`, at 
least on Linux. I'm not sure what part of this is actual bugs that need to 
be fixed and what is a documentation bug, but let me state what I've found.

The documentation for Mkdir says: "Mkdir creates a new directory with the 
specified name and permission bits.". To me, this suggests that any 
permissions would be applied as-is, with no further processing. However, in 
practice, on at least Linux and probably other unices, the umask is applied:

matthijs@grubby:/tmp$ cat test.go
package main
import "os"
func main() {
        os.Mkdir("/tmp/foo", 0770)
}
matthijs@grubby:/tmp$ go build test.go
matthijs@grubby:/tmp$ ./test
matthijs@grubby:/tmp$ ls -ld foo
drwxr-x--- 2 matthijs matthijs 4096 Dec 13 14:25 foo    (Note missing g+w 
bit)
matthijs@grubby:/tmp$ rmdir foo
matthijs@grubby:/tmp$ umask 0
matthijs@grubby:/tmp$ ./test
matthijs@grubby:/tmp$ ls -ld foo
drwxrwx--- 2 matthijs matthijs 4096 Dec 13 14:25 foo    (Note permissions 
are as requested)
matthijs@grubby:/tmp$ umask 777
matthijs@grubby:/tmp$ rmdir foo
matthijs@grubby:/tmp$ ./test
matthijs@grubby:/tmp$ ls -ld foo
d--------- 2 matthijs matthijs 4096 Dec 13 14:25 foo    (Note all 
permissions masked away)

By itself, this is not uncommon for mkdir, it's just calling the mkdir 
syscall, so it behaves the same as the libc mkdir as well. This suggests 
this is merely a documentation bug.

However, when looking at the source for Mkdir 
<https://github.com/golang/go/blob/8776be153540cf450eafd847cf8efde0a01774dc/src/os/file.go#L220-L223>,
 
I find:

    // mkdir(2) itself won't handle the sticky bit on *BSD and Solari
    if !supportsCreateWithStickyBit && perm&ModeSticky != 0 {
        Chmod(name, perm)
    }

This means that, on BSD platforms (which also have umask), an explicit 
Chmod happens using the passed permissions, completely bypassing umask. 
This is at least inconsistent and surprising, and could be a security 
problem in some cases.


I also suspect that both of these problems exist exactly like this for 
OpenFile (I assume OpenFile also adheres to umask without this being 
documented, and it also special cases for the sticky bit 
<https://github.com/golang/go/blob/8776be153540cf450eafd847cf8efde0a01774dc/src/os/file_unix.go#L159-L163>
).

As suggested by the docs, I'm asking here before filing a bug, since I'm 
not sure what the exact bug and path forward should be from here. Making 
the permission argument behave as documented and always running a chmod 
seems like an obvious fix, but that completely breaks compatibility, likely 
resulting in security problems, so that seems out of the question...

A backward compatible fix in user code would be to just pass 0 as the 
permission to Mkdir or OpenFile, and then manually Chmod to whatever value 
is needed, which should be secure and work in most cases (except when some 
other process is waiting for the directory or file to be created, exposing 
a race condition).

Gr.

Matthijs

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to