package rootstate import ( "os" "path/filepath" "testing" ) func TestTemplateUnitLinkRead(t *testing.T) { parent := t.TempDir() if err := os.Chmod(parent, 0755); err != nil { t.Fatal(err) } name := "sshd@.service.wants" if err := os.Mkdir(filepath.Join(parent, name), 0755); err != nil { t.Fatal(err) } if err := os.Symlink("/usr/lib/systemd/system/getty@.service", filepath.Join(parent, name, "getty@tty1.service")); err != nil { t.Fatal(err) } fd, err := os.Open(parent) if err != nil { t.Fatal(err) } defer fd.Close() s, err := descend(fd, []string{name}, false, true, uint32(os.Geteuid())) if err != nil { t.Fatal("trusted public template directory", err) } defer s.Close() target, err := s.(*directory).readLink("getty@tty1.service") if err != nil || target != "/usr/lib/systemd/system/getty@.service" { t.Fatal("template link", target, err) } if err = s.Write("new@record", []byte("authority")); err == nil { t.Fatal("template exception admitted record write") } for _, parts := range [][]string{{".."}, {"../sshd@.service.wants"}, {"sshd@.service.wants/.."}} { if d, e := descend(fd, parts, false, true, uint32(os.Geteuid())); e == nil { d.Close() t.Fatal("traversal accepted", parts) } } if d, e := descend(fd, []string{"new@directory"}, true, true, uint32(os.Geteuid())); e == nil { d.Close() t.Fatal("template exception admitted directory creation") } if err = os.Chmod(filepath.Join(parent, name), 0777); err != nil { t.Fatal(err) } if d, e := descend(fd, []string{name}, false, true, uint32(os.Geteuid())); e == nil { d.Close() t.Fatal("writable template directory accepted") } }