Source file
src/os/exec/lp_linux_test.go
1
2
3
4
5 package exec_test
6
7 import (
8 "errors"
9 "internal/syscall/unix"
10 "internal/testenv"
11 "os"
12 "os/exec"
13 "path/filepath"
14 "syscall"
15 "testing"
16 )
17
18 func TestFindExecutableVsNoexec(t *testing.T) {
19 t.Parallel()
20
21
22 if major, minor := unix.KernelVersion(); major < 5 || (major == 5 && minor < 8) {
23 t.Skip("requires Linux kernel v5.8 with faccessat2(2) syscall")
24 }
25
26 tmp := t.TempDir()
27
28
29 err := syscall.Mount("tmpfs", tmp, "tmpfs", 0, "")
30 if testenv.SyscallIsNotSupported(err) {
31
32
33 t.Skipf("requires ability to mount tmpfs (%v)", err)
34 } else if err != nil {
35 t.Fatalf("mount %s failed: %v", tmp, err)
36 }
37 t.Cleanup(func() {
38 if err := syscall.Unmount(tmp, 0); err != nil {
39 t.Error(err)
40 }
41 })
42
43
44 path := filepath.Join(tmp, "program")
45 err = os.WriteFile(path, []byte("#!/bin/sh\necho 123\n"), 0o755)
46 if err != nil {
47 t.Fatal(err)
48 }
49
50
51 _, err = exec.LookPath(path)
52 if err != nil {
53 t.Fatalf("LookPath: got %v, want nil", err)
54 }
55
56 for {
57 err = exec.Command(path).Run()
58 if err == nil {
59 break
60 }
61 if errors.Is(err, syscall.ETXTBSY) {
62
63
64
65
66
67 } else {
68 t.Fatalf("exec: got %v, want nil", err)
69 }
70 }
71
72
73 err = syscall.Mount("", tmp, "", syscall.MS_REMOUNT|syscall.MS_NOEXEC, "")
74 if testenv.SyscallIsNotSupported(err) {
75 t.Skipf("requires ability to re-mount tmpfs (%v)", err)
76 } else if err != nil {
77 t.Fatalf("remount %s with noexec failed: %v", tmp, err)
78 }
79
80 if err := exec.Command(path).Run(); err == nil {
81 t.Fatal("exec on noexec filesystem: got nil, want error")
82 }
83
84 _, err = exec.LookPath(path)
85 if err == nil {
86 t.Fatalf("LookPath: got nil, want error")
87 }
88 }
89
View as plain text