podman: new option --preserve-fd

add a new option --preserve-fd that allows to specify a list of FDs to
pass down to the container.

It is similar to --preserve-fds but it allows to specify a list of FDs
instead of the maximum FD number to preserve.

--preserve-fd and --preserve-fds are mutually exclusive.

It requires crun since runc would complain if any fd below
--preserve-fds is not preserved.

Closes: https://github.com/containers/podman/issues/20844

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2023-12-01 11:49:29 +01:00
parent 6b9221d852
commit 01d397a658
19 changed files with 172 additions and 23 deletions

View File

@ -83,6 +83,10 @@ func execFlags(cmd *cobra.Command) {
flags.UintVar(&execOpts.PreserveFDs, preserveFdsFlagName, 0, "Pass N additional file descriptors to the container")
_ = cmd.RegisterFlagCompletionFunc(preserveFdsFlagName, completion.AutocompleteNone)
preserveFdFlagName := "preserve-fd"
flags.UintSliceVar(&execOpts.PreserveFD, preserveFdFlagName, nil, "Pass a list of additional file descriptors to the container")
_ = cmd.RegisterFlagCompletionFunc(preserveFdFlagName, completion.AutocompleteNone)
workdirFlagName := "workdir"
flags.StringVarP(&execOpts.WorkDir, workdirFlagName, "w", "", "Working directory inside the container")
_ = cmd.RegisterFlagCompletionFunc(workdirFlagName, completion.AutocompleteDefault)
@ -139,6 +143,12 @@ func exec(cmd *cobra.Command, args []string) error {
execOpts.Envs = envLib.Join(execOpts.Envs, cliEnv)
for _, fd := range execOpts.PreserveFD {
if !rootless.IsFdInherited(int(fd)) {
return fmt.Errorf("file descriptor %d is not available - the preserve-fd option requires that file descriptors must be passed", fd)
}
}
for fd := 3; fd < int(3+execOpts.PreserveFDs); fd++ {
if !rootless.IsFdInherited(fd) {
return fmt.Errorf("file descriptor %d is not available - the preserve-fds option requires that file descriptors must be passed", fd)

View File

@ -67,9 +67,13 @@ func runFlags(cmd *cobra.Command) {
flags.BoolVar(&runRmi, "rmi", false, "Remove image unless used by other containers, implies --rm")
preserveFdsFlagName := "preserve-fds"
flags.UintVar(&runOpts.PreserveFDs, "preserve-fds", 0, "Pass a number of additional file descriptors into the container")
flags.UintVar(&runOpts.PreserveFDs, preserveFdsFlagName, 0, "Pass a number of additional file descriptors into the container")
_ = cmd.RegisterFlagCompletionFunc(preserveFdsFlagName, completion.AutocompleteNone)
preserveFdFlagName := "preserve-fd"
flags.UintSliceVar(&runOpts.PreserveFD, preserveFdFlagName, nil, "Pass a file descriptor into the container")
_ = cmd.RegisterFlagCompletionFunc(preserveFdFlagName, completion.AutocompleteNone)
flags.BoolVarP(&runOpts.Detach, "detach", "d", false, "Run container in background and print container ID")
detachKeysFlagName := "detach-keys"
@ -85,7 +89,8 @@ func runFlags(cmd *cobra.Command) {
flags.BoolVar(&runOpts.Passwd, passwdFlagName, true, "add entries to /etc/passwd and /etc/group")
if registry.IsRemote() {
_ = flags.MarkHidden("preserve-fds")
_ = flags.MarkHidden(preserveFdsFlagName)
_ = flags.MarkHidden(preserveFdFlagName)
_ = flags.MarkHidden("conmon-pidfile")
_ = flags.MarkHidden("pidfile")
}
@ -135,6 +140,11 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
for _, fd := range runOpts.PreserveFD {
if !rootless.IsFdInherited(int(fd)) {
return fmt.Errorf("file descriptor %d is not available - the preserve-fd option requires that file descriptors must be passed", fd)
}
}
for fd := 3; fd < int(3+runOpts.PreserveFDs); fd++ {
if !rootless.IsFdInherited(fd) {
return fmt.Errorf("file descriptor %d is not available - the preserve-fds option requires that file descriptors must be passed", fd)
@ -196,6 +206,7 @@ func run(cmd *cobra.Command, args []string) error {
}
cliVals.PreserveFDs = runOpts.PreserveFDs
cliVals.PreserveFD = runOpts.PreserveFD
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
return err