Skip to content

Commit c23410a

Browse files
tklauserianlancetaylor
authored andcommitted
unix: check Fchmodat flags parameter on Linux
Currently Linux' fchmodat(2) syscall implementation doesn't support the flags parameter (though it might in future versions [1]). Fchmodat in x/sys/unix 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 Change the Fchmodat implementation accordingly and also add the corresponding test. Fixes golang/go#20130 Change-Id: I62e677e6674d3702eaf388af0ac3d7e623a35c24 Reviewed-on: https://go-review.googlesource.com/46474 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
1 parent fb4cac3 commit c23410a

13 files changed

Lines changed: 205 additions & 166 deletions

‎unix/syscall_linux.go‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ func Creat(path string, mode uint32) (fd int, err error) {
3636
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
3737
}
3838

39+
//sys fchmodat(dirfd int, path string, mode uint32) (err error)
40+
41+
func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
42+
// Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior
43+
// and check the flags. Otherwise the mode would be applied to the symlink
44+
// destination which is not what the user expects.
45+
if flags&^AT_SYMLINK_NOFOLLOW != 0 {
46+
return EINVAL
47+
} else if flags&AT_SYMLINK_NOFOLLOW != 0 {
48+
return EOPNOTSUPP
49+
}
50+
return fchmodat(dirfd, path, mode)
51+
}
52+
3953
//sys ioctl(fd int, req uint, arg uintptr) (err error)
4054

4155
// ioctl itself should not be exposed directly, but additional get/set
@@ -1177,7 +1191,6 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
11771191
//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error)
11781192
//sys Fchdir(fd int) (err error)
11791193
//sys Fchmod(fd int, mode uint32) (err error)
1180-
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
11811194
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
11821195
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
11831196
//sys Fdatasync(fd int) (err error)

‎unix/syscall_linux_test.go‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,32 @@ import (
1515
"golang.org/x/sys/unix"
1616
)
1717

18+
func TestFchmodat(t *testing.T) {
19+
defer chtmpdir(t)()
20+
21+
touch(t, "file1")
22+
os.Symlink("file1", "symlink1")
23+
24+
err := unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, 0)
25+
if err != nil {
26+
t.Fatalf("Fchmodat: unexpected error: %v", err)
27+
}
28+
29+
fi, err := os.Stat("file1")
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
34+
if fi.Mode() != 0444 {
35+
t.Errorf("Fchmodat: failed to change mode: expected %v, got %v", 0444, fi.Mode())
36+
}
37+
38+
err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", 0444, unix.AT_SYMLINK_NOFOLLOW)
39+
if err != unix.EOPNOTSUPP {
40+
t.Fatalf("Fchmodat: unexpected error: %v, expected EOPNOTSUPP", err)
41+
}
42+
}
43+
1844
func TestIoctlGetInt(t *testing.T) {
1945
f, err := os.Open("/dev/random")
2046
if err != nil {

‎unix/zsyscall_linux_386.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_amd64.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_arm.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_arm64.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_mips.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_mips64.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎unix/zsyscall_linux_mips64le.go‎

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)