| 1 | //go:build linux |
| 2 | |
| 3 | package host |
| 4 | |
| 5 | import ( |
| 6 | "net/http" |
| 7 | "os" |
| 8 | "os/exec" |
| 9 | "sync/atomic" |
| 10 | "testing" |
| 11 | ) |
| 12 | |
| 13 | // TestProbeRefusesForeignPeer (Review Focus 4, ruling H12): the moves owner |
| 14 | // set binds no readiness of its own, so the probe's readiness is the claim's |
| 15 | // (claimProbeSocketReady) on the path Select read from the app's manifest. A |
| 16 | // listener in this test process answers 200 on that path, but its peer is |
| 17 | // not in the spawned process's tree: the check refuses and the app's |
| 18 | // listener is never asked. |
| 19 | func TestProbeRefusesForeignPeer(t *testing.T) { |
| 20 | if (&movesProbeOwners{}).MovesOwners(&movesProbeAttempts{}).ProbeReady != nil { |
| 21 | t.Fatal("the moves owners replace the claim's probe readiness") |
| 22 | } |
| 23 | group := plan9D3SelfCgroup(t) |
| 24 | status := new(atomic.Int32) |
| 25 | status.Store(http.StatusOK) |
| 26 | rt, hits := plan9D3Server(t, status) |
| 27 | spawned := exec.Command("sleep", "5") |
| 28 | if err := spawned.Start(); err != nil { |
| 29 | t.Fatal(err) |
| 30 | } |
| 31 | t.Cleanup(func() { spawned.Process.Kill(); spawned.Wait() }) |
| 32 | if err := plan9D3Ready(t, plan9D3Cmd(t, spawned.Process.Pid), rt, "/ready", group); err == nil { |
| 33 | t.Fatal("a peer outside the spawned tree was accepted") |
| 34 | } |
| 35 | if hits.Load() != 0 { |
| 36 | t.Fatal("the foreign listener was asked") |
| 37 | } |
| 38 | // The same listener, answering as the spawned process, passes. |
| 39 | if err := plan9D3Ready(t, plan9D3Cmd(t, os.Getpid()), rt, "/ready", group); err != nil { |
| 40 | t.Fatalf("the spawned process itself: %v", err) |
| 41 | } |
| 42 | } |
| 43 | |