• E
    util: make virSetUIDGID async-signal-safe · ee777e99
    Eric Blake 提交于
    https://bugzilla.redhat.com/show_bug.cgi?id=964358
    
    POSIX states that multi-threaded apps should not use functions
    that are not async-signal-safe between fork and exec, yet we
    were using getpwuid_r and initgroups.  Although rare, it is
    possible to hit deadlock in the child, when it tries to grab
    a mutex that was already held by another thread in the parent.
    I actually hit this deadlock when testing multiple domains
    being started in parallel with a command hook, with the following
    backtrace in the child:
    
     Thread 1 (Thread 0x7fd56bbf2700 (LWP 3212)):
     #0  __lll_lock_wait ()
         at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136
     #1  0x00007fd5761e7388 in _L_lock_854 () from /lib64/libpthread.so.0
     #2  0x00007fd5761e7257 in __pthread_mutex_lock (mutex=0x7fd56be00360)
         at pthread_mutex_lock.c:61
     #3  0x00007fd56bbf9fc5 in _nss_files_getpwuid_r (uid=0, result=0x7fd56bbf0c70,
         buffer=0x7fd55c2a65f0 "", buflen=1024, errnop=0x7fd56bbf25b8)
         at nss_files/files-pwd.c:40
     #4  0x00007fd575aeff1d in __getpwuid_r (uid=0, resbuf=0x7fd56bbf0c70,
         buffer=0x7fd55c2a65f0 "", buflen=1024, result=0x7fd56bbf0cb0)
         at ../nss/getXXbyYY_r.c:253
     #5  0x00007fd578aebafc in virSetUIDGID (uid=0, gid=0) at util/virutil.c:1031
     #6  0x00007fd578aebf43 in virSetUIDGIDWithCaps (uid=0, gid=0, capBits=0,
         clearExistingCaps=true) at util/virutil.c:1388
     #7  0x00007fd578a9a20b in virExec (cmd=0x7fd55c231f10) at util/vircommand.c:654
     #8  0x00007fd578a9dfa2 in virCommandRunAsync (cmd=0x7fd55c231f10, pid=0x0)
         at util/vircommand.c:2247
     #9  0x00007fd578a9d74e in virCommandRun (cmd=0x7fd55c231f10, exitstatus=0x0)
         at util/vircommand.c:2100
     #10 0x00007fd56326fde5 in qemuProcessStart (conn=0x7fd53c000df0,
         driver=0x7fd55c0dc4f0, vm=0x7fd54800b100, migrateFrom=0x0, stdin_fd=-1,
         stdin_path=0x0, snapshot=0x0, vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
         flags=1) at qemu/qemu_process.c:3694
     ...
    
    The solution is to split the work of getpwuid_r/initgroups into the
    unsafe portions (getgrouplist, called pre-fork) and safe portions
    (setgroups, called post-fork).
    
    * src/util/virutil.h (virSetUIDGID, virSetUIDGIDWithCaps): Adjust
    signature.
    * src/util/virutil.c (virSetUIDGID): Add parameters.
    (virSetUIDGIDWithCaps): Adjust clients.
    * src/util/vircommand.c (virExec): Likewise.
    * src/util/virfile.c (virFileAccessibleAs, virFileOpenForked)
    (virDirCreate): Likewise.
    * src/security/security_dac.c (virSecurityDACSetProcessLabel):
    Likewise.
    * src/lxc/lxc_container.c (lxcContainerSetID): Likewise.
    * configure.ac (AC_CHECK_FUNCS_ONCE): Check for setgroups, not
    initgroups.
    Signed-off-by: NEric Blake <eblake@redhat.com>
    ee777e99
configure.ac 85.8 KB