• E
    command: avoid deadlock on EPIPE situation · 858c2476
    Eric Blake 提交于
    It is possible to deadlock libvirt by having a domain with XML
    longer than PIPE_BUF, and by writing a hook script that closes
    stdin early.  This is because libvirt was keeping a copy of the
    child's stdin read fd open, which means the write fd in the
    parent will never see EPIPE (remember, libvirt should always be
    run with SIGPIPE ignored, so we should never get a SIGPIPE signal).
    Since there is no error, libvirt blocks waiting for a write to
    complete, even though the only reader is also libvirt.  The
    solution is to ensure that only the child can act as a reader
    before the parent does any writes; and then dealing with the
    fallout of dealing with EPIPE.
    
    Thankfully, this is not a security hole - since the only way to
    trigger the deadlock is to install a custom hook script, anyone
    that already has privileges to install a hook script already has
    privileges to do any number of other equally disruptive things
    to libvirt; it would only be a security hole if an unprivileged
    user could install a hook script to DoS a privileged user.
    
    * src/util/command.c (virCommandRun): Close parent's copy of child
    read fd earlier.
    (virCommandProcessIO): Don't let EPIPE be fatal; the child may
    be done parsing input.
    * tests/commandhelper.c (main): Set up a SIGPIPE situation.
    * tests/commandtest.c (test20): Trigger it.
    * tests/commanddata/test20.log: New file.
    858c2476
command.c 69.7 KB