From 38ca0129a8c697b9523ce75c0b343da07de5279d Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 15:17:31 +0000 Subject: [PATCH 1/3] fix(agent/agentcontainers): chown coder binary --- agent/agentcontainers/api.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/agent/agentcontainers/api.go b/agent/agentcontainers/api.go index 0f8fd3e380932..257a971e0255b 100644 --- a/agent/agentcontainers/api.go +++ b/agent/agentcontainers/api.go @@ -1442,6 +1442,11 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c return xerrors.Errorf("set agent binary executable: %w", err) } + // Make sure the agent binary is executable so we can run it. + if _, err := api.ccli.ExecAs(ctx, container.ID, "root", "/bin/sh", "-c", fmt.Sprintf("chown $(id -u):$(id -g) %s", coderPathInsideContainer)); err != nil { + return xerrors.Errorf("set agent binary executable: %w", err) + } + // Attempt to add CAP_NET_ADMIN to the binary to improve network // performance (optional, allow to fail). See `bootstrap_linux.sh`. // TODO(mafredri): Disable for now until we can figure out why this From cb0786ef0601f4e64c3cef9b4b5b6bc8091f2cb7 Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 15:24:52 +0000 Subject: [PATCH 2/3] fix: tests that use mocking --- agent/agentcontainers/api_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/agent/agentcontainers/api_test.go b/agent/agentcontainers/api_test.go index 33f35e2b21602..7c9b7ce0f632d 100644 --- a/agent/agentcontainers/api_test.go +++ b/agent/agentcontainers/api_test.go @@ -1392,6 +1392,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), "test-container-id", coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) mClock.Set(time.Now()).MustWait(ctx) @@ -1480,6 +1481,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), "test-container-id", coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), "test-container-id", "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) // Verify that the agent has started. @@ -1540,6 +1542,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), "new-test-container-id", "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), "new-test-container-id", coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), "new-test-container-id", "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), "new-test-container-id", "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) fakeDCCLI.readConfig.MergedConfiguration.Customizations.Coder = []agentcontainers.CoderCustomization{ @@ -1941,6 +1944,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), testContainer.ID, coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) mClock.Set(time.Now()).MustWait(ctx) @@ -2034,6 +2038,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), testContainer.ID, coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) mClock.Set(time.Now()).MustWait(ctx) @@ -2138,6 +2143,7 @@ func TestAPI(t *testing.T) { mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "mkdir", "-p", "/.coder-agent").Return(nil, nil), mCCLI.EXPECT().Copy(gomock.Any(), testContainer.ID, coderBin, "/.coder-agent/coder").Return(nil), mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "chmod", "0755", "/.coder-agent", "/.coder-agent/coder").Return(nil, nil), + mCCLI.EXPECT().ExecAs(gomock.Any(), testContainer.ID, "root", "/bin/sh", "-c", "chown $(id -u):$(id -g) /.coder-agent/coder").Return(nil, nil), ) mClock.Set(time.Now()).MustWait(ctx) From 6e5373cea30e31627c28bcfc58aaa1b8e321a32d Mon Sep 17 00:00:00 2001 From: Danielle Maywood Date: Thu, 26 Jun 2025 16:29:09 +0100 Subject: [PATCH 3/3] chore: copilot feedback Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- agent/agentcontainers/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/agentcontainers/api.go b/agent/agentcontainers/api.go index 257a971e0255b..dcb9a7b0e2372 100644 --- a/agent/agentcontainers/api.go +++ b/agent/agentcontainers/api.go @@ -1444,7 +1444,7 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c // Make sure the agent binary is executable so we can run it. if _, err := api.ccli.ExecAs(ctx, container.ID, "root", "/bin/sh", "-c", fmt.Sprintf("chown $(id -u):$(id -g) %s", coderPathInsideContainer)); err != nil { - return xerrors.Errorf("set agent binary executable: %w", err) + return xerrors.Errorf("set agent binary ownership: %w", err) } // Attempt to add CAP_NET_ADMIN to the binary to improve network