Bug 602186

Summary: When using 'change' command, QEMU always tries to open the media read-write
Product: Red Hat Enterprise Linux 6 Reporter: Daniel Berrangé <berrange>
Component: qemu-kvmAssignee: Markus Armbruster <armbru>
Status: CLOSED DUPLICATE QA Contact: Virtualization Bugs <virt-bugs>
Severity: medium Docs Contact:
Priority: low    
Version: 6.0CC: kwolf, lcapitulino, mkenneth, virt-maint
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-06-22 14:35:58 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 601135    

Description Daniel Berrangé 2010-06-09 10:39:34 UTC
Description of problem:
I have a libvirt guest with a CDROM device. All attempts to use the 'change' command to alter the CDROM media result in QEMU attempting to open the new media for read-write and failing as selinux blocks this illegal write access attempt.

Furthermore, QMP does not correctly report this EACCESS error instead returning an 'undefined error' message

This is my full guest XML. In particular notice a readonly CDROM and readonly Floppy device

# virsh dumpxml f12i686
<domain type='kvm' id='4'>
  <name>f12i686</name>
  <uuid>0301f2c1-05fc-dddf-089b-60e874f11e64</uuid>
  <memory>1048576</memory>
  <currentMemory>1048576</currentMemory>
  <vcpu cpuset='1'>4</vcpu>
  <os>
    <type arch='x86_64' machine='pc-0.12'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <cpu match='exact'>
    <model>core2duo</model>
    <topology sockets='1' cores='2' threads='1'/>
    <feature policy='require' name='lahf_lm'/>
    <feature policy='require' name='sse4.1'/>
    <feature policy='require' name='xtpr'/>
    <feature policy='require' name='cx16'/>
    <feature policy='require' name='tm2'/>
    <feature policy='require' name='est'/>
    <feature policy='require' name='vmx'/>
    <feature policy='require' name='ds_cpl'/>
    <feature policy='require' name='pbe'/>
    <feature policy='require' name='tm'/>
    <feature policy='require' name='ht'/>
    <feature policy='require' name='ss'/>
    <feature policy='require' name='acpi'/>
    <feature policy='require' name='ds'/>
  </cpu>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/f12i686.img'/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu'/>
      <source file='/var/lib/libvirt/images/boot.iso'/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' unit='0'/>
    </disk>
    <disk type='file' device='floppy'>
      <driver name='qemu'/>
      <target dev='fda' bus='fdc'/>
      <readonly/>
      <alias name='fdc0-0-0'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <controller type='ide' index='0'>
      <alias name='ide0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='fdc' index='0'>
      <alias name='fdc0'/>
    </controller>
    <interface type='network'>
      <mac address='52:54:00:4c:7e:aa'/>
      <source network='default'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/11'/>
      <target port='0'/>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/11'>
      <source path='/dev/pts/11'/>
      <target port='0'/>
      <alias name='serial0'/>
    </console>
    <input type='tablet' bus='usb'>
      <alias name='input0'/>
    </input>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='5900' autoport='yes' keymap='en-us'/>
    <sound model='es1370'>
      <alias name='sound0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </sound>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
  </devices>
  <seclabel type='dynamic' model='selinux'>
    <label>system_u:system_r:svirt_t:s0:c112,c115</label>
    <imagelabel>system_u:object_r:svirt_image_t:s0:c112,c115</imagelabel>
  </seclabel>
</domain>


The corresponding full QEMU command line run is:

/usr/libexec/qemu-kvm -S -M pc-0.12 -cpu core2duo,+lahf_lm,+sse4.1,+xtpr,+cx16,+tm2,+est,+vmx,+ds_cpl,+pbe,+tm,+ht,+ss,+acpi,+ds -enable-kvm -m 1024 -smp 4,sockets=1,cores=2,threads=1 -name f12i686 -uuid 0301f2c1-05fc-dddf-089b-60e874f11e64 -nodefaults -chardev socket,id=monitor,path=/var/lib/libvirt/qemu/f12i686.monitor,server,nowait -mon chardev=monitor,mode=control -rtc base=utc -boot c -drive file=/var/lib/libvirt/images/f12i686.img,if=none,id=drive-virtio-disk0,boot=on,format=raw -device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0 -drive file=/var/lib/libvirt/images/boot.iso,if=none,media=cdrom,id=drive-ide0-1-0,readonly=on -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -drive if=none,id=drive-fdc0-0-0,readonly=on -global isa-fdc.driveA=drive-fdc0-0-0 -netdev tap,fd=19,id=hostnet0 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:4c:7e:aa,bus=pci.0,addr=0x6 -chardev pty,id=serial0 -device isa-serial,chardev=serial0 -usb -device usb-tablet,id=input0 -vnc 127.0.0.1:0,password -k en-us -vga cirrus -device ES1370,id=sound0,bus=pci.0,addr=0x5 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3

Notice in particular the 'readonly=on' flag against the CDROM and floppy drives.

QEMU is running as 'qemu:qemu' user/group and SELinux is enforcing


Now attempting to change the CDROM media

  # virsh attach-disk f12i686 /var/lib/libvirt/images/boot.iso hdc --driver file --type cdrom --mode readonly

This results in the following QMP command:

  {"execute":"change","arguments":{"device":"drive-ide0-1-0","target":"/var/lib/libvirt/images/boot.iso"}}

Which returns

  {"error": {"class": "UndefinedError", "desc": "An undefined error has ocurred", "data": {}}}

The strace of the QEMU binary shows

19215 stat("/var/lib/libvirt/images/boot.iso", {st_mode=S_IFREG|0644,
st_size=203423744, ...}) = 0
19215 stat("/var/lib/libvirt/images/boot.iso", {st_mode=S_IFREG|0644,
st_size=203423744, ...}) = 0
19215 open("/var/lib/libvirt/images/boot.iso", O_RDONLY|O_SYNC|O_CLOEXEC) = 21
19215 close(21)                         = 0
19215 stat("/var/lib/libvirt/images/boot.iso", {st_mode=S_IFREG|0644,
st_size=203423744, ...}) = 0
19215 open("/var/lib/libvirt/images/boot.iso", O_RDWR|O_SYNC|O_CLOEXEC) = -1
EACCES (Permission denied)
19215 write(19, "{\"error\": {\"class\": \"UndefinedError\", \"desc\": \"An
undefined error has ocurred\", \"data\": {}}}\r\n", 94) = 94

So it initially opens it readonly, but then closes it and re-opens read-write and fails since SELinux blocks this illegal access attempt.

So there are two problems:

 - The EACCESS error condition is not being reported back via QMP properly

 - Either 
    * QEMU needs to honour the original 'readonly=on' flag for this device when changing media
   Or
    * The 'change' command needs to allow specification of the readonly flag for the new media

I imagine probably the latter is the one that needs fixing, since it also doesn't have any way to specify other things like file format (qcow2, raw, etc)


Version-Release number of selected component (if applicable):
qemu-kvm-0.12.1.2-2.69.el6.x86_64

How reproducible:
Always

Steps to Reproduce:
1. Define the guest XML above
2. Run virsh attach-disk f12i686 /var/lib/libvirt/images/boot.iso hdc --driver file --type cdrom --mode readonly
3. See the undefined error returned

NB, this test scenario relies on SELinux being Enforcing to prevent QEMU's attempt to open it read-write.

  
Actual results:
QEMU opens the boot.iso  readwrite and fails with poor error message

Expected results:
QEMU opens the boot.iso  readonly and suceeds


Additional info:

Comment 2 RHEL Program Management 2010-06-09 11:03:13 UTC
This request was evaluated by Red Hat Product Management for inclusion in a Red
Hat Enterprise Linux major release.  Product Management has requested further
review of this request by Red Hat Engineering, for potential inclusion in a Red
Hat Enterprise Linux Major release.  This request is not yet committed for
inclusion.

Comment 3 Kevin Wolf 2010-06-11 10:16:27 UTC
(In reply to comment #0)
> So there are two problems:
> 
>  - The EACCESS error condition is not being reported back via QMP properly
> 
>  - Either 
>     * QEMU needs to honour the original 'readonly=on' flag for this device when
> changing media

This is something for Luiz. Upstream commit 07a5d95a added a OpenFileFailed error response for this case, but it doesn't say anything about the reason why it failed.

>    Or
>     * The 'change' command needs to allow specification of the readonly flag
> for the new media
> 
> I imagine probably the latter is the one that needs fixing, since it also
> doesn't have any way to specify other things like file format (qcow2, raw, etc)

Upstream commit cb4e5f8e added a guess here so that it opens read-only for CD-ROMs and read-write otherwise. This is still wrong, of course. I think the real solution for this is the blockdev_* implementation.

Comment 4 Markus Armbruster 2010-06-11 11:27:11 UTC
Most drive parameters set set with -drive / drive_add silently revert to defaults on media change.  media doesn't revert.  readonly reverts to on for media=cdrom, off otherwise.  This is not necessarily the same as what you set on drive creation.

The blockdev series will provide a new monitor command to insert media that gives you full control over parameters.

Comment 5 Daniel Berrangé 2010-06-22 14:35:58 UTC
This bug appears to have been fixed as a result of bug 602026

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