From 377052c90cae9c1fd148ab2e64c7730917a57db1 Mon Sep 17 00:00:00 2001 From: Mewp Date: Sun, 9 Mar 2025 16:06:52 +0000 Subject: [PATCH] fix: Listening on abstract domain sockets (#7020) When passed a socket name that starts with @, go will listen on an abstract unix domain socket. Forgejo breaks this by assuming the socket name is a file path and normalizing it to an absolute path. This small commit prevents treating the socket name as a filesystem path if it starts with @. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7020 Reviewed-by: Gusted Co-authored-by: Mewp Co-committed-by: Mewp --- modules/graceful/net_unix.go | 9 ++++++--- modules/graceful/net_unix_linux_test.go | 15 +++++++++++++++ modules/setting/server.go | 2 +- modules/setting/server_test.go | 13 +++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 modules/graceful/net_unix_linux_test.go diff --git a/modules/graceful/net_unix.go b/modules/graceful/net_unix.go index 97b591f98f..320904db17 100644 --- a/modules/graceful/net_unix.go +++ b/modules/graceful/net_unix.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "os" + "path/filepath" "strconv" "strings" "sync" @@ -235,9 +236,11 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener, return nil, err } - fileMode := os.FileMode(setting.UnixSocketPermission) - if err = os.Chmod(address.Name, fileMode); err != nil { - return nil, fmt.Errorf("Failed to set permission of unix socket to %s: %w", fileMode.String(), err) + if filepath.IsAbs(address.Name) { + fileMode := os.FileMode(setting.UnixSocketPermission) + if err = os.Chmod(address.Name, fileMode); err != nil { + return nil, fmt.Errorf("Failed to set permission of unix socket to %s: %w", fileMode.String(), err) + } } activeListeners = append(activeListeners, l) diff --git a/modules/graceful/net_unix_linux_test.go b/modules/graceful/net_unix_linux_test.go new file mode 100644 index 0000000000..144e5a4881 --- /dev/null +++ b/modules/graceful/net_unix_linux_test.go @@ -0,0 +1,15 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package graceful + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAbstractUnixSocket(t *testing.T) { + _, err := DefaultGetListener("unix", "@abc") + require.NoError(t, err) +} diff --git a/modules/setting/server.go b/modules/setting/server.go index 5cc33f6fc4..c874a58069 100644 --- a/modules/setting/server.go +++ b/modules/setting/server.go @@ -265,7 +265,7 @@ func loadServerFrom(rootCfg ConfigProvider) { } UnixSocketPermission = uint32(UnixSocketPermissionParsed) - if !filepath.IsAbs(HTTPAddr) { + if HTTPAddr[0] != '@' && !filepath.IsAbs(HTTPAddr) { HTTPAddr = filepath.Join(AppWorkPath, HTTPAddr) } } diff --git a/modules/setting/server_test.go b/modules/setting/server_test.go index 7054c474ff..4b95961a26 100644 --- a/modules/setting/server_test.go +++ b/modules/setting/server_test.go @@ -73,3 +73,16 @@ MAX_USER_REDIRECTS = 8` assert.EqualValues(t, 3, Service.UsernameCooldownPeriod) assert.EqualValues(t, 8, Service.MaxUserRedirects) } + +func TestUnixSocketAbstractNamespace(t *testing.T) { + iniStr := ` + [server] + PROTOCOL=http+unix + HTTP_ADDR=@forgejo + ` + cfg, err := NewConfigProviderFromData(iniStr) + require.NoError(t, err) + loadServerFrom(cfg) + + assert.EqualValues(t, "@forgejo", HTTPAddr) +}