Skip to content

Commit 7891268

Browse files
authored
lapi: return specific error if a unix socket path is too long for the OS (#3593)
1 parent f941797 commit 7891268

5 files changed

Lines changed: 44 additions & 8 deletions

File tree

pkg/acquisition/modules/appsec/appsec.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/crowdsecurity/crowdsec/pkg/appsec"
2828
"github.com/crowdsecurity/crowdsec/pkg/appsec/allowlists"
2929
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
30+
"github.com/crowdsecurity/crowdsec/pkg/csnet"
3031
"github.com/crowdsecurity/crowdsec/pkg/types"
3132
)
3233

@@ -361,7 +362,7 @@ func (w *AppsecSource) listenAndServe(ctx context.Context, t *tomb.Tomb) error {
361362

362363
listener, err := net.Listen("unix", socket)
363364
if err != nil {
364-
serverError <- fmt.Errorf("appsec server failed: %w", err)
365+
serverError <- csnet.WrapSockErr(err, socket)
365366
return
366367
}
367368

pkg/apiclient/client_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
log "github.com/sirupsen/logrus"
1515
"github.com/stretchr/testify/assert"
1616
"github.com/stretchr/testify/require"
17+
"golang.org/x/net/nettest"
1718

1819
"github.com/crowdsecurity/go-cs-lib/cstest"
1920
)
@@ -69,8 +70,10 @@ func setupUnixSocketWithPrefix(t *testing.T, socket string, urlPrefix string) (m
6970
apiHandler.Handle(baseURLPath+"/", http.StripPrefix(baseURLPath, mux))
7071

7172
server := httptest.NewUnstartedServer(apiHandler)
72-
l, _ := net.Listen("unix", socket)
73-
_ = server.Listener.Close()
73+
l, err := net.Listen("unix", socket)
74+
require.NoError(t, err)
75+
err = server.Listener.Close()
76+
require.NoError(t, err)
7477
server.Listener = l
7578
server.Start()
7679

@@ -117,8 +120,8 @@ func TestNewClientOk(t *testing.T) {
117120

118121
func TestNewClientOk_UnixSocket(t *testing.T) {
119122
ctx := t.Context()
120-
tmpDir := t.TempDir()
121-
socket := path.Join(tmpDir, "socket")
123+
socket, err := nettest.LocalPath()
124+
require.NoError(t, err)
122125

123126
mux, urlx, teardown := setupUnixSocketWithPrefix(t, socket, "v1")
124127
defer teardown()
@@ -221,8 +224,8 @@ func TestNewDefaultClient(t *testing.T) {
221224
func TestNewDefaultClient_UnixSocket(t *testing.T) {
222225
ctx := t.Context()
223226

224-
tmpDir := t.TempDir()
225-
socket := path.Join(tmpDir, "socket")
227+
socket, err := nettest.LocalPath()
228+
require.NoError(t, err)
226229

227230
mux, urlx, teardown := setupUnixSocketWithPrefix(t, socket, "v1")
228231
defer teardown()

pkg/apiserver/apiserver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/crowdsecurity/crowdsec/pkg/apiserver/controllers"
2525
v1 "github.com/crowdsecurity/crowdsec/pkg/apiserver/middlewares/v1"
2626
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
27+
"github.com/crowdsecurity/crowdsec/pkg/csnet"
2728
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
2829
"github.com/crowdsecurity/crowdsec/pkg/database"
2930
"github.com/crowdsecurity/crowdsec/pkg/types"
@@ -467,7 +468,7 @@ func (s *APIServer) listenAndServeLAPI(apiReady chan bool) error {
467468

468469
listener, err := net.Listen("unix", socket)
469470
if err != nil {
470-
serverError <- fmt.Errorf("while creating unix listener: %w", err)
471+
serverError <- csnet.WrapSockErr(err, socket)
471472
return
472473
}
473474

pkg/csnet/socket.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package csnet
2+
3+
import (
4+
"fmt"
5+
"runtime"
6+
)
7+
8+
// WrapSockErr wraps the provided error with a possible cause if the unix socket path exceeds
9+
// a system-specific maximum length. It returns the original error otherwise.
10+
func WrapSockErr(err error, socket string) error {
11+
limit := 0
12+
switch runtime.GOOS {
13+
case "linux":
14+
// the actual numbers are not exported in Go, so we hardcode them
15+
limit = 108
16+
case "freebsd", "darwin", "openbsd":
17+
limit = 104
18+
}
19+
if limit > 0 && len(socket) > limit {
20+
return fmt.Errorf("%w (path length exceeds system limit: %d > %d)", err, len(socket), limit)
21+
}
22+
return err
23+
}

test/bats/01_crowdsec_lapi.bats

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ teardown() {
4242
assert_stderr --partial "local API server stopped with error: listening on 127.0.0.1:-80: listen tcp: address -80: invalid port"
4343
}
4444

45+
@test "lapi (socket path too long)" {
46+
LONG_NAME="12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
47+
export LONG_NAME
48+
rune -0 config_set '.api.server.listen_socket = strenv(BATS_FILE_TMPDIR) + "/" + strenv(LONG_NAME)'
49+
rune -1 "$CROWDSEC" -no-cs
50+
assert_stderr --partial "local API server stopped with error: listen unix $BATS_FILE_TMPDIR/$LONG_NAME: bind: invalid argument (path length exceeds system limit"
51+
}
52+
4553
@test "lapi (listen on random port)" {
4654
config_set '.common.log_media="stdout"'
4755
rune -0 config_set 'del(.api.server.listen_socket) | .api.server.listen_uri="127.0.0.1:0"'

0 commit comments

Comments
 (0)