]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: allow \x00-prefixed unix abstract socket to use full path length
authorAlbert Sundjaja <albertsundjaja@gmail.com>
Sat, 22 Feb 2025 23:02:57 +0000 (23:02 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 24 Feb 2025 17:43:24 +0000 (09:43 -0800)
Fixes #70893

Change-Id: Ia0aaa497dad335fe962d52d3f115d26e8046e36f
GitHub-Last-Rev: 7dd663678d8aecdfac94541a570dfbd1aa2577e7
GitHub-Pull-Request: golang/go#71851
Reviewed-on: https://go-review.googlesource.com/c/go/+/650875
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
src/net/unixsock_linux_test.go
src/net/unixsock_windows_test.go
src/syscall/syscall_linux.go
src/syscall/syscall_windows.go

index d04007cef38b2c43f820bc7d26e4483b87ed4bf5..fa50ba7bd51abd64bacbb838ddea3374cfc80162 100644 (file)
@@ -49,6 +49,23 @@ func TestUnixAutobindClose(t *testing.T) {
        ln.Close()
 }
 
+func TestUnixAbstractLongNameNulStart(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")
+
+       la, err := ResolveUnixAddr("unix", string(paddedAddr))
+       if err != nil {
+               t.Fatal(err)
+       }
+       c, err := ListenUnix("unix", la)
+       if err != nil {
+               t.Fatal(err)
+       }
+       c.Close()
+}
+
 func TestUnixgramLinuxAbstractLongName(t *testing.T) {
        if !testableNetwork("unixgram") {
                t.Skip("abstract unix socket long name test")
index 511ba6f2df203e596c71336cd38f300b50669be8..4c1a8d7e7e04c06c004b35f7dac13fc8757cf0d1 100644 (file)
@@ -10,6 +10,7 @@ import (
        "internal/syscall/windows"
        "os"
        "reflect"
+       "syscall"
        "testing"
 )
 
@@ -69,6 +70,27 @@ func TestUnixConnLocalWindows(t *testing.T) {
        }
 }
 
+func TestUnixAbstractLongNameNulStart(t *testing.T) {
+       if !windows.SupportUnixSocket() {
+               t.Skip("unix test")
+       }
+
+       // 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")
+
+       la, err := ResolveUnixAddr("unix", string(paddedAddr))
+       if err != nil {
+               t.Fatal(err)
+       }
+       c, err := ListenUnix("unix", la)
+       if err != nil {
+               t.Fatal(err)
+       }
+       c.Close()
+}
+
 func TestModeSocket(t *testing.T) {
        if !windows.SupportUnixSocket() {
                t.Skip("unix test")
index 57d84748fe56d78d8dfccf5291230543260a55a5..d733ca9bf9230f92eb4d440cbe9eed0adc6cc718 100644 (file)
@@ -550,23 +550,29 @@ 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] != '@' {
+       // Abstract addresses start with NUL.
+       // '@' is also a valid way to specify abstract addresses.
+       isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
+
+       // Non-abstract named addresses are NUL terminated.
+       // The length can't use the full capacity as we need to add NUL.
+       if n == len(sa.raw.Path) && !isAbstract {
                return nil, 0, EINVAL
        }
        sa.raw.Family = AF_UNIX
        for i := 0; i < n; i++ {
                sa.raw.Path[i] = int8(name[i])
        }
-       // length is family (uint16), name, NUL.
-       sl := _Socklen(2)
-       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.
+       // Length is family + name (+ NUL if non-abstract).
+       // Family is of type uint16 (2 bytes).
+       sl := _Socklen(2 + n)
+       if isAbstract {
+               // Abstract addresses are not NUL terminated.
+               // We rewrite '@' prefix to NUL here.
                sa.raw.Path[0] = 0
-               // Don't count trailing NUL for abstract address.
-               sl--
+       } else if n > 0 {
+               // Add NUL for non-abstract named addresses.
+               sl++
        }
 
        return unsafe.Pointer(&sa.raw), sl, nil
index 344f6c325cd8fb54720ce3046c90a647067e76e2..7a349ddd341a14da981eaca6c8bed3f7729b2b2d 100644 (file)
@@ -858,23 +858,29 @@ 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] != '@' {
+       // Abstract addresses start with NUL.
+       // '@' is also a valid way to specify abstract addresses.
+       isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
+
+       // Non-abstract named addresses are NUL terminated.
+       // The length can't use the full capacity as we need to add NUL.
+       if n == len(sa.raw.Path) && !isAbstract {
                return nil, 0, EINVAL
        }
        sa.raw.Family = AF_UNIX
        for i := 0; i < n; i++ {
                sa.raw.Path[i] = int8(name[i])
        }
-       // length is family (uint16), name, NUL.
-       sl := int32(2)
-       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.
+       // Length is family + name (+ NUL if non-abstract).
+       // Family is of type uint16 (2 bytes).
+       sl := int32(2 + n)
+       if isAbstract {
+               // Abstract addresses are not NUL terminated.
+               // We rewrite '@' prefix to NUL here.
                sa.raw.Path[0] = 0
-               // Don't count trailing NUL for abstract address.
-               sl--
+       } else if n > 0 {
+               // Add NUL for non-abstract named addresses.
+               sl++
        }
 
        return unsafe.Pointer(&sa.raw), sl, nil