libpod: use /var/run instead of /run on FreeBSD

This changes /run to /var/run for .containerenv and secrets in FreeBSD
containers for consistency with FreeBSD path conventions. Running Linux
containers on FreeBSD hosts continue to use /run for compatibility.

[NO NEW TESTS NEEDED]

Signed-off-by: Doug Rabson <dfr@rabson.org>
This commit is contained in:
Doug Rabson
2023-08-17 14:04:23 +01:00
parent e0b8178ad0
commit 27b41f0877
9 changed files with 87 additions and 15 deletions

View File

@ -26,7 +26,9 @@ Secret Options
- `target=target` : Target of secret. - `target=target` : Target of secret.
For mounted secrets, this is the path to the secret inside the container. For mounted secrets, this is the path to the secret inside the container.
If a fully qualified path is provided, the secret is mounted at that location. If a fully qualified path is provided, the secret is mounted at that location.
Otherwise, the secret is mounted to `/run/secrets/target`. Otherwise, the secret is mounted to
`/run/secrets/target` for linux containers or
`/var/run/secrets/target` for freebsd containers.
If the target is not set, the secret is mounted to `/run/secrets/secretname` by default. If the target is not set, the secret is mounted to `/run/secrets/secretname` by default.
For env secrets, this is the environment variable key. Defaults to `secretname`. For env secrets, this is the environment variable key. Defaults to `secretname`.
- `uid=0` : UID of secret. Defaults to 0. Mount secret type only. - `uid=0` : UID of secret. Defaults to 0. Mount secret type only.

View File

@ -28,7 +28,8 @@ These will be based on the host's version of the files, though they can be
customized with options (for example, **--dns** will override the host's DNS customized with options (for example, **--dns** will override the host's DNS
servers in the created _resolv.conf_). Additionally, a container environment servers in the created _resolv.conf_). Additionally, a container environment
file is created in each container to indicate to programs they are running in a file is created in each container to indicate to programs they are running in a
container. This file is located at _/run/.containerenv_. When using the container. This file is located at _/run/.containerenv_ (or
_/var/run/.containerenv_ for FreeBSD containers). When using the
--privileged flag the .containerenv contains name/value pairs indicating the --privileged flag the .containerenv contains name/value pairs indicating the
container engine version, whether the engine is running in rootless mode, the container engine version, whether the engine is running in rootless mode, the
container name and ID, as well as the image name and ID that the container is based on. Note: _/run/.containerenv_ will not be created when a volume is mounted on /run. container name and ID, as well as the image name and ID that the container is based on. Note: _/run/.containerenv_ will not be created when a volume is mounted on /run.

View File

@ -1953,16 +1953,22 @@ func (c *Container) makeBindMounts() error {
} }
} }
_, hasRunContainerenv := c.state.BindMounts["/run/.containerenv"] runPath, err := c.getPlatformRunPath()
if err != nil {
return fmt.Errorf("cannot determine run directory for container: %w", err)
}
containerenvPath := filepath.Join(runPath, ".containerenv")
_, hasRunContainerenv := c.state.BindMounts[containerenvPath]
if !hasRunContainerenv { if !hasRunContainerenv {
Loop: Loop:
// check in the spec mounts // check in the spec mounts
for _, m := range c.config.Spec.Mounts { for _, m := range c.config.Spec.Mounts {
switch { switch {
case m.Destination == "/run/.containerenv": case m.Destination == containerenvPath:
hasRunContainerenv = true hasRunContainerenv = true
break Loop break Loop
case m.Destination == "/run" && m.Type != define.TypeTmpfs: case m.Destination == runPath && m.Type != define.TypeTmpfs:
hasRunContainerenv = true hasRunContainerenv = true
break Loop break Loop
} }
@ -1988,11 +1994,11 @@ imageid=%q
rootless=%d rootless=%d
%s`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless, containerenv) %s`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless, containerenv)
} }
containerenvPath, err := c.writeStringToRundir(".containerenv", containerenv) containerenvHostPath, err := c.writeStringToRundir(".containerenv", containerenv)
if err != nil { if err != nil {
return fmt.Errorf("creating containerenv file for container %s: %w", c.ID(), err) return fmt.Errorf("creating containerenv file for container %s: %w", c.ID(), err)
} }
c.state.BindMounts["/run/.containerenv"] = containerenvPath c.state.BindMounts[containerenvPath] = containerenvHostPath
} }
// Add Subscription Mounts // Add Subscription Mounts
@ -2010,12 +2016,12 @@ rootless=%d
// creates the /run/secrets dir in the container where we mount as well. // creates the /run/secrets dir in the container where we mount as well.
if len(c.Secrets()) > 0 { if len(c.Secrets()) > 0 {
// create /run/secrets if subscriptions did not create // create /run/secrets if subscriptions did not create
if err := c.createSecretMountDir(); err != nil { if err := c.createSecretMountDir(runPath); err != nil {
return fmt.Errorf("creating secrets mount: %w", err) return fmt.Errorf("creating secrets mount: %w", err)
} }
for _, secret := range c.Secrets() { for _, secret := range c.Secrets() {
secretFileName := secret.Name secretFileName := secret.Name
base := "/run/secrets" base := filepath.Join(runPath, "secrets")
if secret.Target != "" { if secret.Target != "" {
secretFileName = secret.Target secretFileName = secret.Target
// If absolute path for target given remove base. // If absolute path for target given remove base.
@ -2797,7 +2803,7 @@ func (c *Container) cleanupOverlayMounts() error {
} }
// Creates and mounts an empty dir to mount secrets into, if it does not already exist // Creates and mounts an empty dir to mount secrets into, if it does not already exist
func (c *Container) createSecretMountDir() error { func (c *Container) createSecretMountDir(runPath string) error {
src := filepath.Join(c.state.RunDir, "/run/secrets") src := filepath.Join(c.state.RunDir, "/run/secrets")
_, err := os.Stat(src) _, err := os.Stat(src)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -2810,7 +2816,7 @@ func (c *Container) createSecretMountDir() error {
if err := os.Chown(src, c.RootUID(), c.RootGID()); err != nil { if err := os.Chown(src, c.RootUID(), c.RootGID()); err != nil {
return err return err
} }
c.state.BindMounts["/run/secrets"] = src c.state.BindMounts[filepath.Join(runPath, "secrets")] = src
return nil return nil
} }

View File

@ -365,3 +365,23 @@ func (c *Container) makePlatformMtabLink(etcInTheContainerFd, rootUID, rootGID i
// /etc/mtab does not exist on FreeBSD // /etc/mtab does not exist on FreeBSD
return nil return nil
} }
func (c *Container) getPlatformRunPath() (string, error) {
// If we have a linux image, use "/run", otherwise use "/var/run" for
// consistency with FreeBSD path conventions.
runPath := "/var/run"
if c.config.RootfsImageID != "" {
image, _, err := c.runtime.libimageRuntime.LookupImage(c.config.RootfsImageID, nil)
if err != nil {
return "", err
}
inspectData, err := image.Inspect(nil, nil)
if err != nil {
return "", err
}
if inspectData.Os == "linux" {
runPath = "/run"
}
}
return runPath, nil
}

View File

@ -801,3 +801,7 @@ func (c *Container) makePlatformMtabLink(etcInTheContainerFd, rootUID, rootGID i
} }
return nil return nil
} }
func (c *Container) getPlatformRunPath() (string, error) {
return "/run", nil
}

View File

@ -424,6 +424,8 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
g.RemoveMount("/etc/hosts") g.RemoveMount("/etc/hosts")
g.RemoveMount("/run/.containerenv") g.RemoveMount("/run/.containerenv")
g.RemoveMount("/run/secrets") g.RemoveMount("/run/secrets")
g.RemoveMount("/var/run/.containerenv")
g.RemoveMount("/var/run/secrets")
// Regenerate Cgroup paths so they don't point to the old // Regenerate Cgroup paths so they don't point to the old
// container ID. // container ID.

View File

@ -176,7 +176,11 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
} }
if s.ReadWriteTmpfs { if s.ReadWriteTmpfs {
baseMounts = addReadWriteTmpfsMounts(baseMounts, s.Volumes) runPath, err := imageRunPath(ctx, img)
if err != nil {
return nil, nil, nil, err
}
baseMounts = addReadWriteTmpfsMounts(baseMounts, s.Volumes, runPath)
} }
// Final step: maps to arrays // Final step: maps to arrays
@ -440,8 +444,8 @@ func InitFSMounts(mounts []spec.Mount) error {
return nil return nil
} }
func addReadWriteTmpfsMounts(mounts map[string]spec.Mount, volumes []*specgen.NamedVolume) map[string]spec.Mount { func addReadWriteTmpfsMounts(mounts map[string]spec.Mount, volumes []*specgen.NamedVolume, runPath string) map[string]spec.Mount {
readonlyTmpfs := []string{"/tmp", "/var/tmp", "/run"} readonlyTmpfs := []string{"/tmp", "/var/tmp", runPath}
options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup"} options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup"}
for _, dest := range readonlyTmpfs { for _, dest := range readonlyTmpfs {
if _, ok := mounts[dest]; ok { if _, ok := mounts[dest]; ok {
@ -458,7 +462,7 @@ func addReadWriteTmpfsMounts(mounts map[string]spec.Mount, volumes []*specgen.Na
Source: define.TypeTmpfs, Source: define.TypeTmpfs,
Options: options, Options: options,
} }
if dest != "/run" { if dest != runPath {
mnt.Options = append(mnt.Options, "noexec") mnt.Options = append(mnt.Options, "noexec")
} }
mounts[dest] = mnt mounts[dest] = mnt

View File

@ -0,0 +1,22 @@
package generate
import (
"context"
"github.com/containers/common/libimage"
)
func imageRunPath(ctx context.Context, img *libimage.Image) (string, error) {
if img != nil {
inspectData, err := img.Inspect(ctx, nil)
if err != nil {
return "", err
}
if inspectData.Os == "freebsd" {
return "/var/run", nil
}
return "/run", nil
} else {
return "/var/run", nil
}
}

View File

@ -0,0 +1,11 @@
package generate
import (
"context"
"github.com/containers/common/libimage"
)
func imageRunPath(ctx context.Context, img *libimage.Image) (string, error) {
return "/run", nil
}