package cgroup import ( "reflect" "strings" "testing" ) func TestShimSpecRoundTripsExactBytes(t *testing.T) { in := shimSpec{ Path: "/run/carlos/exe/app", Dir: "/data/app dir", Argv: []string{"app", "", "two words", "line\nbreak", "--db", "/data/x.db"}, Env: []string{"A=1", "EMPTY=", "EQ=a=b", "BAD=\xff\xfe", "BIG=" + strings.Repeat("x", 1<<20)}, Expected: "/system.slice/carlos-edge.service/carlos-exec@a.example/g3", KeepFDs: 5, TestHold: 2, SigIgn: 1<<0 | 1<<14 | 1<<63, } b, err := encodeShimSpec(in) if err != nil { t.Fatal(err) } out, err := decodeShimSpec(b) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(in, out) { t.Fatalf("round trip changed the spec") } } // An empty argv and env round-trip as empty, not as one empty string. func TestShimSpecRoundTripsEmptyLists(t *testing.T) { in := shimSpec{Path: "/x", Argv: []string{}, Env: []string{}, Expected: "/g", KeepFDs: 3} b, err := encodeShimSpec(in) if err != nil { t.Fatal(err) } out, err := decodeShimSpec(b) if err != nil { t.Fatal(err) } if len(out.Argv) != 0 || len(out.Env) != 0 || out.Path != "/x" || out.Expected != "/g" || out.KeepFDs != 3 { t.Fatalf("got %+v", out) } } func TestShimSpecRefusesNUL(t *testing.T) { if _, err := encodeShimSpec(shimSpec{Path: "/x", Argv: []string{"a\x00b"}, Expected: "/g", KeepFDs: 3}); err == nil { t.Fatal("a NUL inside argv was encoded") } if _, err := encodeShimSpec(shimSpec{Path: "/x", Env: []string{"A=\x00"}, Expected: "/g", KeepFDs: 3}); err == nil { t.Fatal("a NUL inside env was encoded") } if _, err := encodeShimSpec(shimSpec{Path: "/x\x00y", Expected: "/g", KeepFDs: 3}); err == nil { t.Fatal("a NUL inside the path was encoded") } } func TestShimSpecRefusesTruncatedAndTrailing(t *testing.T) { b, _ := encodeShimSpec(shimSpec{Path: "/x", Argv: []string{"x"}, Env: []string{"A=1"}, Expected: "/g", KeepFDs: 3}) for _, bad := range [][]byte{b[:len(b)-1], append(append([]byte{}, b...), 'z', 0), []byte("carlos-cgexec-0\x00")} { if _, err := decodeShimSpec(bad); err == nil { t.Fatalf("decoded a bad spec %q", bad) } } } func TestShimSpecRefusesHugeCounts(t *testing.T) { bad := []byte("carlos-cgexec-2\x00/x\x00\x00/g\x003\x000\x000\x001048577\x00") if _, err := decodeShimSpec(bad); err == nil { t.Fatal("decoded an argv count above 1<<20") } // The control: the same spec with a count in bounds decodes. ok := []byte("carlos-cgexec-2\x00/x\x00\x00/g\x003\x000\x000\x000\x000\x00") if _, err := decodeShimSpec(ok); err != nil { t.Fatalf("the control spec: %v", err) } } // The ignored-signal set is a 64-bit number: a bad one, and a spec in the // encoding before the set was added (magic carlos-cgexec-1), are refused. func TestShimSpecRefusesBadSigIgnAndTheOldEncoding(t *testing.T) { for _, bad := range []string{ "carlos-cgexec-2\x00/x\x00\x00/g\x003\x000\x00x\x000\x000\x00", "carlos-cgexec-2\x00/x\x00\x00/g\x003\x000\x0018446744073709551616\x000\x000\x00", "carlos-cgexec-2\x00/x\x00\x00/g\x003\x000\x00-1\x000\x000\x00", "carlos-cgexec-1\x00/x\x00\x00/g\x003\x000\x000\x000\x00", } { if _, err := decodeShimSpec([]byte(bad)); err == nil { t.Fatalf("decoded a bad spec %q", bad) } } }