mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
204c673cce
A regression reported for runc v1.1.3 says that "runc exec -t" fails after doing "systemctl daemon-reload": > exec failed: unable to start container process: open /dev/pts/0: operation not permitted: unknown Apparently, with commit7219387eb7we are no longer adding "DeviceAllow=char-pts rwm" rule (because os.Stat("char-pts") returns ENOENT). The bug can only be seen after "systemctl daemon-reload" because runc also applies the same rules manually (by writing to devices.allow for cgroup v1), and apparently reloading systemd leads to re-applying the rules that systemd has (thus removing the char-pts access). The fix is to do os.Stat only for "/dev" paths. Also, emit a warning that the path was skipped. Since the original idea was to emit less warnings, demote the level to debug. Note this also fixes the issue of not adding "m" permission for block-* and char-* devices. A test case is added, which reliably fails before the fix on both cgroup v1 and v2. This is a backport of commit58b1374f0ato release-1.1 branch. Fixes: https://github.com/opencontainers/runc/issues/3551 Fixes:7219387eb7Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
147 lines
4.5 KiB
Bash
147 lines
4.5 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
load helpers
|
|
|
|
function setup() {
|
|
setup_busybox
|
|
}
|
|
|
|
function teardown() {
|
|
teardown_bundle
|
|
}
|
|
|
|
@test "runc run [redundant default /dev/tty]" {
|
|
update_config ' .linux.devices += [{"path": "/dev/tty", "type": "c", "major": 5, "minor": 0}]
|
|
| .process.args |= ["ls", "-lLn", "/dev/tty"]'
|
|
|
|
runc run test_dev
|
|
[ "$status" -eq 0 ]
|
|
|
|
if [[ "$ROOTLESS" -ne 0 ]]; then
|
|
[[ "${lines[0]}" =~ "crw-rw-rw".+"1".+"65534".+"65534".+"5,".+"0".+"/dev/tty" ]]
|
|
else
|
|
[[ "${lines[0]}" =~ "crw-rw-rw".+"1".+"0".+"0".+"5,".+"0".+"/dev/tty" ]]
|
|
fi
|
|
}
|
|
|
|
@test "runc run [redundant default /dev/ptmx]" {
|
|
update_config ' .linux.devices += [{"path": "/dev/ptmx", "type": "c", "major": 5, "minor": 2}]
|
|
| .process.args |= ["ls", "-lLn", "/dev/ptmx"]'
|
|
|
|
runc run test_dev
|
|
[ "$status" -eq 0 ]
|
|
[[ "${lines[0]}" =~ "crw-rw-rw".+"1".+"0".+"0".+"5,".+"2".+"/dev/ptmx" ]]
|
|
}
|
|
|
|
@test "runc run/update [device cgroup deny]" {
|
|
requires root
|
|
|
|
update_config ' .linux.resources.devices = [{"allow": false, "access": "rwm"}]
|
|
| .linux.devices = [{"path": "/dev/kmsg", "type": "c", "major": 1, "minor": 11}]
|
|
| .process.capabilities.bounding += ["CAP_SYSLOG"]
|
|
| .process.capabilities.effective += ["CAP_SYSLOG"]
|
|
| .process.capabilities.inheritable += ["CAP_SYSLOG"]
|
|
| .process.capabilities.permitted += ["CAP_SYSLOG"]
|
|
| .process.args |= ["sh"]'
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_deny
|
|
[ "$status" -eq 0 ]
|
|
|
|
# test write
|
|
runc exec test_deny sh -c 'hostname | tee /dev/kmsg'
|
|
[ "$status" -eq 1 ]
|
|
[[ "${output}" == *'Operation not permitted'* ]]
|
|
|
|
# test read
|
|
runc exec test_deny sh -c 'head -n 1 /dev/kmsg'
|
|
[ "$status" -eq 1 ]
|
|
[[ "${output}" == *'Operation not permitted'* ]]
|
|
|
|
runc update test_deny --pids-limit 42
|
|
|
|
# test write
|
|
runc exec test_deny sh -c 'hostname | tee /dev/kmsg'
|
|
[ "$status" -eq 1 ]
|
|
[[ "${output}" == *'Operation not permitted'* ]]
|
|
|
|
# test read
|
|
runc exec test_deny sh -c 'head -n 1 /dev/kmsg'
|
|
[ "$status" -eq 1 ]
|
|
[[ "${output}" == *'Operation not permitted'* ]]
|
|
}
|
|
|
|
@test "runc run [device cgroup allow rw char device]" {
|
|
requires root
|
|
|
|
update_config ' .linux.resources.devices = [{"allow": false, "access": "rwm"},{"allow": true, "type": "c", "major": 1, "minor": 11, "access": "rw"}]
|
|
| .linux.devices = [{"path": "/dev/kmsg", "type": "c", "major": 1, "minor": 11}]
|
|
| .process.args |= ["sh"]
|
|
| .process.capabilities.bounding += ["CAP_SYSLOG"]
|
|
| .process.capabilities.effective += ["CAP_SYSLOG"]
|
|
| .process.capabilities.inheritable += ["CAP_SYSLOG"]
|
|
| .process.capabilities.permitted += ["CAP_SYSLOG"]
|
|
| .hostname = "myhostname"'
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_allow_char
|
|
[ "$status" -eq 0 ]
|
|
|
|
# test write
|
|
runc exec test_allow_char sh -c 'hostname | tee /dev/kmsg'
|
|
[ "$status" -eq 0 ]
|
|
[[ "${lines[0]}" == *'myhostname'* ]]
|
|
|
|
# test read
|
|
runc exec test_allow_char sh -c 'head -n 1 /dev/kmsg'
|
|
[ "$status" -eq 0 ]
|
|
|
|
# test access
|
|
TEST_NAME="dev_access_test"
|
|
gcc -static -o "rootfs/bin/${TEST_NAME}" "${TESTDATA}/${TEST_NAME}.c"
|
|
runc exec test_allow_char sh -c "${TEST_NAME} /dev/kmsg"
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "runc run [device cgroup allow rm block device]" {
|
|
requires root
|
|
|
|
# Get the first block device.
|
|
IFS=$' \t:' read -r device major minor <<<"$(lsblk -nd -o NAME,MAJ:MIN)"
|
|
# Could have used -o PATH but lsblk from CentOS 7 does not have it.
|
|
device="/dev/$device"
|
|
|
|
update_config ' .linux.resources.devices = [{"allow": false, "access": "rwm"},{"allow": true, "type": "b", "major": '"$major"', "minor": '"$minor"', "access": "rwm"}]
|
|
| .linux.devices = [{"path": "'"$device"'", "type": "b", "major": '"$major"', "minor": '"$minor"'}]
|
|
| .process.args |= ["sh"]
|
|
| .process.capabilities.bounding += ["CAP_MKNOD"]
|
|
| .process.capabilities.effective += ["CAP_MKNOD"]
|
|
| .process.capabilities.inheritable += ["CAP_MKNOD"]
|
|
| .process.capabilities.permitted += ["CAP_MKNOD"]'
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_allow_block
|
|
[ "$status" -eq 0 ]
|
|
|
|
# test mknod
|
|
runc exec test_allow_block sh -c 'mknod /dev/fooblock b '"$major"' '"$minor"''
|
|
[ "$status" -eq 0 ]
|
|
|
|
# test read
|
|
runc exec test_allow_block sh -c 'fdisk -l '"$device"''
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
# https://github.com/opencontainers/runc/issues/3551
|
|
@test "runc exec vs systemctl daemon-reload" {
|
|
requires systemd root
|
|
|
|
runc run -d --console-socket "$CONSOLE_SOCKET" test_exec
|
|
[ "$status" -eq 0 ]
|
|
|
|
runc exec -t test_exec sh -c "ls -l /proc/self/fd/0; echo 123"
|
|
[ "$status" -eq 0 ]
|
|
|
|
systemctl daemon-reload
|
|
|
|
runc exec -t test_exec sh -c "ls -l /proc/self/fd/0; echo 123"
|
|
[ "$status" -eq 0 ]
|
|
}
|