github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/os/exec/lp_linux_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package exec 6 7 import ( 8 "internal/syscall/unix" 9 "os" 10 "path/filepath" 11 "syscall" 12 "testing" 13 ) 14 15 func TestFindExecutableVsNoexec(t *testing.T) { 16 t.Parallel() 17 18 // This test case relies on faccessat2(2) syscall, which appeared in Linux v5.8. 19 if major, minor := unix.KernelVersion(); major < 5 || (major == 5 && minor < 8) { 20 t.Skip("requires Linux kernel v5.8 with faccessat2(2) syscall") 21 } 22 23 tmp := t.TempDir() 24 25 // Create a tmpfs mount. 26 err := syscall.Mount("tmpfs", tmp, "tmpfs", 0, "") 27 if err != nil { 28 // Usually this means lack of CAP_SYS_ADMIN, but there might be 29 // other reasons, especially in restricted test environments. 30 t.Skipf("requires ability to mount tmpfs (%v)", err) 31 } 32 t.Cleanup(func() { 33 if err := syscall.Unmount(tmp, 0); err != nil { 34 t.Error(err) 35 } 36 }) 37 38 // Create an executable. 39 path := filepath.Join(tmp, "program") 40 err = os.WriteFile(path, []byte("#!/bin/sh\necho 123\n"), 0o755) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 // Check that it works as expected. 46 err = findExecutable(path) 47 if err != nil { 48 t.Fatalf("findExecutable: got %v, want nil", err) 49 } 50 51 if err := Command(path).Run(); err != nil { 52 t.Fatalf("exec: got %v, want nil", err) 53 } 54 55 // Remount with noexec flag. 56 err = syscall.Mount("", tmp, "", syscall.MS_REMOUNT|syscall.MS_NOEXEC, "") 57 if err != nil { 58 t.Fatalf("remount %s with noexec failed: %v", tmp, err) 59 } 60 61 if err := Command(path).Run(); err == nil { 62 t.Fatal("exec on noexec filesystem: got nil, want error") 63 } 64 65 err = findExecutable(path) 66 if err == nil { 67 t.Fatalf("findExecutable: got nil, want error") 68 } 69 }