From 8f95d2d8ec2ae7143fe95c59f7f406e0bd1656dc Mon Sep 17 00:00:00 2001 From: jwijenbergh Date: Wed, 19 Jun 2024 14:53:01 +0200 Subject: Config: Atomic file writes using tailscale package --- internal/config/atomicfile/atomicfile_test.go | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 internal/config/atomicfile/atomicfile_test.go (limited to 'internal/config/atomicfile/atomicfile_test.go') diff --git a/internal/config/atomicfile/atomicfile_test.go b/internal/config/atomicfile/atomicfile_test.go new file mode 100644 index 0000000..78c93e6 --- /dev/null +++ b/internal/config/atomicfile/atomicfile_test.go @@ -0,0 +1,47 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !js && !windows + +package atomicfile + +import ( + "net" + "os" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func TestDoesNotOverwriteIrregularFiles(t *testing.T) { + // Per tailscale/tailscale#7658 as one example, almost any imagined use of + // atomicfile.Write should likely not attempt to overwrite an irregular file + // such as a device node, socket, or named pipe. + + const filename = "TestDoesNotOverwriteIrregularFiles" + var path string + // macOS private temp does not allow unix socket creation, but /tmp does. + if runtime.GOOS == "darwin" { + path = filepath.Join("/tmp", filename) + t.Cleanup(func() { os.Remove(path) }) + } else { + path = filepath.Join(t.TempDir(), filename) + } + + // The least troublesome thing to make that is not a file is a unix socket. + // Making a null device sadly requires root. + l, err := net.ListenUnix("unix", &net.UnixAddr{Name: path, Net: "unix"}) + if err != nil { + t.Fatal(err) + } + defer l.Close() + + err = WriteFile(path, []byte("hello"), 0644) + if err == nil { + t.Fatal("expected error, got nil") + } + if !strings.Contains(err.Error(), "is not a regular file") { + t.Fatalf("unexpected error: %v", err) + } +} -- cgit v1.2.3