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.

Reply via email to