• E
    selinux: distinguish failure to label from request to avoid label · 0f082e69
    Eric Blake 提交于
    https://bugzilla.redhat.com/show_bug.cgi?id=924153
    
    Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
    an attribute relabel='no' in order to try and minimize the
    impact of shutdown delays when an NFS server disappears.  The idea
    was that if a disk is on NFS and can't be labeled in the first
    place, there is no need to attempt the (no-op) relabel on domain
    shutdown.  Unfortunately, the way this was implemented was by
    modifying the domain XML so that the optimization would survive
    libvirtd restart, but in a way that is indistinguishable from an
    explicit user setting.  Furthermore, once the setting is turned
    on, libvirt avoids attempts at labeling, even for operations like
    snapshot or blockcopy where the chain is being extended or pivoted
    onto non-NFS, where SELinux labeling is once again possible.  As
    a result, it was impossible to do a blockcopy to pivot from an
    NFS image file onto a local file.
    
    The solution is to separate the semantics of a chain that must
    not be labeled (which the user can set even on persistent domains)
    vs. the optimization of not attempting a relabel on cleanup (a
    live-only annotation), and using only the user's explicit notation
    rather than the optimization as the decision on whether to skip
    a label attempt in the first place.  When upgrading an older
    libvirtd to a newer, an NFS volume will still attempt the relabel;
    but as the avoidance of a relabel was only an optimization, this
    shouldn't cause any problems.
    
    In the ideal future, libvirt will eventually have XML describing
    EVERY file in the backing chain, with each file having a separate
    <seclabel> element.  At that point, libvirt will be able to track
    more closely which files need a relabel attempt at shutdown.  But
    until we reach that point, the single <seclabel> for the entire
    <disk> chain is treated as a hint - when a chain has only one
    file, then we know it is accurate; but if the chain has more than
    one file, we have to attempt relabel in spite of the attribute,
    in case part of the chain is local and SELinux mattered for that
    portion of the chain.
    
    * src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
    member.
    * src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
    Parse it, for live images only.
    (virSecurityDeviceLabelDefFormat): Output it.
    (virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
    (virDomainDiskSourceDefFormat, virDomainChrDefFormat)
    (virDomainDiskDefFormat): Pass flags on through.
    * src/security/security_selinux.c
    (virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
    when possible.
    (virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
    norelabel, if labeling fails.
    (virSecuritySELinuxSetFileconHelper): Fix indentation.
    * docs/formatdomain.html.in (seclabel): Document new xml.
    * docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
    * tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
    * tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
    * tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
    New test files.
    * tests/qemuxml2argvtest.c (mymain): Run the new tests.
    * tests/qemuxml2xmltest.c (mymain): Likewise.
    Signed-off-by: NEric Blake <eblake@redhat.com>
    0f082e69
domain_conf.c 584.8 KB