diff --git a/internal/wayland/conn.go b/internal/wayland/conn.go index 17ddae8..4a4428b 100644 --- a/internal/wayland/conn.go +++ b/internal/wayland/conn.go @@ -36,18 +36,18 @@ func (sc *SecurityContext) Close() error { func New(displayPath, bindPath *check.Absolute, appID, instanceID string) (*SecurityContext, error) { // ensure bindPath is available if f, err := os.Create(bindPath.String()); err != nil { - return nil, &Error{Cause: RHostCreate, Errno: err} + return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err} } else if err = f.Close(); err != nil { - return nil, &Error{Cause: RHostCreate, Errno: err} + return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err} } else if err = os.Remove(bindPath.String()); err != nil { - return nil, &Error{Cause: RHostCreate, Errno: err} + return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err} } if fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0); err != nil { - return nil, &Error{RHostSocket, err} + return nil, &Error{RHostSocket, bindPath.String(), displayPath.String(), err} } else if err = syscall.Connect(fd, &syscall.SockaddrUnix{Name: displayPath.String()}); err != nil { _ = syscall.Close(fd) - return nil, &Error{RHostConnect, err} + return nil, &Error{RHostConnect, bindPath.String(), displayPath.String(), err} } else { closeFds, bindErr := securityContextBindPipe(fd, bindPath, appID, instanceID) if bindErr != nil { diff --git a/internal/wayland/wayland-client-helper.h b/internal/wayland/wayland-client-helper.h index 6dfad88..5cdf033 100644 --- a/internal/wayland/wayland-client-helper.h +++ b/internal/wayland/wayland-client-helper.h @@ -16,7 +16,7 @@ typedef enum { HAKUREI_WAYLAND_LISTEN, /* ensure pathname failed, implemented in conn.go */ - HAKUREI_WAYLAND_HOST_CREAT, + HAKUREI_WAYLAND_CREAT, /* socket for host server failed, implemented in conn.go */ HAKUREI_WAYLAND_HOST_SOCKET, /* connect for host server failed, implemented in conn.go */ diff --git a/internal/wayland/wayland.go b/internal/wayland/wayland.go index 5f2ecee..f511300 100644 --- a/internal/wayland/wayland.go +++ b/internal/wayland/wayland.go @@ -38,6 +38,10 @@ type ( Error struct { // Where the failure occurred. Cause Res + // Attempted pathname socket. + Path string + // Pathname socket to host server. Omitted for libwayland errors. + Host string // Global errno value set during the fault. Errno error } @@ -69,8 +73,8 @@ const ( // RListen is returned if listen failed. The global errno is set. RListen Res = C.HAKUREI_WAYLAND_LISTEN - // RHostCreate is returned if ensuring pathname availability failed. Returned by [New]. - RHostCreate Res = C.HAKUREI_WAYLAND_HOST_CREAT + // RCreate is returned if ensuring pathname availability failed. Returned by [New]. + RCreate Res = C.HAKUREI_WAYLAND_CREAT // RHostSocket is returned if socket failed for host server. Returned by [New]. RHostSocket Res = C.HAKUREI_WAYLAND_HOST_SOCKET // RHostConnect is returned if connect failed for host server. Returned by [New]. @@ -96,21 +100,25 @@ func (e *Error) Error() string { case RNotAvail: return "compositor does not implement security_context_v1" - case RSocket, RBind, RListen: + case RSocket: if e.Errno == nil { return "socket operation failed" } - return e.Errno.Error() + return "socket: " + e.Errno.Error() + case RBind: + return e.withPrefix("cannot bind " + e.Path) + case RListen: + return e.withPrefix("cannot listen on " + e.Path) - case RHostCreate: + case RCreate: if e.Errno == nil { return "cannot ensure wayland pathname socket" } return e.Errno.Error() case RHostSocket: - return e.withPrefix("socket for host wayland server") + return e.withPrefix("socket") case RHostConnect: - return e.withPrefix("connect to host wayland server") + return e.withPrefix("cannot connect to " + e.Host) default: return e.withPrefix("impossible outcome") /* not reached */ @@ -142,6 +150,7 @@ func securityContextBind( if e.Cause == RSuccess { return nil } + e.Path = socketPath return &e } diff --git a/internal/wayland/wayland_test.go b/internal/wayland/wayland_test.go index a74d749..16ab22a 100644 --- a/internal/wayland/wayland_test.go +++ b/internal/wayland/wayland_test.go @@ -53,30 +53,43 @@ func TestError(t *testing.T) { {"socket", wayland.Error{ Cause: wayland.RSocket, Errno: stub.UniqueError(4), - }, "unique error 4 injected by the test suite"}, + }, "socket: unique error 4 injected by the test suite"}, + + {"bind", wayland.Error{ + Cause: wayland.RBind, + Path: "/hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland", + Errno: stub.UniqueError(5), + }, "cannot bind /hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland: unique error 5 injected by the test suite"}, + + {"listen", wayland.Error{ + Cause: wayland.RListen, + Path: "/hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland", + Errno: stub.UniqueError(6), + }, "cannot listen on /hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland: unique error 6 injected by the test suite"}, {"socket invalid", wayland.Error{ Cause: wayland.RSocket, }, "socket operation failed"}, - {"host create", wayland.Error{ - Cause: wayland.RHostCreate, + {"create", wayland.Error{ + Cause: wayland.RCreate, }, "cannot ensure wayland pathname socket"}, - {"host create path", wayland.Error{ - Cause: wayland.RHostCreate, + {"create path", wayland.Error{ + Cause: wayland.RCreate, Errno: &os.PathError{Op: "create", Path: "/proc/nonexistent", Err: syscall.EEXIST}, }, "create /proc/nonexistent: file exists"}, {"host socket", wayland.Error{ Cause: wayland.RHostSocket, - Errno: stub.UniqueError(5), - }, "socket for host wayland server: unique error 5 injected by the test suite"}, + Errno: stub.UniqueError(7), + }, "socket: unique error 7 injected by the test suite"}, {"host connect", wayland.Error{ Cause: wayland.RHostConnect, - Errno: stub.UniqueError(6), - }, "connect to host wayland server: unique error 6 injected by the test suite"}, + Host: "/run/user/1971/wayland-1", + Errno: stub.UniqueError(8), + }, "cannot connect to /run/user/1971/wayland-1: unique error 8 injected by the test suite"}, {"invalid", wayland.Error{ Cause: 0xbad, @@ -84,8 +97,8 @@ func TestError(t *testing.T) { {"invalid errno", wayland.Error{ Cause: 0xbad, - Errno: stub.UniqueError(5), - }, "impossible outcome: unique error 5 injected by the test suite"}, + Errno: stub.UniqueError(9), + }, "impossible outcome: unique error 9 injected by the test suite"}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) {