-
Notifications
You must be signed in to change notification settings - Fork 2.3k
libct: setns process recreate cmd object before calling the first start #5066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,14 +14,17 @@ import ( | |
| "strings" | ||
| "syscall" | ||
| "testing" | ||
| "time" | ||
|
|
||
| securejoin "github.com/cyphar/filepath-securejoin" | ||
| "github.com/opencontainers/cgroups" | ||
| "github.com/opencontainers/cgroups/systemd" | ||
| "github.com/opencontainers/runc/internal/linux" | ||
| "github.com/opencontainers/runc/internal/pathrs" | ||
| "github.com/opencontainers/runc/libcontainer" | ||
| "github.com/opencontainers/runc/libcontainer/configs" | ||
| "github.com/opencontainers/runc/libcontainer/internal/userns" | ||
| "github.com/opencontainers/runc/libcontainer/utils" | ||
| "github.com/opencontainers/runtime-spec/specs-go" | ||
|
|
||
| "golang.org/x/sys/unix" | ||
|
|
@@ -231,6 +234,124 @@ func TestEnter(t *testing.T) { | |
| } | ||
| } | ||
|
|
||
| const stateFilename = "state.json" | ||
|
|
||
| // We need to dump changed state into state file. | ||
| func saveState(stateDir string, s *libcontainer.State) (retErr error) { | ||
| tmpFile, err := os.CreateTemp(stateDir, "state-") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| defer func() { | ||
| if retErr != nil { | ||
| tmpFile.Close() | ||
| os.Remove(tmpFile.Name()) | ||
| } | ||
| }() | ||
|
|
||
| err = utils.WriteJSON(tmpFile, s) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| err = tmpFile.Close() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| stateFilePath := filepath.Join(stateDir, stateFilename) | ||
| return os.Rename(tmpFile.Name(), stateFilePath) | ||
| } | ||
|
|
||
| func TestCmdRetry(t *testing.T) { | ||
| if testing.Short() { | ||
| return | ||
| } | ||
|
|
||
| if !cgroups.IsCgroup2UnifiedMode() { | ||
| t.Skip("CLONE_INTO_CGROUP works only with cgroup v2") | ||
| } | ||
|
|
||
| // Create dir to "pseudo" cgroup path | ||
| pseudoPath := t.TempDir() | ||
|
|
||
| config := newTemplateConfig(t, nil) | ||
|
|
||
| name := strings.ReplaceAll(t.Name(), "/", "_") + strconv.FormatInt(-int64(time.Now().Nanosecond()), 35) | ||
| root := t.TempDir() | ||
|
|
||
| // Container State Dir | ||
| stateDir, err := securejoin.SecureJoin(root, name) | ||
| ok(t, err) | ||
|
|
||
| // Create Container | ||
| container, err := libcontainer.Create(root, name, config) | ||
|
|
||
| ok(t, err) | ||
| defer destroyContainer(container) | ||
|
|
||
| // Execute a first process in the container | ||
| stdinR, stdinW, err := os.Pipe() | ||
| ok(t, err) | ||
|
|
||
| var stdout, stdout2 bytes.Buffer | ||
|
|
||
| pconfig := libcontainer.Process{ | ||
| Cwd: "/", | ||
| Args: []string{"sh", "-c", "cat"}, | ||
| Env: standardEnvironment, | ||
| Stdin: stdinR, | ||
| Stdout: &stdout, | ||
| Init: true, | ||
| } | ||
|
|
||
| err = container.Run(&pconfig) | ||
| _ = stdinR.Close() | ||
| defer stdinW.Close() | ||
| ok(t, err) | ||
|
|
||
| state, err := container.State() | ||
| ok(t, err) | ||
|
|
||
| // Dump our "pseudo" cgroup path as dirPath | ||
| state.CgroupPaths[""] = pseudoPath | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This assumes (and will work only with) cgroup v2
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have checked the cgroup version in the call of cgroups.IsCgroup2UnifiedMode. As for cgroup v1 it is deprecated :) #4955 . |
||
| err = saveState(stateDir, state) | ||
| ok(t, err) | ||
|
|
||
| // Load container from dumped state | ||
| container2, err := libcontainer.Load(root, name) | ||
| ok(t, err) | ||
|
|
||
| // Execute another process in the container | ||
| stdinR2, stdinW2, err := os.Pipe() | ||
| ok(t, err) | ||
| pconfig2 := libcontainer.Process{ | ||
| Cwd: "/", | ||
| Env: standardEnvironment, | ||
| } | ||
| pconfig2.Args = []string{"sh", "-c", "cat"} | ||
| pconfig2.Stdin = stdinR2 | ||
| pconfig2.Stdout = &stdout2 | ||
|
|
||
| // Turn on TestMode in cgroups library to not check path mode and create all necessary files. | ||
| cgroups.TestMode = true | ||
| defer func() { | ||
| cgroups.TestMode = false | ||
| }() | ||
|
|
||
| err = container2.Run(&pconfig2) | ||
| _ = stdinR2.Close() | ||
| defer stdinW2.Close() | ||
| ok(t, err) | ||
|
|
||
| // Wait processes | ||
| _ = stdinW2.Close() | ||
| waitProcess(&pconfig2, t) | ||
|
|
||
| _ = stdinW.Close() | ||
| waitProcess(&pconfig, t) | ||
| } | ||
|
|
||
| func TestProcessEnv(t *testing.T) { | ||
| if testing.Short() { | ||
| return | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect this commit (" libct: add Container method to recreate cmd Object in setnsProcess") to only move cmd.* assignments to a function that we then just call. And keep all the sealing of the binary untouched.
Is not possible to do something like that, that is super straight-forward?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I have kept the sealing untouched. I have deleted only exePath (it is not used in this function). In createCmdObject function I use the created safeExe if runc binary is cloned. I can move createCmdObject after newParentProcess function that's why there won't be any changes in newParentProcess function header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I can keep the function signatures and should create cmd without cgroup fd. In Setns Process Cmd retry it will be ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is we create a function that does the cmd and the commit is just moving
cmd.X = asdlines from one place to the other. That will be quite clear we are not missing anything.