From 74527fe23c7b202d314eafd63489b3c635a3fb52 Mon Sep 17 00:00:00 2001 From: Albert Sundjaja Date: Wed, 18 Dec 2024 21:56:44 +1100 Subject: [PATCH] syscall: allow \x00-prefixed unix abstract socket to use full path length of 108 Fixes #70893 --- src/net/unixsock_linux_test.go | 18 ++++++++++++++++++ src/net/unixsock_windows_test.go | 23 +++++++++++++++++++++++ src/syscall/syscall_linux.go | 6 +++--- src/syscall/syscall_windows.go | 6 +++--- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/net/unixsock_linux_test.go b/src/net/unixsock_linux_test.go index d04007cef38b2c..88fa0d86735a12 100644 --- a/src/net/unixsock_linux_test.go +++ b/src/net/unixsock_linux_test.go @@ -49,6 +49,24 @@ func TestUnixAutobindClose(t *testing.T) { ln.Close() } +func TestUnixAbstractLongNameeNullStart(t *testing.T) { + addr := "\x00abstract_test" + rsu := syscall.RawSockaddrUnix{} + paddedAddr := make([]byte, len(rsu.Path)) + copy(paddedAddr, "\x00abstract_test") + addr = string(paddedAddr) + + la, err := ResolveUnixAddr("unix", addr) + if err != nil { + t.Fatal(err) + } + c, err := ListenUnix("unix", la) + if err != nil { + t.Fatal(err) + } + defer c.Close() +} + func TestUnixgramLinuxAbstractLongName(t *testing.T) { if !testableNetwork("unixgram") { t.Skip("abstract unix socket long name test") diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index 511ba6f2df203e..da08d4a1c54427 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -10,6 +10,7 @@ import ( "internal/syscall/windows" "os" "reflect" + "syscall" "testing" ) @@ -69,6 +70,28 @@ func TestUnixConnLocalWindows(t *testing.T) { } } +func TestUnixAbstractLongNameNullStart(t *testing.T) { + if !windows.SupportUnixSocket() { + t.Skip("unix test") + } + + addr := "\x00abstract_test" + rsu := syscall.RawSockaddrUnix{} + paddedAddr := make([]byte, len(rsu.Path)) + copy(paddedAddr, "\x00abstract_test") + addr = string(paddedAddr) + + la, err := ResolveUnixAddr("unix", addr) + if err != nil { + t.Fatal(err) + } + c, err := ListenUnix("unix", la) + if err != nil { + t.Fatal(err) + } + defer c.Close() +} + func TestModeSocket(t *testing.T) { if !windows.SupportUnixSocket() { t.Skip("unix test") diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 003f7a538c581f..e8326070f9cc7c 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -554,7 +554,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > len(sa.raw.Path) { return nil, 0, EINVAL } - if n == len(sa.raw.Path) && name[0] != '@' { + isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00') + if n == len(sa.raw.Path) && !isAbstract { return nil, 0, EINVAL } sa.raw.Family = AF_UNIX @@ -566,8 +567,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { - // Check sl > 3 so we don't change unnamed socket behavior. + if isAbstract { sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 05c29c7b2060ad..0412651da73952 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -856,7 +856,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { if n > len(sa.raw.Path) { return nil, 0, EINVAL } - if n == len(sa.raw.Path) && name[0] != '@' { + isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00') + if n == len(sa.raw.Path) && !isAbstract { return nil, 0, EINVAL } sa.raw.Family = AF_UNIX @@ -868,8 +869,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { if n > 0 { sl += int32(n) + 1 } - if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { - // Check sl > 3 so we don't change unnamed socket behavior. + if isAbstract { sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl--