From fb4fb0430b8d77b5487f51fd780bba25476e816c Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 13 Jun 2018 15:54:42 +0200 Subject: syscall: check Fchmodat flags parameter on Linux As mentioned in #25845, port CL 46474 from golang.org/x/sys/unix to the syscall package. Currently Linux' fchmodat(2) syscall implementation doesn't support the flags parameter (though it might in future versions [1]). Fchmodat in the syscall package takes the parameter and (wrongly) passes it on to the syscall which will ignore it. According to the POSIX.1-2008 manual page [2], AT_SYMLINK_NOFOLLOW is the only valid value for the flags parameter and EOPNOTSUPP should be returned in case changing the mode of a symbolic link is not supported by the underlying system. EINVAL should be returned for any other value of the flags parameter. [1] https://patchwork.kernel.org/patch/9596301/ [2] http://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html Updates #20130 Updates #25845 Change-Id: I1021dd0e6a4f4cb3557cb1c1b34dd618c378cda6 Reviewed-on: https://go-review.googlesource.com/118658 Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_linux.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/syscall/syscall_linux.go') diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 58216f1957..8d0532e216 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -35,6 +35,20 @@ func Creat(path string, mode uint32) (fd int, err error) { return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) } +//sys fchmodat(dirfd int, path string, mode uint32) (err error) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + // Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior + // and check the flags. Otherwise the mode would be applied to the symlink + // destination which is not what the user expects. + if flags&^_AT_SYMLINK_NOFOLLOW != 0 { + return EINVAL + } else if flags&_AT_SYMLINK_NOFOLLOW != 0 { + return EOPNOTSUPP + } + return fchmodat(dirfd, path, mode) +} + //sys linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) func Link(oldpath string, newpath string) (err error) { @@ -830,7 +844,6 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri //sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) //sys Fchdir(fd int) (err error) //sys Fchmod(fd int, mode uint32) (err error) -//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys fcntl(fd int, cmd int, arg int) (val int, err error) //sys Fdatasync(fd int) (err error) -- cgit v1.3