runc: Cannot run apt-get update in rootless container with sufficient capabilities
Similar to https://github.com/opencontainers/runc/issues/1860. I can’t seem to get a rootless ubuntu:18.04 container to run apt-get update, even with CAP_SYS_ADMIN.
$ mkdir rootfs
$ docker export $(docker create ubuntu:18.04) | tar -C rootfs -xf -
$ runc --version
runc version 1.0.0-rc91
spec: 1.0.2-dev
$ cat config.json
{
"ociVersion": "1.0.2-dev",
"process": {
"terminal": false,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"apt-get",
"update"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"cwd": "/",
"capabilities": {
"bounding": [
"CAP_SYS_ADMIN"
],
"effective": [
"CAP_SYS_ADMIN"
],
"inheritable": [
"CAP_SYS_ADMIN"
],
"permitted": [
"CAP_SYS_ADMIN"
],
"ambient": [
"CAP_SYS_ADMIN"
]
},
"rlimits": [
{
"type": "RLIMIT_NOFILE",
"hard": 1024,
"soft": 1024
}
],
"noNewPrivileges": true
},
"root": {
"path": "rootfs",
"readonly": false
},
"hostname": "runc",
"mounts": [
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
{
"destination": "/dev",
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"strictatime",
"mode=755",
"size=65536k"
]
},
{
"destination": "/dev/pts",
"type": "devpts",
"source": "devpts",
"options": [
"nosuid",
"noexec",
"newinstance",
"ptmxmode=0666",
"mode=0620"
]
},
{
"destination": "/dev/shm",
"type": "tmpfs",
"source": "shm",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
{
"destination": "/dev/mqueue",
"type": "mqueue",
"source": "mqueue",
"options": [
"nosuid",
"noexec",
"nodev"
]
},
{
"destination": "/sys",
"type": "none",
"source": "/sys",
"options": [
"rbind",
"nosuid",
"noexec",
"nodev",
"ro"
]
}
],
"linux": {
"uidMappings": [
{
"containerID": 0,
"hostID": 1000,
"size": 1
}
],
"gidMappings": [
{
"containerID": 0,
"hostID": 1000,
"size": 1
}
],
"namespaces": [
{
"type": "pid"
},
{
"type": "ipc"
},
{
"type": "uts"
},
{
"type": "mount"
},
{
"type": "user"
}
],
"maskedPaths": [
"/proc/acpi",
"/proc/asound",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/sys/firmware",
"/proc/scsi"
],
"readonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
}
}
The error I’m getting is:
$ runc run example
E: setgroups 65534 failed - setgroups (1: Operation not permitted)
E: setegid 65534 failed - setegid (22: Invalid argument)
E: seteuid 100 failed - seteuid (22: Invalid argument)
E: setgroups 0 failed - setgroups (1: Operation not permitted)
Reading package lists...
W: chown to _apt:root of directory /var/lib/apt/lists/partial failed - SetupAPTPartialDirectory (22: Invalid argument)
W: chown to _apt:root of directory /var/lib/apt/lists/auxfiles failed - SetupAPTPartialDirectory (22: Invalid argument)
E: setgroups 65534 failed - setgroups (1: Operation not permitted)
E: setegid 65534 failed - setegid (22: Invalid argument)
E: seteuid 100 failed - seteuid (22: Invalid argument)
E: setgroups 0 failed - setgroups (1: Operation not permitted)
E: Method gave invalid 400 URI Failure message: Failed to setgroups - setgroups (1: Operation not permitted)
E: Method http has died unexpectedly!
E: Sub-process http returned an error code (112)
With rootless docker I am able to actually run apt-get update
. Any clue what’s going wrong here?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 21 (3 by maintainers)
This is how I got around it (thanks to @rofl0r commenting on apt internals above)
it seems the developers of apt went to great lengths to make it hard to use their software outside the context they envisioned. we can find this source code in apt-pkg/contrib/fileutl.cc (which i found after receiving those error messages after creating a ptrace hook to return fake success from SYS_chown):
i.e. the software refuses to work if you don’t use exactly the sandboxing mechanism they invented.
the good news is that we can get it to work by simply removing the line with the username
_apt
from /etc/passwd, and suddenly we can useapt update
even with the most simple unshare sandbox as regular user. there seems to be also a config option “APT::Sandbox::Verify” but i don’t know how/where one can set it.i’m commenting here in the hope other users getting those errors messages will find my solution, rather than having to mess around with capabilities to get it to work and generally wasting a lot of time.
I mean, I can do it – though there are far less combative ways to ask me to write and send patches to another project.
It’s not reluctance to co-operate with other projects (speaking for myself, I contribute to many other projects). There are a couple of reasons why having workaround solutions in place is a good thing:
None of this means “we shouldn’t fix upstream projects” (far from it), it’s just that having a workaround solution is clearly better than not having one and I don’t see why you feel so strongly that having a workaround solution is somehow negative. The alternative is that users have no way of working around a project that doesn’t work in rootless containers.
(Not to mention that for some more complicated cases – such as faking
mknod(2)
– tools likeSECCOMP_RET_USER_NOTIF
are the only way of getting programs to run in containers nicely. So these techniques are useful in general.)Same happens with the whole list: