From: Simon Ruderich Date: Sun, 4 Apr 2021 06:25:57 +0000 (+0200) Subject: fixperms: don't follow symlinks X-Git-Url: https://ruderich.org/simon/gitweb/?p=safcm%2Fsafcm.git;a=commitdiff_plain;h=b3947ca010d5e49ae519722393dd4d2d2a3c19f7 fixperms: don't follow symlinks This prevents a possible TOCTOU when chmodding files. --- diff --git a/cmd/safcm/fixperms.go b/cmd/safcm/fixperms.go index 6770934..47e4fb9 100644 --- a/cmd/safcm/fixperms.go +++ b/cmd/safcm/fixperms.go @@ -23,6 +23,7 @@ import ( "log" "os" "path/filepath" + "syscall" "ruderich.org/simon/safcm/cmd/safcm/config" ) @@ -78,7 +79,7 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error { // This is safe because perm does not include // setuid/setgid/sticky which use different values in // FileMode. - err := os.Chmod(path, fs.FileMode(perm)) + err := chmodNoFollow(path, fs.FileMode(perm)) if err != nil { return err } @@ -87,7 +88,7 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error { if perm != 0755 { perm = 0755 log.Printf("chmodding %q to %#o", path, perm) - err := os.Chmod(path, fs.FileMode(perm)) + err := chmodNoFollow(path, fs.FileMode(perm)) if err != nil { return err } @@ -97,3 +98,20 @@ func fixpermsWalkDirFunc(path string, d fs.DirEntry, err error) error { return nil } + +// chmodNoFollow works like os.Chmod but doesn't follow symlinks. +func chmodNoFollow(path string, mode fs.FileMode) error { + x, err := os.OpenFile(path, + os.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_NONBLOCK, 0) + if err != nil { + return err + } + defer x.Close() + + err = x.Chmod(mode) + if err != nil { + return err + } + + return nil +}