Moderate severityNVD Advisory· Published Oct 2, 2024· Updated Oct 2, 2024
CVE-2024-8038
CVE-2024-8038
Description
Vulnerable juju introspection abstract UNIX domain socket. An abstract UNIX domain socket responsible for introspection is available without authentication locally to network namespace users. This enables denial of service attacks.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/juju/jujuGo | < 0.0.0-20240829052008-43f0fc59790d | 0.0.0-20240829052008-43f0fc59790d |
Affected products
1- Range: 3.5
Patches
143f0fc59790dfix: use unix domain socket file for introspection socket
17 files changed · +124 −111
agent/addons/addons.go+7 −11 modified@@ -4,12 +4,12 @@ package addons import ( + "path" "runtime" "github.com/juju/clock" "github.com/juju/errors" "github.com/juju/loggo" - "github.com/juju/names/v4" "github.com/juju/worker/v3" "github.com/juju/worker/v3/dependency" "github.com/prometheus/client_golang/prometheus" @@ -22,17 +22,14 @@ import ( var logger = loggo.GetLogger("juju.cmd.jujud.agent.addons") -// DefaultIntrospectionSocketName returns the socket name to use for the -// abstract domain socket that the introspection worker serves requests -// over. -func DefaultIntrospectionSocketName(entityTag names.Tag) string { - return "jujud-" + entityTag.String() -} +// IntrospectionSocketName is the name of the socket file inside +// the agent's directory used for introspection calls. +const IntrospectionSocketName = "introspection.socket" // IntrospectionConfig defines the various components that the introspection // worker reports on or needs to start up. type IntrospectionConfig struct { - AgentTag names.Tag + AgentDir string Engine *dependency.Engine StatePoolReporter introspection.Reporter PubSubReporter introspection.Reporter @@ -44,8 +41,7 @@ type IntrospectionConfig struct { CentralHub introspection.StructuredHub LeaseFSM introspection.Leases - NewSocketName func(names.Tag) string - WorkerFunc func(config introspection.Config) (worker.Worker, error) + WorkerFunc func(config introspection.Config) (worker.Worker, error) } // StartIntrospection creates the introspection worker. It cannot and should @@ -60,7 +56,7 @@ func StartIntrospection(cfg IntrospectionConfig) error { return nil } - socketName := cfg.NewSocketName(cfg.AgentTag) + socketName := path.Join(cfg.AgentDir, IntrospectionSocketName) w, err := cfg.WorkerFunc(introspection.Config{ SocketName: socketName, DepEngine: cfg.Engine,
agent/addons/addons_test.go+4 −12 modified@@ -10,7 +10,6 @@ import ( "github.com/juju/clock" "github.com/juju/errors" "github.com/juju/loggo" - "github.com/juju/names/v4" "github.com/juju/testing" jc "github.com/juju/testing/checkers" "github.com/juju/worker/v3" @@ -55,8 +54,7 @@ func (s *introspectionSuite) TestStartError(c *gc.C) { } cfg := addons.IntrospectionConfig{ - AgentTag: names.NewMachineTag("42"), - NewSocketName: addons.DefaultIntrospectionSocketName, + AgentDir: c.MkDir(), WorkerFunc: func(_ introspection.Config) (worker.Worker, error) { return nil, errors.New("boom") }, @@ -85,9 +83,8 @@ func (s *introspectionSuite) TestStartSuccess(c *gc.C) { c.Assert(err, jc.ErrorIsNil) cfg := addons.IntrospectionConfig{ - AgentTag: names.NewMachineTag("42"), - Engine: engine, - NewSocketName: func(tag names.Tag) string { return "bananas" }, + AgentDir: c.MkDir(), + Engine: engine, WorkerFunc: func(cfg introspection.Config) (worker.Worker, error) { fake.config = cfg return fake, nil @@ -98,7 +95,7 @@ func (s *introspectionSuite) TestStartSuccess(c *gc.C) { c.Assert(err, jc.ErrorIsNil) c.Check(fake.config.DepEngine, gc.Equals, engine) - c.Check(fake.config.SocketName, gc.Equals, "bananas") + c.Check(fake.config.SocketName, jc.HasSuffix, "introspection.socket") // Stopping the engine causes the introspection worker to stop. engine.Kill() @@ -110,11 +107,6 @@ func (s *introspectionSuite) TestStartSuccess(c *gc.C) { } } -func (s *introspectionSuite) TestDefaultIntrospectionSocketName(c *gc.C) { - name := addons.DefaultIntrospectionSocketName(names.NewMachineTag("42")) - c.Assert(name, gc.Equals, "jujud-machine-42") -} - type dummyWorker struct { config introspection.Config done chan struct{}
cmd/containeragent/main_nix.go+1 −1 modified@@ -177,7 +177,7 @@ func main() { return cmd.Main(&run.RunCommand{MachineLock: lock}, ctx, args[1:]) }, jujuIntrospect: func(ctx *cmd.Context, args []string) int { - return cmd.Main(introspect.New(nil), ctx, args[1:]) + return cmd.Main(introspect.New(), ctx, args[1:]) }, } os.Exit(mainWrapper(f, os.Args))
cmd/containeragent/unit/agent.go+1 −2 modified@@ -291,10 +291,9 @@ func (c *containerUnitAgent) workers(sigTermCh chan os.Signal) (worker.Worker, e return nil, err } if err := addons.StartIntrospection(addons.IntrospectionConfig{ - AgentTag: c.CurrentConfig().Tag(), + AgentDir: agentConfig.Dir(), Engine: eng, MachineLock: c.machineLock, - NewSocketName: addons.DefaultIntrospectionSocketName, PrometheusGatherer: c.prometheusRegistry, WorkerFunc: introspection.NewWorker, Clock: c.clk,
cmd/jujud/agent/caasoperator.go+1 −2 modified@@ -258,10 +258,9 @@ func (op *CaasOperatorAgent) Workers() (worker.Worker, error) { return nil, err } if err := addons.StartIntrospection(addons.IntrospectionConfig{ - AgentTag: op.CurrentConfig().Tag(), + AgentDir: agentConfig.Dir(), Engine: engine, MachineLock: op.machineLock, - NewSocketName: addons.DefaultIntrospectionSocketName, PrometheusGatherer: op.prometheusRegistry, WorkerFunc: introspection.NewWorker, Clock: clock.WallClock,
cmd/jujud/agent/machine.go+3 −7 modified@@ -270,7 +270,6 @@ func (a *machineAgentCmd) Info() *cmd.Info { func MachineAgentFactoryFn( agentConfWriter agentconf.AgentConfigWriter, bufferedLogger *logsender.BufferedLogWriter, - newIntrospectionSocketName func(names.Tag) string, preUpgradeSteps upgrades.PreUpgradeStepsFunc, rootDir string, ) machineAgentFactoryFnType { @@ -286,7 +285,6 @@ func MachineAgentFactoryFn( Logger: logger, }), looputil.NewLoopDeviceManager(), - newIntrospectionSocketName, preUpgradeSteps, rootDir, isCaasAgent, @@ -301,7 +299,6 @@ func NewMachineAgent( bufferedLogger *logsender.BufferedLogWriter, runner *worker.Runner, loopDeviceManager looputil.LoopDeviceManager, - newIntrospectionSocketName func(names.Tag) string, preUpgradeSteps upgrades.PreUpgradeStepsFunc, rootDir string, isCaasAgent bool, @@ -321,7 +318,6 @@ func NewMachineAgent( rootDir: rootDir, initialUpgradeCheckComplete: gate.NewLock(), loopDeviceManager: loopDeviceManager, - newIntrospectionSocketName: newIntrospectionSocketName, prometheusRegistry: prometheusRegistry, mongoTxnCollector: mongometrics.NewTxnCollector(), mongoDialCollector: mongometrics.NewDialCollector(), @@ -558,9 +554,10 @@ func (a *MachineAgent) makeEngineCreator( agentName string, previousAgentVersion version.Number, ) func() (worker.Worker, error) { return func() (worker.Worker, error) { + agentConfig := a.CurrentConfig() engineConfigFunc := engine.DependencyEngineConfig metrics := engine.NewMetrics() - controllerMetricsSink := metrics.ForModel(a.CurrentConfig().Model()) + controllerMetricsSink := metrics.ForModel(agentConfig.Model()) engine, err := dependency.NewEngine(engineConfigFunc(controllerMetricsSink)) if err != nil { return nil, err @@ -648,12 +645,11 @@ func (a *MachineAgent) makeEngineCreator( return nil, err } if err := addons.StartIntrospection(addons.IntrospectionConfig{ - AgentTag: a.CurrentConfig().Tag(), + AgentDir: agentConfig.Dir(), Engine: engine, StatePoolReporter: &statePoolReporter, PubSubReporter: pubsubReporter, MachineLock: a.machineLock, - NewSocketName: a.newIntrospectionSocketName, PrometheusGatherer: a.prometheusRegistry, PresenceRecorder: presenceRecorder, WorkerFunc: introspection.NewWorker,
cmd/jujud/agent/util_test.go+0 −1 modified@@ -192,7 +192,6 @@ func NewTestMachineAgentFactory( rootDir: rootDir, initialUpgradeCheckComplete: gate.NewLock(), loopDeviceManager: &mockLoopDeviceManager{}, - newIntrospectionSocketName: addons.DefaultIntrospectionSocketName, prometheusRegistry: prometheusRegistry, mongoTxnCollector: mongometrics.NewTxnCollector(), mongoDialCollector: mongometrics.NewDialCollector(),
cmd/jujud/introspect/introspect.go+5 −12 modified@@ -10,6 +10,7 @@ import ( "net/http/httputil" "net/url" "os" + "path" "path/filepath" "strings" @@ -19,6 +20,7 @@ import ( "github.com/juju/names/v4" "github.com/kr/pretty" + "github.com/juju/juju/agent" "github.com/juju/juju/agent/addons" apiagent "github.com/juju/juju/api/agent/agent" jujucmd "github.com/juju/juju/cmd" @@ -35,16 +37,11 @@ type IntrospectCommand struct { verbose bool post bool form url.Values - - // IntrospectionSocketName returns the socket name - // for a given tag. If IntrospectionSocketName is nil, - // agent.DefaultIntrospectionSocketName is used. - IntrospectionSocketName func(names.Tag) string } // New initializes IntrospectCommand. -func New(sockNameGetter func(names.Tag) string) cmd.Command { - return &IntrospectCommand{IntrospectionSocketName: sockNameGetter} +func New() cmd.Command { + return &IntrospectCommand{} } const introspectCommandDoc = ` @@ -127,11 +124,7 @@ func (c *IntrospectCommand) Run(ctx *cmd.Context) error { return err } - getSocketName := c.IntrospectionSocketName - if getSocketName == nil { - getSocketName = addons.DefaultIntrospectionSocketName - } - socketName := "@" + getSocketName(tag) + socketName := path.Join(agent.Dir(c.dataDir, tag), addons.IntrospectionSocketName) if c.listen != "" { listener, err := net.Listen("tcp", c.listen) if err != nil {
cmd/jujud/introspect/introspect_test.go+29 −23 modified@@ -21,7 +21,6 @@ import ( "github.com/juju/cmd/v3" "github.com/juju/cmd/v3/cmdtesting" - "github.com/juju/names/v4" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" @@ -57,11 +56,7 @@ func (*IntrospectCommandSuite) assertInitError(c *gc.C, expect string, args ...s } func (*IntrospectCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) { - return cmdtesting.RunCommand(c, &introspect.IntrospectCommand{ - IntrospectionSocketName: func(tag names.Tag) string { - return filepath.Join(config.DataDir, "jujud-"+tag.String()) - }, - }, args...) + return cmdtesting.RunCommand(c, &introspect.IntrospectCommand{}, args...) } func (s *IntrospectCommandSuite) TestAutoDetectMachineAgent(c *gc.C) { @@ -70,7 +65,7 @@ func (s *IntrospectCommandSuite) TestAutoDetectMachineAgent(c *gc.C) { c.Assert(err, jc.ErrorIsNil) _, err = s.run(c, "query") - c.Assert(err, gc.ErrorMatches, ".*jujud-machine-1024.*") + c.Assert(err, gc.ErrorMatches, ".*machine-1024.*") } func (s *IntrospectCommandSuite) TestAutoDetectMachineAgentFails(c *gc.C) { @@ -84,11 +79,14 @@ func (s *IntrospectCommandSuite) TestAutoDetectMachineAgentFails(c *gc.C) { func (s *IntrospectCommandSuite) TestAgentSpecified(c *gc.C) { _, err := s.run(c, "query", "--agent=unit-foo-0") - c.Assert(err, gc.ErrorMatches, ".*jujud-unit-foo-0.*") + c.Assert(err, gc.ErrorMatches, ".*unit-foo-0.*") } func (s *IntrospectCommandSuite) TestQuery(c *gc.C) { - listener, err := net.Listen("unix", "@"+filepath.Join(config.DataDir, "jujud-machine-0")) + agentDir := filepath.Join(config.DataDir, "agents", "machine-0") + err := os.MkdirAll(agentDir, 0755) + c.Assert(err, jc.ErrorIsNil) + listener, err := net.Listen("unix", filepath.Join(agentDir, "introspection.socket")) c.Assert(err, jc.ErrorIsNil) defer listener.Close() @@ -102,7 +100,10 @@ func (s *IntrospectCommandSuite) TestQuery(c *gc.C) { } func (s *IntrospectCommandSuite) TestQueryFails(c *gc.C) { - listener, err := net.Listen("unix", "@"+filepath.Join(config.DataDir, "jujud-machine-0")) + agentDir := filepath.Join(config.DataDir, "agents", "machine-0") + err := os.MkdirAll(agentDir, 0755) + c.Assert(err, jc.ErrorIsNil) + listener, err := net.Listen("unix", filepath.Join(agentDir, "introspection.socket")) c.Assert(err, jc.ErrorIsNil) defer listener.Close() @@ -122,7 +123,10 @@ func (s *IntrospectCommandSuite) TestQueryFails(c *gc.C) { } func (s *IntrospectCommandSuite) TestGetToPostEndpoint(c *gc.C) { - listener, err := net.Listen("unix", "@"+filepath.Join(config.DataDir, "jujud-machine-0")) + agentDir := filepath.Join(config.DataDir, "agents", "machine-0") + err := os.MkdirAll(agentDir, 0755) + c.Assert(err, jc.ErrorIsNil) + listener, err := net.Listen("unix", filepath.Join(agentDir, "introspection.socket")) c.Assert(err, jc.ErrorIsNil) defer listener.Close() @@ -137,7 +141,10 @@ func (s *IntrospectCommandSuite) TestGetToPostEndpoint(c *gc.C) { } func (s *IntrospectCommandSuite) TestPost(c *gc.C) { - listener, err := net.Listen("unix", "@"+filepath.Join(config.DataDir, "jujud-machine-0")) + agentDir := filepath.Join(config.DataDir, "agents", "machine-0") + err := os.MkdirAll(agentDir, 0755) + c.Assert(err, jc.ErrorIsNil) + listener, err := net.Listen("unix", filepath.Join(agentDir, "introspection.socket")) c.Assert(err, jc.ErrorIsNil) defer listener.Close() @@ -155,8 +162,11 @@ single="value" } func (s *IntrospectCommandSuite) TestListen(c *gc.C) { - socketName := filepath.Join(config.DataDir, "jujud-machine-0") - listener, err := net.Listen("unix", "@"+socketName) + agentDir := filepath.Join(config.DataDir, "agents", "machine-0") + err := os.MkdirAll(agentDir, 0755) + c.Assert(err, jc.ErrorIsNil) + socketName := filepath.Join(agentDir, "introspection.socket") + listener, err := net.Listen("unix", socketName) c.Assert(err, jc.ErrorIsNil) defer listener.Close() @@ -166,7 +176,7 @@ func (s *IntrospectCommandSuite) TestListen(c *gc.C) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - cmd := exec.CommandContext(ctx, os.Args[0], "-run-listen="+socketName) + cmd := exec.CommandContext(ctx, os.Args[0], "-run-listen="+config.DataDir) stderr, err := cmd.StderrPipe() c.Assert(err, jc.ErrorIsNil) defer stderr.Close() @@ -176,7 +186,7 @@ func (s *IntrospectCommandSuite) TestListen(c *gc.C) { scanner := bufio.NewScanner(stderr) c.Assert(scanner.Scan(), jc.IsTrue) line := scanner.Text() - c.Assert(line, gc.Matches, "Exposing @.* introspection socket on 127.0.0.1:.*") + c.Assert(line, gc.Matches, "Exposing .* introspection socket on 127.0.0.1:.*") fields := strings.Fields(line) addr := fields[len(fields)-1] @@ -221,16 +231,12 @@ func newServer(l net.Listener) *http.Server { return srv } -var flagListen = flag.String("run-listen", "", "Name of the Unix socket to connect the introspect command to using --listen=:0") +var flagListen = flag.String("run-listen", "", "DataDir of the Unix socket to connect the introspect command to using --listen=:0") func TestRunListen(t *stdtesting.T) { if *flagListen != "" { - introspectCommand := &introspect.IntrospectCommand{ - IntrospectionSocketName: func(names.Tag) string { - return *flagListen - }, - } - args := append(flag.Args(), "--listen=127.0.0.1:0", "--agent=machine-0") + introspectCommand := &introspect.IntrospectCommand{} + args := append(flag.Args(), "--data-dir="+*flagListen, "--listen=127.0.0.1:0", "--agent=machine-0") if err := cmdtesting.InitCommand(introspectCommand, args); err != nil { t.Fatal(err) }
cmd/jujud/main.go+1 −2 modified@@ -26,7 +26,6 @@ import ( "github.com/juju/utils/v3/exec" "github.com/juju/version/v2" - "github.com/juju/juju/agent/addons" k8sexec "github.com/juju/juju/caas/kubernetes/provider/exec" jujucmd "github.com/juju/juju/cmd" agentcmd "github.com/juju/juju/cmd/jujud/agent" @@ -40,6 +39,7 @@ import ( coreos "github.com/juju/juju/core/os" jujunames "github.com/juju/juju/juju/names" "github.com/juju/juju/juju/sockets" + // Import the providers. _ "github.com/juju/juju/provider/all" "github.com/juju/juju/upgrades" @@ -261,7 +261,6 @@ func jujuDMain(args []string, ctx *cmd.Context) (code int, err error) { machineAgentFactory := agentcmd.MachineAgentFactoryFn( agentConf, bufferedLogger, - addons.DefaultIntrospectionSocketName, upgrades.PreUpgradeSteps, "", )
featuretests/dblog_test.go+0 −2 modified@@ -18,7 +18,6 @@ import ( gc "gopkg.in/check.v1" "github.com/juju/juju/agent" - "github.com/juju/juju/agent/addons" apiclient "github.com/juju/juju/api/client/client" "github.com/juju/juju/api/common" "github.com/juju/juju/caas/kubernetes/provider" @@ -106,7 +105,6 @@ func (s *dblogSuite) assertAgentLogsGoToDB(c *gc.C, tag names.Tag, isCaas bool) machineAgentFactory := agentcmd.MachineAgentFactoryFn( aCfg, logger, - addons.DefaultIntrospectionSocketName, noPreUpgradeSteps, c.MkDir(), )
state/backups/files.go+25 −5 modified@@ -4,6 +4,8 @@ package backups import ( + "fmt" + "io/fs" "os" "path/filepath" "sort" @@ -107,17 +109,35 @@ func GetFilesToBackUp(rootDir string, paths *Paths) ([]string, error) { } // Handle user SSH files (might not exist). - SSHDir := filepath.Join(rootDir, sshDir) - if _, err := os.Stat(SSHDir); err != nil { + authorizedKeysFile := filepath.Join(rootDir, sshDir, authKeysFile) + if _, err := os.Stat(authorizedKeysFile); err != nil { if !os.IsNotExist(err) { return nil, errors.Trace(err) } - logger.Errorf("skipping missing dir %q", SSHDir) + logger.Errorf("skipping missing file %q", authorizedKeysFile) } else { - backupFiles = append(backupFiles, filepath.Join(SSHDir, authKeysFile)) + backupFiles = append(backupFiles, authorizedKeysFile) } - return backupFiles, nil + var finalBackupFiles []string + for _, file := range backupFiles { + err := filepath.Walk(file, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + if info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 { + finalBackupFiles = append(finalBackupFiles, path) + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("cannot walk %q: %w", file, err) + } + } + return finalBackupFiles, nil } // replaceableFolders for testing purposes.
state/backups/files_test.go+28 −15 modified@@ -17,6 +17,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + "github.com/juju/juju/juju/sockets" "github.com/juju/juju/mongo" "github.com/juju/juju/state/backups" "github.com/juju/juju/testing" @@ -60,6 +61,12 @@ func (s *filesSuite) createFiles(c *gc.C, paths backups.Paths, root, machineID s c.Assert(err, jc.ErrorIsNil) file.Close() } + socket := func(dirname, name string) { + path := filepath.Join(dirname, name) + l, err := sockets.Listen(sockets.Socket{Network: "unix", Address: path}) + c.Assert(err, jc.ErrorIsNil) + l.Close() + } dirname := mkdir(paths.DataDir) touch(dirname, "system-identity") @@ -71,10 +78,12 @@ func (s *filesSuite) createFiles(c *gc.C, paths backups.Paths, root, machineID s } else { touch(dirname, "shared-secret") } - mkdir(filepath.Join(paths.DataDir, "tools")) + dirname = mkdir(filepath.Join(paths.DataDir, "tools")) + touch(dirname, "a-tool") - dirname = mkdir(filepath.Join(paths.DataDir, "agents")) - touch(dirname, "machine-"+machineID+".conf") + dirname = mkdir(filepath.Join(paths.DataDir, "agents", "machine-"+machineID)) + touch(dirname, "agent.conf") + socket(dirname, "introspection.socket") dirname = mkdir("/home/ubuntu/.ssh") touch(dirname, "authorized_keys") @@ -125,17 +134,23 @@ func (s *filesSuite) TestGetFilesToBackUp(c *gc.C) { expected := []string{ filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"), - filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"), - filepath.Join(s.root, "/var/lib/juju/agents/machine-1.conf"), + filepath.Join(s.root, "/var/lib/juju/agents/machine-0/agent.conf"), + filepath.Join(s.root, "/var/lib/juju/agents/machine-1/agent.conf"), filepath.Join(s.root, "/var/lib/juju/nonce.txt"), filepath.Join(s.root, "/var/lib/juju/server.pem"), filepath.Join(s.root, "/var/lib/juju/shared-secret"), filepath.Join(s.root, "/var/lib/juju/system-identity"), - filepath.Join(s.root, "/var/lib/juju/tools"), - filepath.Join(s.root, "/var/lib/juju/init/juju-db"), + filepath.Join(s.root, "/var/lib/juju/tools/a-tool"), + filepath.Join(s.root, "/var/lib/juju/init/juju-db/juju-db.service"), } c.Check(files, jc.SameContents, expected) s.checkSameStrings(c, files, expected) + + // Check the introspection sockets are not Tar'd up. + _, err = os.Stat(filepath.Join(s.root, "/var/lib/juju/agents/machine-0/introspection.socket")) + c.Assert(err, jc.ErrorIsNil) + _, err = os.Stat(filepath.Join(s.root, "/var/lib/juju/agents/machine-1/introspection.socket")) + c.Assert(err, jc.ErrorIsNil) } func (s *filesSuite) TestDirectoriesCleaned(c *gc.C) { @@ -249,15 +264,13 @@ func (s *filesSuite) TestGetFilesToBackUpMissing(c *gc.C) { c.Assert(err, jc.ErrorIsNil) expected := []string{ - filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"), + filepath.Join(s.root, "/var/lib/juju/agents/machine-0/agent.conf"), filepath.Join(s.root, "/var/lib/juju/server.pem"), filepath.Join(s.root, "/var/lib/juju/shared-secret"), filepath.Join(s.root, "/var/lib/juju/system-identity"), - filepath.Join(s.root, "/var/lib/juju/tools"), - filepath.Join(s.root, "/var/lib/juju/init/juju-db"), + filepath.Join(s.root, "/var/lib/juju/tools/a-tool"), + filepath.Join(s.root, "/var/lib/juju/init/juju-db/juju-db.service"), } - // This got re-created. - expected = append(expected, filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys")) c.Check(files, jc.SameContents, expected) s.checkSameStrings(c, files, expected) } @@ -274,13 +287,13 @@ func (s *filesSuite) TestGetFilesToBackUpSnap(c *gc.C) { expected := []string{ filepath.Join(s.root, "/home/ubuntu/.ssh/authorized_keys"), - filepath.Join(s.root, "/var/lib/juju/agents/machine-0.conf"), + filepath.Join(s.root, "/var/lib/juju/agents/machine-0/agent.conf"), filepath.Join(s.root, "/var/lib/juju/nonce.txt"), filepath.Join(s.root, "/var/lib/juju/server.pem"), filepath.Join(s.root, "/var/snap/juju-db/common/shared-secret"), filepath.Join(s.root, "/var/lib/juju/system-identity"), - filepath.Join(s.root, "/var/lib/juju/tools"), - filepath.Join(s.root, "/var/lib/juju/init/juju-db"), + filepath.Join(s.root, "/var/lib/juju/tools/a-tool"), + filepath.Join(s.root, "/var/lib/juju/init/juju-db/juju-db.service"), } c.Check(files, jc.SameContents, expected) s.checkSameStrings(c, files, expected)
worker/deployer/unit_agent.go+1 −2 modified@@ -225,9 +225,8 @@ func (a *UnitAgent) start() (worker.Worker, error) { a.mu.Unlock() }() if err := addons.StartIntrospection(addons.IntrospectionConfig{ - AgentTag: a.CurrentConfig().Tag(), + AgentDir: a.CurrentConfig().Dir(), Engine: engine, - NewSocketName: addons.DefaultIntrospectionSocketName, PrometheusGatherer: a.prometheusRegistry, MachineLock: machineLock, WorkerFunc: introspection.NewWorker,
worker/introspection/script.go+5 −1 modified@@ -42,7 +42,11 @@ const shellFuncs = ` juju_agent_call () { local agent=$1 shift - juju-introspect --agent=$agent $@ + if [ -x "$(which sudo)" ]; then + sudo juju-introspect --agent=$agent $@ + else + juju-introspect --agent=$agent $@ + fi } juju_machine_agent_name () {
worker/introspection/worker.go+7 −9 modified@@ -23,6 +23,7 @@ import ( "github.com/juju/juju/cmd/output" "github.com/juju/juju/core/machinelock" "github.com/juju/juju/core/presence" + "github.com/juju/juju/juju/sockets" "github.com/juju/juju/pubsub/agent" "github.com/juju/juju/worker/introspection/pprof" ) @@ -98,7 +99,7 @@ func (c *Config) Validate() error { // socketListener is a worker and constructed with NewWorker. type socketListener struct { tomb tomb.Tomb - listener *net.UnixListener + listener net.Listener depEngine DepEngineReporter statePool Reporter pubsub Reporter @@ -122,17 +123,14 @@ func NewWorker(config Config) (worker.Worker, error) { return nil, errors.NotSupportedf("os %q", runtime.GOOS) } - path := "@" + config.SocketName - addr, err := net.ResolveUnixAddr("unix", path) - if err != nil { - return nil, errors.Annotate(err, "unable to resolve unix socket") - } - - l, err := net.ListenUnix("unix", addr) + l, err := sockets.Listen(sockets.Socket{ + Network: "unix", + Address: config.SocketName, + }) if err != nil { return nil, errors.Annotate(err, "unable to listen on unix socket") } - logger.Debugf("introspection worker listening on %q", path) + logger.Debugf("introspection worker listening on %q", config.SocketName) w := &socketListener{ listener: l,
worker/introspection/worker_test.go+6 −4 modified@@ -11,6 +11,7 @@ import ( "net/http" "net/url" "os" + "path" "runtime" "strings" "time" @@ -64,8 +65,9 @@ func (s *suite) TestStartStop(c *gc.C) { c.Skip("introspection worker not supported on non-linux") } + socketName := path.Join(c.MkDir(), "introspection-test") w, err := introspection.NewWorker(introspection.Config{ - SocketName: "introspection-test", + SocketName: socketName, PrometheusGatherer: prometheus.NewRegistry(), }) c.Assert(err, jc.ErrorIsNil) @@ -105,7 +107,7 @@ func (s *introspectionSuite) SetUpTest(c *gc.C) { } func (s *introspectionSuite) startWorker(c *gc.C) { - s.name = fmt.Sprintf("introspection-test-%d", os.Getpid()) + s.name = path.Join(c.MkDir(), fmt.Sprintf("introspection-test-%d", os.Getpid())) w, err := introspection.NewWorker(introspection.Config{ SocketName: s.name, DepEngine: s.reporter, @@ -124,7 +126,7 @@ func (s *introspectionSuite) startWorker(c *gc.C) { } func (s *introspectionSuite) call(c *gc.C, path string) *http.Response { - client := unixSocketHTTPClient("@" + s.name) + client := unixSocketHTTPClient(s.name) c.Assert(strings.HasPrefix(path, "/"), jc.IsTrue) targetURL, err := url.Parse("http://unix.socket" + path) c.Assert(err, jc.ErrorIsNil) @@ -135,7 +137,7 @@ func (s *introspectionSuite) call(c *gc.C, path string) *http.Response { } func (s *introspectionSuite) post(c *gc.C, path string, values url.Values) *http.Response { - client := unixSocketHTTPClient("@" + s.name) + client := unixSocketHTTPClient(s.name) c.Assert(strings.HasPrefix(path, "/"), jc.IsTrue) targetURL, err := url.Parse("http://unix.socket" + path) c.Assert(err, jc.ErrorIsNil)
Vulnerability mechanics
Synthesis attempt was rejected by the grounding validator. Re-run pending.
References
7- github.com/advisories/GHSA-xwgj-vpm9-q2rqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-8038ghsaADVISORY
- github.com/juju/juju/blob/725800953aaa29dbeda4f806097bf838e61644dd/worker/introspection/worker.goghsaWEB
- github.com/juju/juju/commit/43f0fc59790d220a457d4d305f484f62be556d3bghsaWEB
- github.com/juju/juju/security/advisories/GHSA-xwgj-vpm9-q2rqghsaissue-trackingWEB
- pkg.go.dev/vuln/GO-2024-3175ghsaWEB
- www.cve.org/CVERecordmitreissue-tracking
News mentions
0No linked articles in our index yet.