From 74527fe23c7b202d314eafd63489b3c635a3fb52 Mon Sep 17 00:00:00 2001 From: Albert Sundjaja Date: Wed, 18 Dec 2024 21:56:44 +1100 Subject: [PATCH 1/4] 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 d04007cef3..88fa0d8673 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 511ba6f2df..da08d4a1c5 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 003f7a538c..e8326070f9 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 05c29c7b20..0412651da7 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-- From d23e90da0dd48a21e8f9eef64fd434545fc993bb Mon Sep 17 00:00:00 2001 From: Albert Sundjaja Date: Sat, 8 Feb 2025 17:43:29 +1100 Subject: [PATCH 2/4] fix typo in func name and simplify test --- src/net/unixsock_linux_test.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/net/unixsock_linux_test.go b/src/net/unixsock_linux_test.go index 88fa0d8673..18324407d5 100644 --- a/src/net/unixsock_linux_test.go +++ b/src/net/unixsock_linux_test.go @@ -49,14 +49,11 @@ func TestUnixAutobindClose(t *testing.T) { ln.Close() } -func TestUnixAbstractLongNameeNullStart(t *testing.T) { - addr := "\x00abstract_test" - rsu := syscall.RawSockaddrUnix{} - paddedAddr := make([]byte, len(rsu.Path)) +func TestUnixAbstractLongNameNullStart(t *testing.T) { + paddedAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) copy(paddedAddr, "\x00abstract_test") - addr = string(paddedAddr) - la, err := ResolveUnixAddr("unix", addr) + la, err := ResolveUnixAddr("unix", string(paddedAddr)) if err != nil { t.Fatal(err) } From 40a763c3d17077ba52380ac034f383dc666d6fad Mon Sep 17 00:00:00 2001 From: Albert Sundjaja Date: Sat, 8 Feb 2025 17:57:09 +1100 Subject: [PATCH 3/4] added comment on test for clarity --- src/net/unixsock_linux_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/unixsock_linux_test.go b/src/net/unixsock_linux_test.go index 18324407d5..3c8fd85a9f 100644 --- a/src/net/unixsock_linux_test.go +++ b/src/net/unixsock_linux_test.go @@ -50,6 +50,8 @@ func TestUnixAutobindClose(t *testing.T) { } func TestUnixAbstractLongNameNullStart(t *testing.T) { + // Create an abstract socket name that starts with a null byte ("\x00") + // whose length is the maximum of RawSockaddrUnix Path len paddedAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) copy(paddedAddr, "\x00abstract_test") From 3dbcc8bdedb581652fe9be73b98062dbef85cbc3 Mon Sep 17 00:00:00 2001 From: Albert Sundjaja Date: Sat, 8 Feb 2025 17:57:32 +1100 Subject: [PATCH 4/4] simplify the unit test for windows --- src/net/unixsock_windows_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index da08d4a1c5..c30916c838 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -75,13 +75,12 @@ func TestUnixAbstractLongNameNullStart(t *testing.T) { t.Skip("unix test") } - addr := "\x00abstract_test" - rsu := syscall.RawSockaddrUnix{} - paddedAddr := make([]byte, len(rsu.Path)) + // Create an abstract socket name that starts with a null byte ("\x00") + // whose length is the maximum of RawSockaddrUnix Path len + paddedAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) copy(paddedAddr, "\x00abstract_test") - addr = string(paddedAddr) - la, err := ResolveUnixAddr("unix", addr) + la, err := ResolveUnixAddr("unix", string(paddedAddr)) if err != nil { t.Fatal(err) }