Note: This is a public test instance of Red Hat Bugzilla. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback at bugzilla.redhat.com.
Bug 1352066 - New use of capng_have_capability() exposes bug in cap-ng breaking libvirt when starting KVM guests
Summary: New use of capng_have_capability() exposes bug in cap-ng breaking libvirt whe...
Keywords:
Status: CLOSED DUPLICATE of bug 1351954
Alias: None
Product: Fedora
Classification: Fedora
Component: audit
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: ---
Assignee: Steve Grubb
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On: 1352064
Blocks: 1351995
TreeView+ depends on / blocked
 
Reported: 2016-07-01 14:24 UTC by Daniel Berrangé
Modified: 2016-07-01 14:47 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of: 1352064
Environment:
Last Closed: 2016-07-01 14:47:10 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Daniel Berrangé 2016-07-01 14:24:58 UTC
+++ This bug was initially created as a clone of Bug #1352064 +++

Description of problem:
The latest version of audit-libs has started using capng_have_capability() before sending audit messages.

This has in turn exposed a bug in libcap-ng's use of thread local state.

Specifically, if you call any capng_* function and then call fork(), the 

static __thread struct cap_ng m

will get initialized with the current PID.

If you then fork() and call another capng API, (for example, you're trying to drop caps for a child process you're spawning), this thread local doesn't get reset. 

As a result capng_apply() will try to set capabilities on the parent PID and gets an error

strace clearly shows the problem:

[pid 26690] capset({_LINUX_CAPABILITY_VERSION_3, 26689}, {0, 0, 0}) = -1 EPERM (Operation not permitted)


not it is runing pid 26690 but setting caps on 26689.

AFAICT, this bug has existed forever. The new audit-libs 2.6.1 has just started calling capng_have_capability() which has in turn broken libvirt which uses capng when spawning processes after fork.

The following demo shows the problem

#include <libaudit.h>
#include <cap-ng.h>

#include <stdio.h>
#include <sys/wait.h>


int main(int argc, char **argv)
{
  int fd = audit_open();

  if (fd < 0) {
    perror("audit_open");
    return 1;
  }

  audit_log_user_message(fd, AUDIT_VIRT_CONTROL, "test", NULL,
			 NULL, NULL, 1);

  close(fd);

  pid_t child = fork();

  if (child == 0) {
    capng_clear(CAPNG_SELECT_CAPS);
    if (capng_apply(CAPNG_SELECT_CAPS) < 0) {
      perror("capng_apply");
      _exit(1);
    }
    
    _exit(0);
  }

  int status = 0;
  waitpid(child, &status, 0);

  fprintf(stderr, "Child exited %d\n", status);
  return 0;
}


$ gcc -lcap-ng -laudit -o cap cap.c
[berrange@t530wlan ~]$ ./cap
capng_apply: Operation not permitted
Child exited 256


If you downgrade to audit-libs-2.6 the problem goes away, though clearly the bug in cap-ng still exists.


Version-Release number of selected component (if applicable):
audit-libs-2.6.1-1.fc24.x86_64
audit-libs-2.6.1-1.fc24.i686
libcap-ng-0.7.7-4.fc24.x86_64
libcap-ng-0.7.7-4.fc24.i686

Comment 1 Steve Grubb 2016-07-01 14:47:10 UTC

*** This bug has been marked as a duplicate of bug 1351954 ***


Note You need to log in before you can comment on or make changes to this bug.