summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/markdown/.gitignore1
-rw-r--r--docs/source/markdown/options/interactive.md3
-rw-r--r--docs/source/markdown/options/preserve-fds.md5
-rw-r--r--docs/source/markdown/options/tty.md9
-rw-r--r--docs/source/markdown/options/user.md7
-rw-r--r--docs/source/markdown/podman-create.1.md.in24
-rw-r--r--docs/source/markdown/podman-exec.1.md.in18
-rw-r--r--docs/source/markdown/podman-run.1.md.in27
-rw-r--r--docs/source/markdown/podman-start.1.md.in (renamed from docs/source/markdown/podman-start.1.md)4
-rw-r--r--libpod/container.go4
-rw-r--r--libpod/container_internal_common.go4
-rw-r--r--libpod/container_path_resolution.go30
-rw-r--r--libpod/container_path_resolution_test.go28
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--test/e2e/run_working_dir_test.go9
-rw-r--r--test/system/035-logs.bats23
-rw-r--r--test/system/045-start.bats2
-rw-r--r--test/system/420-cgroups.bats5
18 files changed, 129 insertions, 76 deletions
diff --git a/docs/source/markdown/.gitignore b/docs/source/markdown/.gitignore
index 552e6f520..69911b5b8 100644
--- a/docs/source/markdown/.gitignore
+++ b/docs/source/markdown/.gitignore
@@ -26,6 +26,7 @@ podman-push.1.md
podman-rm.1.md
podman-run.1.md
podman-search.1.md
+podman-start.1.md
podman-stop.1.md
podman-unpause.1.md
podman-update.1.md
diff --git a/docs/source/markdown/options/interactive.md b/docs/source/markdown/options/interactive.md
new file mode 100644
index 000000000..a28088368
--- /dev/null
+++ b/docs/source/markdown/options/interactive.md
@@ -0,0 +1,3 @@
+#### **--interactive**, **-i**
+
+When set to **true**, keep stdin open even if not attached. The default is **false**.
diff --git a/docs/source/markdown/options/preserve-fds.md b/docs/source/markdown/options/preserve-fds.md
new file mode 100644
index 000000000..61e33bdf4
--- /dev/null
+++ b/docs/source/markdown/options/preserve-fds.md
@@ -0,0 +1,5 @@
+#### **--preserve-fds**=*N*
+
+Pass down to the process N additional file descriptors (in addition to 0, 1, 2).
+The total FDs will be 3+N.
+(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
diff --git a/docs/source/markdown/options/tty.md b/docs/source/markdown/options/tty.md
new file mode 100644
index 000000000..04bd8af2c
--- /dev/null
+++ b/docs/source/markdown/options/tty.md
@@ -0,0 +1,9 @@
+#### **--tty**, **-t**
+
+Allocate a pseudo-TTY. The default is **false**.
+
+When set to **true**, Podman will allocate a pseudo-tty and attach to the standard
+input of the container. This can be used, for example, to run a throwaway
+interactive shell.
+
+**NOTE**: The --tty flag prevents redirection of standard output. It combines STDOUT and STDERR, it can insert control characters, and it can hang pipes. This option should only be used when run interactively in a terminal. When feeding input to Podman, use -i only, not -it.
diff --git a/docs/source/markdown/options/user.md b/docs/source/markdown/options/user.md
new file mode 100644
index 000000000..6cf12d347
--- /dev/null
+++ b/docs/source/markdown/options/user.md
@@ -0,0 +1,7 @@
+#### **--user**, **-u**=*user[:group]*
+
+Sets the username or UID used and, optionally, the groupname or GID for the specified command. Both *user* and *group* may be symbolic or numeric.
+
+Without this argument, the command will run as the user specified in the container image. Unless overridden by a `USER` command in the Containerfile or by a value passed to this option, this user generally defaults to root.
+
+When a user namespace is not in use, the UID and GID used within the container and on the host will match. When user namespaces are in use, however, the UID and GID in the container may correspond to another UID and GID on the host. In rootless containers, for example, a user namespace is always used, and root in the container will by default correspond to the UID and GID of the user invoking Podman.
diff --git a/docs/source/markdown/podman-create.1.md.in b/docs/source/markdown/podman-create.1.md.in
index e407ff4d4..020cdc00e 100644
--- a/docs/source/markdown/podman-create.1.md.in
+++ b/docs/source/markdown/podman-create.1.md.in
@@ -224,9 +224,7 @@ pod when that pod is not running.
@@option init-path
-#### **--interactive**, **-i**
-
-Keep STDIN open even if not attached. The default is *false*.
+@@option interactive
@@option ip
@@ -438,16 +436,7 @@ When size is `0`, there is no limit on the amount of memory used for IPC by the
@@option tmpfs
-#### **--tty**, **-t**
-
-Allocate a pseudo-TTY. The default is *false*.
-
-When set to true Podman will allocate a pseudo-tty and attach to the standard
-input of the container. This can be used, for example, to run a throwaway
-interactive shell. The default is false.
-
-Note: The **-t** option is incompatible with a redirection of the Podman client
-standard input.
+@@option tty
@@option tz
@@ -461,14 +450,7 @@ standard input.
@@option unsetenv-all
-#### **--user**, **-u**=*user*
-
-Sets the username or UID used and optionally the groupname or GID for the specified command.
-
-The following examples are all valid:
---user [user | user:group | uid | uid:gid | user:gid | uid:group ]
-
-Without this argument the command will be run as root in the container.
+@@option user
@@option userns.container
diff --git a/docs/source/markdown/podman-exec.1.md.in b/docs/source/markdown/podman-exec.1.md.in
index 0d161ef66..8198c319e 100644
--- a/docs/source/markdown/podman-exec.1.md.in
+++ b/docs/source/markdown/podman-exec.1.md.in
@@ -31,30 +31,20 @@ This option allows arbitrary environment variables that are available for the pr
Read in a line delimited file of environment variables.
-#### **--interactive**, **-i**
-
-When set to true, keep stdin open even if not attached. The default is *false*.
+@@option interactive
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
-#### **--preserve-fds**=*N*
-
-Pass down to the process N additional file descriptors (in addition to 0, 1, 2). The total FDs will be 3+N.
+@@option preserve-fds
@@option privileged
-#### **--tty**, **-t**
-
-Allocate a pseudo-TTY.
-
-#### **--user**, **-u**
+@@option tty
-Sets the username or UID used and optionally the groupname or GID for the specified command.
-The following examples are all valid:
---user [user | user:group | uid | uid:gid | user:gid | uid:group ]
+@@option user
@@option workdir
diff --git a/docs/source/markdown/podman-run.1.md.in b/docs/source/markdown/podman-run.1.md.in
index d9dcd60f9..227eb455c 100644
--- a/docs/source/markdown/podman-run.1.md.in
+++ b/docs/source/markdown/podman-run.1.md.in
@@ -245,9 +245,7 @@ Print usage statement
@@option init-path
-#### **--interactive**, **-i**
-
-When set to **true**, keep stdin open even if not attached. The default is **false**.
+@@option interactive
@@option ip
@@ -366,10 +364,7 @@ If a container is run with a pod, and the pod has an infra-container, the infra-
@@option pod-id-file.container
-#### **--preserve-fds**=*N*
-
-Pass down to the process N additional file descriptors (in addition to 0, 1, 2).
-The total FDs will be 3+N. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
+@@option preserve-fds
@@option privileged
@@ -478,15 +473,7 @@ Sets whether the signals sent to the **podman run** command are proxied to the c
@@option tmpfs
-#### **--tty**, **-t**
-
-Allocate a pseudo-TTY. The default is **false**.
-
-When set to **true**, Podman will allocate a pseudo-tty and attach to the standard
-input of the container. This can be used, for example, to run a throwaway
-interactive shell. The default is **false**.
-
-**NOTE**: The --tty flag prevents redirection of standard output. It combines STDOUT and STDERR, it can insert control characters, and it can hang pipes. This option should only be used when run interactively in a terminal. When feeding input to Podman, use -i only, not -it.
+@@option tty
```
echo "asdf" | podman run --rm -i someimage /bin/cat
@@ -504,13 +491,7 @@ echo "asdf" | podman run --rm -i someimage /bin/cat
@@option unsetenv-all
-#### **--user**, **-u**=*user[:group]*
-
-Sets the username or UID used and, optionally, the groupname or GID for the specified command. Both *user* and *group* may be symbolic or numeric.
-
-Without this argument, the command will run as the user specified in the container image. Unless overridden by a `USER` command in the Containerfile or by a value passed to this option, this user generally defaults to root.
-
-When a user namespace is not in use, the UID and GID used within the container and on the host will match. When user namespaces are in use, however, the UID and GID in the container may correspond to another UID and GID on the host. In rootless containers, for example, a user namespace is always used, and root in the container will by default correspond to the UID and GID of the user invoking Podman.
+@@option user
@@option userns.container
diff --git a/docs/source/markdown/podman-start.1.md b/docs/source/markdown/podman-start.1.md.in
index fd24c6bf4..6fa41018b 100644
--- a/docs/source/markdown/podman-start.1.md
+++ b/docs/source/markdown/podman-start.1.md.in
@@ -53,9 +53,7 @@ Valid filters are listed below:
| pod | [Pod] name or full or partial ID of pod |
| network | [Network] name or full ID of network |
-#### **--interactive**, **-i**
-
-Attach container's STDIN. The default is false.
+@@option interactive
#### **--latest**, **-l**
diff --git a/libpod/container.go b/libpod/container.go
index bdedafd22..cfffd8ea1 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -356,7 +356,9 @@ func (c *Container) specFromState() (*spec.Spec, error) {
return nil, fmt.Errorf("reading container config: %w", err)
}
if err := json.Unmarshal(content, &returnSpec); err != nil {
- return nil, fmt.Errorf("unmarshalling container config: %w", err)
+ // Malformed spec, just use c.config.Spec instead
+ logrus.Warnf("Error unmarshalling container %s config: %v", c.ID(), err)
+ return c.config.Spec, nil
}
} else if !os.IsNotExist(err) {
// ignore when the file does not exist
diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go
index c7f59aba5..9c4a3bb67 100644
--- a/libpod/container_internal_common.go
+++ b/libpod/container_internal_common.go
@@ -531,7 +531,7 @@ func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
}
if resolvedSymlink != "" {
_, resolvedSymlinkWorkdir, err := c.resolvePath(c.state.Mountpoint, resolvedSymlink)
- if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnBindMount(c, resolvedSymlinkWorkdir) {
+ if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnMount(c, resolvedSymlinkWorkdir) {
// Resolved symlink exists on external volume or mount
return true
}
@@ -564,7 +564,7 @@ func (c *Container) resolveWorkDir() error {
// If the specified workdir is a subdir of a volume or mount,
// we don't need to do anything. The runtime is taking care of
// that.
- if isPathOnVolume(c, workdir) || isPathOnBindMount(c, workdir) {
+ if isPathOnVolume(c, workdir) || isPathOnMount(c, workdir) {
logrus.Debugf("Workdir %q resolved to a volume or mount", workdir)
return nil
}
diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go
index 35622d623..cd86df540 100644
--- a/libpod/container_path_resolution.go
+++ b/libpod/container_path_resolution.go
@@ -119,15 +119,29 @@ func findVolume(c *Container, containerPath string) (*Volume, error) {
return nil, nil
}
+// isSubDir checks whether path is a subdirectory of root.
+func isSubDir(path, root string) bool {
+ // check if the specified container path is below a bind mount.
+ rel, err := filepath.Rel(root, path)
+ if err != nil {
+ return false
+ }
+ return rel != ".." && !strings.HasPrefix(rel, "../")
+}
+
// isPathOnVolume returns true if the specified containerPath is a subdir of any
// Volume's destination.
func isPathOnVolume(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
for _, vol := range c.config.NamedVolumes {
- if cleanedContainerPath == filepath.Clean(vol.Dest) {
+ cleanedDestination := filepath.Clean(vol.Dest)
+ if cleanedContainerPath == cleanedDestination {
return true
}
- for dest := vol.Dest; dest != "/" && dest != "."; dest = filepath.Dir(dest) {
+ if isSubDir(cleanedContainerPath, cleanedDestination) {
+ return true
+ }
+ for dest := cleanedDestination; dest != "/" && dest != "."; dest = filepath.Dir(dest) {
if cleanedContainerPath == dest {
return true
}
@@ -152,15 +166,19 @@ func findBindMount(c *Container, containerPath string) *specs.Mount {
return nil
}
-/// isPathOnBindMount returns true if the specified containerPath is a subdir of any
+/// isPathOnMount returns true if the specified containerPath is a subdir of any
// Mount's destination.
-func isPathOnBindMount(c *Container, containerPath string) bool {
+func isPathOnMount(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
for _, m := range c.config.Spec.Mounts {
- if cleanedContainerPath == filepath.Clean(m.Destination) {
+ cleanedDestination := filepath.Clean(m.Destination)
+ if cleanedContainerPath == cleanedDestination {
+ return true
+ }
+ if isSubDir(cleanedContainerPath, cleanedDestination) {
return true
}
- for dest := m.Destination; dest != "/" && dest != "."; dest = filepath.Dir(dest) {
+ for dest := cleanedDestination; dest != "/" && dest != "."; dest = filepath.Dir(dest) {
if cleanedContainerPath == dest {
return true
}
diff --git a/libpod/container_path_resolution_test.go b/libpod/container_path_resolution_test.go
new file mode 100644
index 000000000..f906c752d
--- /dev/null
+++ b/libpod/container_path_resolution_test.go
@@ -0,0 +1,28 @@
+package libpod
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestIsSubDir(t *testing.T) {
+ assert.True(t, isSubDir("/foo", "/foo"))
+ assert.True(t, isSubDir("/foo/bar", "/foo"))
+ assert.True(t, isSubDir("/foo/bar", "/foo/"))
+ assert.True(t, isSubDir("/foo/bar", "/foo//"))
+ assert.True(t, isSubDir("/foo/bar/", "/foo"))
+ assert.True(t, isSubDir("/foo/bar/baz/", "/foo"))
+ assert.True(t, isSubDir("/foo/bar/baz/", "/foo/bar"))
+ assert.True(t, isSubDir("/foo/bar/baz/", "/foo/bar/"))
+ assert.False(t, isSubDir("/foo/bar/baz/", "/foobar/"))
+ assert.False(t, isSubDir("/foo/bar/baz/../../", "/foobar/"))
+ assert.False(t, isSubDir("/foo/bar/baz/", "../foo/bar"))
+ assert.False(t, isSubDir("/foo/bar/baz/", "../foo/"))
+ assert.False(t, isSubDir("/foo/bar/baz/", "../foo"))
+ assert.False(t, isSubDir("/", ".."))
+ assert.False(t, isSubDir("//", ".."))
+ assert.False(t, isSubDir("//", "../"))
+ assert.False(t, isSubDir("//", "..//"))
+ assert.True(t, isSubDir("/foo/bar/baz/../../", "/foo/"))
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 324802a1f..572807ad6 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -517,7 +517,7 @@ func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIDs []string,
stdout := opts.StdoutWriter != nil
stderr := opts.StderrWriter != nil
options := new(containers.LogOptions).WithFollow(opts.Follow).WithSince(since).WithUntil(until).WithStderr(stderr)
- options.WithStdout(stdout).WithTail(tail)
+ options.WithStdout(stdout).WithTail(tail).WithTimestamps(opts.Timestamps)
var err error
stdoutCh := make(chan string)
diff --git a/test/e2e/run_working_dir_test.go b/test/e2e/run_working_dir_test.go
index ff91a420f..84792481f 100644
--- a/test/e2e/run_working_dir_test.go
+++ b/test/e2e/run_working_dir_test.go
@@ -46,6 +46,15 @@ var _ = Describe("Podman run", func() {
Expect(session).Should(Exit(126))
})
+ It("podman run a container using a --workdir under a bind mount", func() {
+ volume, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+
+ session := podmanTest.Podman([]string{"run", "--volume", fmt.Sprintf("%s:/var_ovl/:O", volume), "--workdir", "/var_ovl/log", ALPINE, "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
+
It("podman run a container on an image with a workdir", func() {
dockerfile := fmt.Sprintf(`FROM %s
RUN mkdir -p /home/foobar /etc/foobar; chown bin:bin /etc/foobar
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index 6b8d5fbc5..6e84e10fc 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -36,13 +36,28 @@ function _log_test_tail() {
run_podman run -d --log-driver=$driver $IMAGE sh -c "echo test1; echo test2"
cid="$output"
- run_podman logs --tail 1 $cid
- is "$output" "test2" "logs should only show last line"
+ run_podman wait $cid
+ run_podman logs --tail 1 --timestamps $cid
+ log1="$output"
+ assert "$log1" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \
+ "logs should only show last line"
+
+ # Sigh. I hate doing this, but podman-remote --timestamp only has 1-second
+ # resolution (regular podman has sub-second). For the timestamps-differ
+ # check below, we need to force a different second.
+ if is_remote; then
+ sleep 2
+ fi
run_podman restart $cid
+ run_podman wait $cid
+
+ run_podman logs -t --tail 1 $cid
+ log2="$output"
+ assert "$log2" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \
+ "logs, after restart, shows only last line"
- run_podman logs --tail 1 $cid
- is "$output" "test2" "logs should only show last line after restart"
+ assert "$log2" != "$log1" "log timestamps should differ"
run_podman rm $cid
}
diff --git a/test/system/045-start.bats b/test/system/045-start.bats
index d19171ec3..773a0acd2 100644
--- a/test/system/045-start.bats
+++ b/test/system/045-start.bats
@@ -40,6 +40,8 @@ load helpers
@test "podman start --filter - start only containers that match the filter" {
run_podman run -d $IMAGE /bin/true
cid="$output"
+ run_podman wait $cid
+
run_podman start --filter restart-policy=always $cid
is "$output" "" "CID of restart-policy=always container"
diff --git a/test/system/420-cgroups.bats b/test/system/420-cgroups.bats
index 025a20012..3269f666c 100644
--- a/test/system/420-cgroups.bats
+++ b/test/system/420-cgroups.bats
@@ -19,6 +19,8 @@ load helpers
esac
run_podman --cgroup-manager=$other run --name myc $IMAGE true
+ assert "$output" = "" "run true, with cgroup-manager=$other, is silent"
+
run_podman container inspect --format '{{.HostConfig.CgroupManager}}' myc
is "$output" "$other" "podman preserved .HostConfig.CgroupManager"
@@ -29,7 +31,8 @@ load helpers
# Restart the container, without --cgroup-manager option (ie use default)
# Prior to #7970, this would fail with an OCI runtime error
- run_podman start myc
+ run_podman start -a myc
+ assert "$output" = "" "restarted container emits no output"
run_podman rm myc
}