diff --git a/internal/system/link.go b/internal/system/link.go new file mode 100644 index 0000000..cbde3a1 --- /dev/null +++ b/internal/system/link.go @@ -0,0 +1,53 @@ +package system + +import ( + "fmt" + "os" + + "git.gensokyo.uk/security/fortify/internal/fmsg" +) + +// Link registers an Op that links dst to src. +func (sys *I) Link(oldname, newname string) *I { return sys.LinkFileType(Process, oldname, newname) } + +// LinkFileType registers a file linking Op labelled with type et. +func (sys *I) LinkFileType(et Enablement, oldname, newname string) *I { + sys.lock.Lock() + defer sys.lock.Unlock() + + sys.ops = append(sys.ops, &Hardlink{et, newname, oldname}) + + return sys +} + +type Hardlink struct { + et Enablement + dst, src string +} + +func (l *Hardlink) Type() Enablement { return l.et } + +func (l *Hardlink) apply(_ *I) error { + fmsg.VPrintln("linking ", l) + return fmsg.WrapErrorSuffix(os.Link(l.src, l.dst), + fmt.Sprintf("cannot link %q:", l.dst)) +} + +func (l *Hardlink) revert(_ *I, ec *Criteria) error { + if ec.hasType(l) { + fmsg.VPrintf("removing hard link %q", l.dst) + return fmsg.WrapErrorSuffix(os.Remove(l.dst), + fmt.Sprintf("cannot remove hard link %q:", l.dst)) + } else { + fmsg.VPrintf("skipping hard link %q", l.dst) + return nil + } +} + +func (l *Hardlink) Is(o Op) bool { + l0, ok := o.(*Hardlink) + return ok && l0 != nil && *l == *l0 +} + +func (l *Hardlink) Path() string { return l.src } +func (l *Hardlink) String() string { return fmt.Sprintf("%q from %q", l.dst, l.src) } diff --git a/internal/system/tmpfiles.go b/internal/system/tmpfiles.go index 6dd9790..7dff7c2 100644 --- a/internal/system/tmpfiles.go +++ b/internal/system/tmpfiles.go @@ -27,24 +27,8 @@ func (sys *I) CopyFileType(et Enablement, dst, src string) *I { return sys } -// Link registers an Op that links dst to src. -func (sys *I) Link(oldname, newname string) *I { - return sys.LinkFileType(Process, oldname, newname) -} - -// LinkFileType registers a file linking Op labelled with type et. -func (sys *I) LinkFileType(et Enablement, oldname, newname string) *I { - sys.lock.Lock() - defer sys.lock.Unlock() - - sys.ops = append(sys.ops, &Tmpfile{et, tmpfileLink, newname, oldname}) - - return sys -} - const ( tmpfileCopy uint8 = iota - tmpfileLink ) type Tmpfile struct { @@ -63,10 +47,6 @@ func (t *Tmpfile) apply(_ *I) error { fmsg.VPrintln("publishing tmpfile", t) return fmsg.WrapErrorSuffix(copyFile(t.dst, t.src), fmt.Sprintf("cannot copy tmpfile %q:", t.dst)) - case tmpfileLink: - fmsg.VPrintln("linking tmpfile", t) - return fmsg.WrapErrorSuffix(os.Link(t.src, t.dst), - fmt.Sprintf("cannot link tmpfile %q:", t.dst)) default: panic("invalid tmpfile method " + strconv.Itoa(int(t.method))) } @@ -94,8 +74,6 @@ func (t *Tmpfile) String() string { switch t.method { case tmpfileCopy: return fmt.Sprintf("%q from %q", t.dst, t.src) - case tmpfileLink: - return fmt.Sprintf("%q from %q", t.dst, t.src) default: panic("invalid tmpfile method " + strconv.Itoa(int(t.method))) } diff --git a/internal/system/tmpfiles_test.go b/internal/system/tmpfiles_test.go index babb67d..254c873 100644 --- a/internal/system/tmpfiles_test.go +++ b/internal/system/tmpfiles_test.go @@ -57,7 +57,7 @@ func TestLink(t *testing.T) { sys := New(150) sys.Link(tc.src, tc.dst) (&tcOp{Process, tc.src}).test(t, sys.ops, []Op{ - &Tmpfile{Process, tmpfileLink, tc.dst, tc.src}, + &Hardlink{Process, tc.dst, tc.src}, }, "Link") }) } @@ -76,7 +76,7 @@ func TestLinkFileType(t *testing.T) { sys := New(150) sys.LinkFileType(tc.et, tc.path, tc.dst) tc.test(t, sys.ops, []Op{ - &Tmpfile{tc.et, tmpfileLink, tc.dst, tc.path}, + &Hardlink{tc.et, tc.dst, tc.path}, }, "LinkFileType") }) } @@ -101,10 +101,6 @@ func TestTmpfile_String(t *testing.T) { }{ {tmpfileCopy, "/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse-cookie", "/home/ophestra/xdg/config/pulse/cookie", `"/tmp/fortify.1971/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse-cookie" from "/home/ophestra/xdg/config/pulse/cookie"`}, - {tmpfileLink, "/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/wayland", "/run/user/1971/wayland-0", - `"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/wayland" from "/run/user/1971/wayland-0"`}, - {tmpfileLink, "/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse", "/run/user/1971/pulse/native", - `"/run/user/1971/fortify/4b6bdc9182fb2f1d3a965c5fa8b9b66e/pulse" from "/run/user/1971/pulse/native"`}, } for _, tc := range testCases {