From 4f3e29c30f3ae78ca94143b77c6462baeb3aa96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20A=2E=20Garc=C3=ADa=20Pardo=20Gim=C3=A9nez=20de=20lo?= =?UTF-8?q?s=20Galanes?= Date: Mon, 9 Sep 2019 07:51:28 +0200 Subject: [PATCH] dispatcher socket file mode. (#3124) Makes the file mode of the socket file configurable. (default 0770) Abstracts the sciond FileMode type into util package and uses it in both configs. Relates to #3099 --- go/godispatcher/internal/config/BUILD.bazel | 1 + go/godispatcher/internal/config/config.go | 9 ++++++ .../internal/config/config_test.go | 2 ++ go/godispatcher/internal/config/sample.go | 3 ++ go/godispatcher/main.go | 6 +++- go/godispatcher/main_test.go | 3 +- go/godispatcher/network/dispatcher.go | 5 +++ go/lib/sock/reliable/reliable.go | 2 ++ go/lib/util/BUILD.bazel | 1 + go/lib/util/file_mode.go | 32 +++++++++++++++++++ go/sciond/internal/config/config.go | 12 +------ 11 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 go/lib/util/file_mode.go diff --git a/go/godispatcher/internal/config/BUILD.bazel b/go/godispatcher/internal/config/BUILD.bazel index fed4d915f0..a51ade1780 100644 --- a/go/godispatcher/internal/config/BUILD.bazel +++ b/go/godispatcher/internal/config/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//go/lib/env:go_default_library", "//go/lib/overlay:go_default_library", "//go/lib/sock/reliable:go_default_library", + "//go/lib/util:go_default_library", ], ) diff --git a/go/godispatcher/internal/config/config.go b/go/godispatcher/internal/config/config.go index fb80f193cd..ccc9e06cce 100644 --- a/go/godispatcher/internal/config/config.go +++ b/go/godispatcher/internal/config/config.go @@ -24,6 +24,7 @@ import ( "github.com/scionproto/scion/go/lib/env" "github.com/scionproto/scion/go/lib/overlay" "github.com/scionproto/scion/go/lib/sock/reliable" + "github.com/scionproto/scion/go/lib/util" ) var _ config.Config = (*Config)(nil) @@ -37,6 +38,8 @@ type Config struct { ID string // ApplicationSocket is the local API socket (default /run/shm/dispatcher/default.sock) ApplicationSocket string + // Socket file permissions when created; read from octal. (default 0770) + SocketFileMode util.FileMode // OverlayPort is the native port opened by the dispatcher (default 30041) OverlayPort int // PerfData starts the pprof HTTP server on the specified address. If not set, @@ -52,6 +55,9 @@ func (cfg *Config) InitDefaults() { if cfg.Dispatcher.ApplicationSocket == "" { cfg.Dispatcher.ApplicationSocket = reliable.DefaultDispPath } + if cfg.Dispatcher.SocketFileMode == 0 { + cfg.Dispatcher.SocketFileMode = reliable.DefaultDispSocketFileMode + } if cfg.Dispatcher.OverlayPort == 0 { cfg.Dispatcher.OverlayPort = overlay.EndhostPort } @@ -61,6 +67,9 @@ func (cfg *Config) Validate() error { if cfg.Dispatcher.ApplicationSocket == "" { return common.NewBasicError("ApplicationSocket must be set", nil) } + if cfg.Dispatcher.SocketFileMode == 0 { + return common.NewBasicError("SocketFileMode must be set", nil) + } if cfg.Dispatcher.OverlayPort == 0 { return common.NewBasicError("OverlayPort must be set", nil) } diff --git a/go/godispatcher/internal/config/config_test.go b/go/godispatcher/internal/config/config_test.go index afe713cc86..32e3c82d26 100644 --- a/go/godispatcher/internal/config/config_test.go +++ b/go/godispatcher/internal/config/config_test.go @@ -52,6 +52,8 @@ func CheckTestConfig(cfg *Config, id string) { SoMsg("ID", cfg.Dispatcher.ID, ShouldEqual, id) SoMsg("ApplicationSocket", cfg.Dispatcher.ApplicationSocket, ShouldEqual, reliable.DefaultDispPath) + SoMsg("SocketFileMode", cfg.Dispatcher.SocketFileMode, ShouldEqual, + reliable.DefaultDispSocketFileMode) SoMsg("OverlayPort", cfg.Dispatcher.OverlayPort, ShouldEqual, overlay.EndhostPort) SoMsg("PerfData", cfg.Dispatcher.PerfData, ShouldBeEmpty) SoMsg("DeleteSocket", cfg.Dispatcher.DeleteSocket, ShouldBeFalse) diff --git a/go/godispatcher/internal/config/sample.go b/go/godispatcher/internal/config/sample.go index 157870daa7..565f04c3ec 100644 --- a/go/godispatcher/internal/config/sample.go +++ b/go/godispatcher/internal/config/sample.go @@ -23,6 +23,9 @@ ID = "%s" # ApplicationSocket is the local API socket. (default /run/shm/dispatcher/default.sock) ApplicationSocket = "/run/shm/dispatcher/default.sock" +# File permissions of the ApplicationSocket socket file, in octal. (default "0770") +SocketFileMode = "0770" + # OverlayPort is the native port opened by the dispatcher. (default 30041) OverlayPort = 30041 diff --git a/go/godispatcher/main.go b/go/godispatcher/main.go index 201c8c0e72..7c56cf438f 100644 --- a/go/godispatcher/main.go +++ b/go/godispatcher/main.go @@ -70,6 +70,7 @@ func realMain() int { err := RunDispatcher( cfg.Dispatcher.DeleteSocket, cfg.Dispatcher.ApplicationSocket, + os.FileMode(cfg.Dispatcher.SocketFileMode), cfg.Dispatcher.OverlayPort, ) if err != nil { @@ -120,7 +121,9 @@ func setupBasic() error { return env.LogAppStarted("Dispatcher", cfg.Dispatcher.ID) } -func RunDispatcher(deleteSocketFlag bool, applicationSocket string, overlayPort int) error { +func RunDispatcher(deleteSocketFlag bool, applicationSocket string, socketFileMode os.FileMode, + overlayPort int) error { + if deleteSocketFlag { if err := deleteSocket(cfg.Dispatcher.ApplicationSocket); err != nil { return err @@ -130,6 +133,7 @@ func RunDispatcher(deleteSocketFlag bool, applicationSocket string, overlayPort RoutingTable: network.NewIATable(1024, 65535), OverlaySocket: fmt.Sprintf(":%d", overlayPort), ApplicationSocket: applicationSocket, + SocketFileMode: socketFileMode, } log.Debug("Dispatcher starting", "appSocket", applicationSocket, "overlayPort", overlayPort) return dispatcher.ListenAndServe() diff --git a/go/godispatcher/main_test.go b/go/godispatcher/main_test.go index cca9f1f26e..bd2178aab8 100644 --- a/go/godispatcher/main_test.go +++ b/go/godispatcher/main_test.go @@ -423,7 +423,8 @@ func TestDataplaneIntegration(t *testing.T) { settings := InitTestSettings(t) go func() { - err := RunDispatcher(false, settings.ApplicationSocket, settings.OverlayPort) + err := RunDispatcher(false, settings.ApplicationSocket, reliable.DefaultDispSocketFileMode, + settings.OverlayPort) xtest.FailOnErr(t, err, "dispatcher error") }() time.Sleep(defaultWaitDuration) diff --git a/go/godispatcher/network/dispatcher.go b/go/godispatcher/network/dispatcher.go index 8cbe01b2cb..67ede6fc1b 100644 --- a/go/godispatcher/network/dispatcher.go +++ b/go/godispatcher/network/dispatcher.go @@ -16,6 +16,7 @@ package network import ( "net" + "os" "sync" "time" @@ -38,6 +39,7 @@ type Dispatcher struct { RoutingTable *IATable OverlaySocket string ApplicationSocket string + SocketFileMode os.FileMode } func (d *Dispatcher) ListenAndServe() error { @@ -62,6 +64,9 @@ func (d *Dispatcher) ListenAndServe() error { return err } defer appServerConn.Close() + if err := os.Chmod(d.ApplicationSocket, d.SocketFileMode); err != nil { + return common.NewBasicError("chmod failed", err, "socket file", d.ApplicationSocket) + } errChan := make(chan error) go func() { diff --git a/go/lib/sock/reliable/reliable.go b/go/lib/sock/reliable/reliable.go index f45e14ef0e..3c4b06f3ae 100644 --- a/go/lib/sock/reliable/reliable.go +++ b/go/lib/sock/reliable/reliable.go @@ -80,6 +80,8 @@ const ( // DefaultDispPath contains the system default for a dispatcher socket. DefaultDispPath = "/run/shm/dispatcher/default.sock" defBufSize = 1 << 18 + // DefaultDispSocketFileMode allows read/write to the user and group only. + DefaultDispSocketFileMode = 0770 ) // DispatcherService controls how SCION applications open sockets in the SCION world. diff --git a/go/lib/util/BUILD.bazel b/go/lib/util/BUILD.bazel index e55f40118b..0d17354d2f 100644 --- a/go/lib/util/BUILD.bazel +++ b/go/lib/util/BUILD.bazel @@ -10,6 +10,7 @@ go_library( "duration.go", "duration_wrap.go", "file.go", + "file_mode.go", "fs.go", "map.go", "padding.go", diff --git a/go/lib/util/file_mode.go b/go/lib/util/file_mode.go new file mode 100644 index 0000000000..e08243f172 --- /dev/null +++ b/go/lib/util/file_mode.go @@ -0,0 +1,32 @@ +// Copyright 2019 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "os" + "strconv" + + "github.com/BurntSushi/toml" +) + +var _ (toml.TextUnmarshaler) = (*FileMode)(nil) + +type FileMode os.FileMode + +func (f *FileMode) UnmarshalText(text []byte) error { + perm, err := strconv.ParseUint(string(text), 8, 32) + *f = FileMode(perm) + return err +} diff --git a/go/sciond/internal/config/config.go b/go/sciond/internal/config/config.go index 8d7df76d2b..053fb96973 100644 --- a/go/sciond/internal/config/config.go +++ b/go/sciond/internal/config/config.go @@ -17,8 +17,6 @@ package config import ( "io" - "os" - "strconv" "time" "github.com/scionproto/scion/go/lib/common" @@ -103,7 +101,7 @@ type SDConfig struct { // unixgram server on the default socket is started. Unix string // Socket files (both Reliable and Unix) permissions when created; read from octal (e.g. 0755). - SocketFileMode FileMode + SocketFileMode util.FileMode // If set to True, the socket is removed before being created DeleteSocket bool // Public is the local address to listen on for SCION messages (if Bind is @@ -171,11 +169,3 @@ func (cfg *SDConfig) CreateSocketDirs() error { } return nil } - -type FileMode os.FileMode - -func (f *FileMode) UnmarshalText(text []byte) error { - perm, err := strconv.ParseUint(string(text), 8, 32) - *f = FileMode(perm) - return err -}