...

Text file src/github.com/opencontainers/runc/tests/integration/exec.bats

Documentation: github.com/opencontainers/runc/tests/integration

     1#!/usr/bin/env bats
     2
     3load helpers
     4
     5function setup() {
     6	setup_busybox
     7}
     8
     9function teardown() {
    10	teardown_bundle
    11}
    12
    13@test "runc exec" {
    14	# run busybox detached
    15	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
    16	[ "$status" -eq 0 ]
    17
    18	runc exec test_busybox echo Hello from exec
    19	[ "$status" -eq 0 ]
    20	echo text echoed = "'""${output}""'"
    21	[[ "${output}" == *"Hello from exec"* ]]
    22}
    23
    24@test "runc exec [exit codes]" {
    25	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
    26	[ "$status" -eq 0 ]
    27
    28	runc exec test_busybox false
    29	[ "$status" -eq 1 ]
    30
    31	runc exec test_busybox sh -c "exit 42"
    32	[ "$status" -eq 42 ]
    33
    34	runc exec --pid-file /non-existent/directory test_busybox true
    35	[ "$status" -eq 255 ]
    36
    37	runc exec test_busybox no-such-binary
    38	[ "$status" -eq 255 ]
    39
    40	runc exec no_such_container true
    41	[ "$status" -eq 255 ]
    42}
    43
    44@test "runc exec --pid-file" {
    45	# run busybox detached
    46	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
    47	[ "$status" -eq 0 ]
    48
    49	runc exec --pid-file pid.txt test_busybox echo Hello from exec
    50	[ "$status" -eq 0 ]
    51	echo text echoed = "'""${output}""'"
    52	[[ "${output}" == *"Hello from exec"* ]]
    53
    54	# check pid.txt was generated
    55	[ -e pid.txt ]
    56
    57	output=$(cat pid.txt)
    58	[[ "$output" =~ [0-9]+ ]]
    59	[[ "$output" != $(__runc state test_busybox | jq '.pid') ]]
    60}
    61
    62@test "runc exec --pid-file with new CWD" {
    63	bundle="$(pwd)"
    64	# create pid_file directory as the CWD
    65	mkdir pid_file
    66	cd pid_file
    67
    68	# run busybox detached
    69	runc run -d -b "$bundle" --console-socket "$CONSOLE_SOCKET" test_busybox
    70	[ "$status" -eq 0 ]
    71
    72	runc exec --pid-file pid.txt test_busybox echo Hello from exec
    73	[ "$status" -eq 0 ]
    74	echo text echoed = "'""${output}""'"
    75	[[ "${output}" == *"Hello from exec"* ]]
    76
    77	# check pid.txt was generated
    78	[ -e pid.txt ]
    79
    80	output=$(cat pid.txt)
    81	[[ "$output" =~ [0-9]+ ]]
    82	[[ "$output" != $(__runc state test_busybox | jq '.pid') ]]
    83}
    84
    85@test "runc exec ls -la" {
    86	# run busybox detached
    87	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
    88	[ "$status" -eq 0 ]
    89
    90	runc exec test_busybox ls -la
    91	[ "$status" -eq 0 ]
    92	[[ ${lines[0]} == *"total"* ]]
    93	[[ ${lines[1]} == *"."* ]]
    94	[[ ${lines[2]} == *".."* ]]
    95}
    96
    97@test "runc exec ls -la with --cwd" {
    98	# run busybox detached
    99	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   100	[ "$status" -eq 0 ]
   101
   102	runc exec --cwd /bin test_busybox pwd
   103	[ "$status" -eq 0 ]
   104	[[ ${output} == "/bin"* ]]
   105}
   106
   107@test "runc exec --env" {
   108	# run busybox detached
   109	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   110	[ "$status" -eq 0 ]
   111
   112	runc exec --env RUNC_EXEC_TEST=true test_busybox env
   113	[ "$status" -eq 0 ]
   114
   115	[[ ${output} == *"RUNC_EXEC_TEST=true"* ]]
   116}
   117
   118@test "runc exec --user" {
   119	# --user can't work in rootless containers that don't have idmap.
   120	[[ "$ROOTLESS" -ne 0 ]] && requires rootless_idmap
   121
   122	# run busybox detached
   123	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   124	[ "$status" -eq 0 ]
   125
   126	runc exec --user 1000:1000 test_busybox id
   127	[ "$status" -eq 0 ]
   128	[[ "${output}" == "uid=1000 gid=1000"* ]]
   129}
   130
   131# https://github.com/opencontainers/runc/issues/3674.
   132@test "runc exec --user vs /dev/null ownership" {
   133	requires root
   134
   135	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   136	[ "$status" -eq 0 ]
   137
   138	ls -l /dev/null
   139	__runc exec -d --user 1000:1000 test_busybox id </dev/null
   140	ls -l /dev/null
   141	UG=$(stat -c %u:%g /dev/null)
   142
   143	# Host's /dev/null must be owned by root.
   144	[ "$UG" = "0:0" ]
   145}
   146
   147@test "runc exec --additional-gids" {
   148	requires root
   149
   150	# run busybox detached
   151	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   152	[ "$status" -eq 0 ]
   153
   154	wait_for_container 15 1 test_busybox
   155
   156	runc exec --user 1000:1000 --additional-gids 100 --additional-gids 65534 test_busybox id -G
   157	[ "$status" -eq 0 ]
   158
   159	[[ ${output} == "1000 100 65534" ]]
   160}
   161
   162@test "runc exec --preserve-fds" {
   163	# run busybox detached
   164	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   165	[ "$status" -eq 0 ]
   166
   167	echo hello >preserve-fds.test
   168	# fd 3 is used by bats, so we use 4
   169	exec 4<preserve-fds.test
   170	runc exec --preserve-fds=2 test_busybox cat /proc/self/fd/4
   171	[ "$status" -eq 0 ]
   172	[[ "${output}" == "hello" ]]
   173}
   174
   175function check_exec_debug() {
   176	[[ "$*" == *"nsexec container setup"* ]]
   177	[[ "$*" == *"child process in init()"* ]]
   178	[[ "$*" == *"setns_init: about to exec"* ]]
   179}
   180
   181@test "runc --debug exec" {
   182	runc run -d --console-socket "$CONSOLE_SOCKET" test
   183	[ "$status" -eq 0 ]
   184
   185	runc --debug exec test true
   186	[ "$status" -eq 0 ]
   187	[[ "${output}" == *"level=debug"* ]]
   188	check_exec_debug "$output"
   189}
   190
   191@test "runc --debug --log exec" {
   192	runc run -d --console-socket "$CONSOLE_SOCKET" test
   193	[ "$status" -eq 0 ]
   194
   195	runc --debug --log log.out exec test true
   196	# check output does not include debug info
   197	[[ "${output}" != *"level=debug"* ]]
   198
   199	cat log.out >&2
   200	# check expected debug output was sent to log.out
   201	output=$(cat log.out)
   202	[[ "${output}" == *"level=debug"* ]]
   203	check_exec_debug "$output"
   204}
   205
   206@test "runc exec --cgroup sub-cgroups [v1]" {
   207	requires root cgroups_v1
   208
   209	set_cgroups_path
   210	set_cgroup_mount_writable
   211
   212	__runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   213	testcontainer test_busybox running
   214
   215	# Check we can't join parent cgroup.
   216	runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
   217	[ "$status" -ne 0 ]
   218	[[ "$output" == *" .. is not a sub cgroup path"* ]]
   219
   220	# Check we can't join non-existing subcgroup.
   221	runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
   222	[ "$status" -ne 0 ]
   223	[[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
   224
   225	# Check we can't join non-existing subcgroup (for a particular controller).
   226	runc exec --cgroup cpu:nonexistent test_busybox cat /proc/self/cgroup
   227	[ "$status" -ne 0 ]
   228	[[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
   229
   230	# Check we can't specify non-existent controller.
   231	runc exec --cgroup whaaat:/ test_busybox true
   232	[ "$status" -ne 0 ]
   233	[[ "$output" == *"unknown controller "* ]]
   234
   235	# Check we can join top-level cgroup (implicit).
   236	runc exec test_busybox cat /proc/self/cgroup
   237	[ "$status" -eq 0 ]
   238	run ! grep -v ":$REL_CGROUPS_PATH\$" <<<"$output"
   239
   240	# Check we can join top-level cgroup (explicit).
   241	runc exec --cgroup / test_busybox cat /proc/self/cgroup
   242	[ "$status" -eq 0 ]
   243	run ! grep -v ":$REL_CGROUPS_PATH\$" <<<"$output"
   244
   245	# Create a few subcgroups.
   246	# Note that cpu,cpuacct may be mounted together or separate.
   247	runc exec test_busybox sh -euc "mkdir -p /sys/fs/cgroup/memory/submem /sys/fs/cgroup/cpu/subcpu /sys/fs/cgroup/cpuacct/subcpu"
   248	[ "$status" -eq 0 ]
   249
   250	# Check that explicit --cgroup works.
   251	runc exec --cgroup memory:submem --cgroup cpu,cpuacct:subcpu test_busybox cat /proc/self/cgroup
   252	[ "$status" -eq 0 ]
   253	[[ "$output" == *":memory:$REL_CGROUPS_PATH/submem"* ]]
   254	[[ "$output" == *":cpu"*":$REL_CGROUPS_PATH/subcpu"* ]]
   255}
   256
   257@test "runc exec --cgroup subcgroup [v2]" {
   258	requires root cgroups_v2
   259
   260	set_cgroups_path
   261	set_cgroup_mount_writable
   262
   263	__runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   264	testcontainer test_busybox running
   265
   266	# Check we can't join parent cgroup.
   267	runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
   268	[ "$status" -ne 0 ]
   269	[[ "$output" == *" .. is not a sub cgroup path"* ]]
   270
   271	# Check we can't join non-existing subcgroup.
   272	runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
   273	[ "$status" -ne 0 ]
   274	[[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
   275
   276	# Check we can join top-level cgroup (implicit).
   277	runc exec test_busybox grep '^0::/$' /proc/self/cgroup
   278	[ "$status" -eq 0 ]
   279
   280	# Check we can join top-level cgroup (explicit).
   281	runc exec --cgroup / test_busybox grep '^0::/$' /proc/self/cgroup
   282	[ "$status" -eq 0 ]
   283
   284	# Now move "init" to a subcgroup, and check it was moved.
   285	runc exec test_busybox sh -euc "mkdir /sys/fs/cgroup/foobar \
   286		&& echo 1 > /sys/fs/cgroup/foobar/cgroup.procs \
   287		&& grep -w foobar /proc/1/cgroup"
   288	[ "$status" -eq 0 ]
   289
   290	# The following part is taken from
   291	# @test "runc exec (cgroup v2 + init process in non-root cgroup) succeeds"
   292
   293	# The init process is now in "/foo", but an exec process can still
   294	# join "/" because we haven't enabled any domain controller yet.
   295	runc exec test_busybox grep '^0::/$' /proc/self/cgroup
   296	[ "$status" -eq 0 ]
   297
   298	# Turn on a domain controller (memory).
   299	runc exec test_busybox sh -euc 'echo $$ > /sys/fs/cgroup/foobar/cgroup.procs; echo +memory > /sys/fs/cgroup/cgroup.subtree_control'
   300	[ "$status" -eq 0 ]
   301
   302	# An exec process can no longer join "/" after turning on a domain
   303	# controller.  Check that cgroup v2 fallback to init cgroup works.
   304	runc exec test_busybox sh -euc "cat /proc/self/cgroup && grep '^0::/foobar$' /proc/self/cgroup"
   305	[ "$status" -eq 0 ]
   306
   307	# Check that --cgroup / disables the init cgroup fallback.
   308	runc exec --cgroup / test_busybox true
   309	[ "$status" -ne 0 ]
   310	[[ "$output" == *" adding pid "*" to cgroups"*"/cgroup.procs: device or resource busy"* ]]
   311
   312	# Check that explicit --cgroup foobar works.
   313	runc exec --cgroup foobar test_busybox grep '^0::/foobar$' /proc/self/cgroup
   314	[ "$status" -eq 0 ]
   315
   316	# Check all processes is in foobar (this check is redundant).
   317	runc exec --cgroup foobar test_busybox sh -euc '! grep -vwH foobar /proc/*/cgroup'
   318	[ "$status" -eq 0 ]
   319
   320	# Add a second subcgroup, check we're in it.
   321	runc exec --cgroup foobar test_busybox mkdir /sys/fs/cgroup/second
   322	[ "$status" -eq 0 ]
   323	runc exec --cgroup second test_busybox grep -w second /proc/self/cgroup
   324	[ "$status" -eq 0 ]
   325}

View as plain text