This prevents a possible TOCTOU when chmodding files.
"log"
"os"
"path/filepath"
"log"
"os"
"path/filepath"
"ruderich.org/simon/safcm/cmd/safcm/config"
)
"ruderich.org/simon/safcm/cmd/safcm/config"
)
// This is safe because perm does not include
// setuid/setgid/sticky which use different values in
// FileMode.
// 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
}
if err != nil {
return err
}
if perm != 0755 {
perm = 0755
log.Printf("chmodding %q to %#o", path, perm)
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
}
if err != nil {
return err
}
+
+// 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
+}