-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
Go's Facessat() implementation fails to account for secondary group memberships when flags != 0 when determining whether a given file access is allowed. This causes it to return an error where file access would actually be allowed. The following example demonstrates the problem, with a file that is only readable because of secondary group membership:
$ go version
go version go1.13.5 linux/amd64
$ cat test.go
package main
import (
"fmt"
"os"
"syscall"
"golang.org/x/sys/unix"
)
func main() {
path := os.Args[1]
err := syscall.Faccessat(0, path, unix.R_OK, unix.AT_EACCESS)
fmt.Printf("uid %v, euid %v, gid %v, egid %v, path %v, err: %v\n", syscall.Getuid(), syscall.Geteuid(), syscall.Getgid(), syscall.Getegid(), path, err)
}
$ go build -o test
$ id
uid=501(lma) gid=20(dialout) groups=20(dialout),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),114(lpadmin),115(sambashare),116(docker)
$ ls -l file
-rwxrwx--- 1 root adm 6 Jun 17 20:19 file
$ cat file
Hello
$ ./test $(pwd)/file
uid 501, euid 501, gid 20, egid 20, path /home/lma/faccessat/file, err: permission denied
$
The go implementation (https://golang.org/src/syscall/syscall_linux.go) references the glibc implementation (https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/faccessat.c;hb=HEAD) but where glibc calls __group_member() to check group memberships if file's gid != user's gid, the go implementation just does a last-resort check of world/other permissions.
Naturally, I'd expect syscall.Faccessat() to act like C faccessat()... :)