diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-11-19 05:41:29 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-11-19 06:37:04 +0900 |
| commit | aab92ce3c1c6649e1a22b00ec999a271e71ef291 (patch) | |
| tree | 3ccfa205103382e9a4cbc225e71ba9f57ac64f94 /internal/wayland/conn.go | |
| parent | a495e09a8f11041fb23a9587c0dc9f52513a2937 (diff) | |
internal/wayland: clean up pathname socket
This is cleaner than cleaning up in internal/system as it covers the failure paths.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/wayland/conn.go')
| -rw-r--r-- | internal/wayland/conn.go | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/internal/wayland/conn.go b/internal/wayland/conn.go index fa7ced8c..40a909e7 100644 --- a/internal/wayland/conn.go +++ b/internal/wayland/conn.go @@ -12,18 +12,32 @@ import ( type SecurityContext struct { // Pipe with its write end passed to security-context-v1. closeFds [2]int + // Absolute pathname the socket was bound to. + bindPath *check.Absolute } // Close releases any resources held by [SecurityContext], and prevents further // connections to its associated socket. +// +// A non-nil error has the concrete type [Error]. func (sc *SecurityContext) Close() error { - if sc == nil { + if sc == nil || sc.bindPath == nil { return os.ErrInvalid } - return errors.Join( + + e := Error{RCleanup, sc.bindPath.String(), "", errors.Join( syscall.Close(sc.closeFds[1]), syscall.Close(sc.closeFds[0]), - ) + // there is still technically a TOCTOU here but this is internal + // and has access to the privileged wayland socket, so it only + // receives trusted input (e.g. from cmd/hakurei) anyway + os.Remove(sc.bindPath.String()), + )} + if e.Errno != nil { + return &e + } + + return nil } // New creates a new security context on the Wayland display at displayPath @@ -51,12 +65,19 @@ func New(displayPath, bindPath *check.Absolute, appID, instanceID string) (*Secu } else { closeFds, bindErr := securityContextBindPipe(fd, bindPath, appID, instanceID) if bindErr != nil { + // securityContextBindPipe does not try to remove the socket during cleanup + closeErr := os.Remove(bindPath.String()) + if closeErr != nil && errors.Is(closeErr, os.ErrNotExist) { + closeErr = nil + } + err = errors.Join(bindErr, // already wrapped + closeErr, // do not leak the socket syscall.Close(fd), ) } - return &SecurityContext{closeFds}, err + return &SecurityContext{closeFds, bindPath}, err } } |
