Package: xchpst
Version: 0.8.5-1
Severity: normal
Tags: security,patch
X-Debbugs-Cc: Debian Security Team <[email protected]>
Hi,
attempting to drop capabilities from the bounding set results in no error being
printed, but also has no effect:
# strace -f -s200 -yy -e
'trace=prctl,capget,capset,setuid,setgid,setgroups,setresuid,setresgid,execve'
xchpst -u nobody --cap-bs-drop CAP_CHOWN /usr/sbin/capsh --print
execve("/usr/bin/xchpst", ["xchpst", "-u", "nobody", "--cap-bs-drop",
"CAP_CHOWN", "/usr/sbin/capsh", "--print"], 0x7fff0ccad728 /* 22 vars */) = 0
prctl(PR_CAPBSET_READ, CAP_MAC_OVERRIDE) = 1
prctl(PR_CAPBSET_READ, 0x30 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, CAP_CHECKPOINT_RESTORE) = 1
prctl(PR_CAPBSET_READ, 0x2c /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x2a /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x29 /* CAP_??? */) = -1 EINVAL (Invalid argument)
setgroups(0, []) = 0
setresgid(65534, 65534, 65534) = 0
setresuid(65534, 65534, 65534) = 0
execve("/usr/sbin/capsh", ["/usr/sbin/capsh", "--print"], 0x7ffe3d657a18 /* 22
vars */) = 0
[...]
Current: =
Bounding set
=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys>
Ambient set =
Current IAB:
Securebits: 00/0x0/1'b0 (no-new-privs=0)
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
secure-no-ambient-raise: no (unlocked)
uid=65534(nobody) euid=65534(nobody)
gid=65534(nogroup)
groups=
Guessed mode: HYBRID (4)
I would have expected something like prctl(PR_CAPBSET_DROP, CAP_CHOWN), but
there is only PR_CAPBSET_READ.
Looking at the source, it seems to me that the problem is that the option
parser never sets opt.cap_bounds_op:
case OPT_CAPBS_KEEP:
case OPT_CAPBS_DROP:
if (!parse_caps(&opt.cap_bounds, optarg))
opt.error = true;
break;
case OPT_CAPS_KEEP:
case OPT_CAPS_DROP:
if (!parse_caps(&opt.caps, optarg))
opt.error = true;
opt.caps_op = optdef->option == OPT_CAPS_KEEP ? CAP_OP_KEEP : CAP_OP_DROP;
break;
An `opt.cap_bounds_op =` line is missing from the first two cases, and the fix
is probably to add this one line:
opt.cap_bounds_op = optdef->option == OPT_CAPBS_KEEP ? CAP_OP_KEEP :
CAP_OP_DROP;
Like this:
case OPT_CAPBS_KEEP:
case OPT_CAPBS_DROP:
if (!parse_caps(&opt.cap_bounds, optarg))
opt.error = true;
opt.cap_bounds_op = optdef->option == OPT_CAPBS_KEEP ? CAP_OP_KEEP :
CAP_OP_DROP;
break;
In my very limited testing, this fixed the problem.
AndrĂ¡s
Ps. justification for "security" tag: a documented and apparently working
security improving feature is in fact a no-op.
-- System Information:
Debian Release: forky/sid
APT prefers stable-security
APT policy: (500, 'stable-security'), (350, 'unstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Init: runit (via /run/runit.stopit)
-- no debconf information
--
If God had intended men to fly, he'd have made it easier to get to the airport.