NoCloud data source is mis-using the "system-serial-number" SMBIOS field, should use "OEM Strings" instead

Bug #1753558 reported by Daniel Berrange
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
cloud-init
Expired
Medium
Unassigned

Bug Description

As the name suggests, the "system-serial-number" field in SMBIOS is intended for exposing a serial number identifying the hardware, to the operating system.

The NoCloud data source is mis-using this field for receiving metadata for initializing cloud-init.

Admittedly there was not really a better alternative available from QEMU historically, if SMBIOS was the required comms channel. This is not true for the SMBIOS spec in general though. It has a specified a table called "OEM Strings" which has no semantics defined and thus intentionally available for passing arbitrary OEM defined data to the guest OS.

This is much better suited to usage by cloud-init, and with careful namespacing it is possible to use "OEM strings" for multiple purposes, not only cloud-init.

Thus I have implemented patches for QEMU to enable use of the "OEM strings" SMBIOS table

  commit 2d6dcbf93fb01b4a7f45a93d276d4d74b16392dd
  Author: Daniel P. Berrange <email address hidden>
  Date: Sat Oct 28 21:51:36 2017 +0100

    smbios: support setting OEM strings table

    The cloud-init program currently allows fetching of its data by repurposing of
    the 'system' type 'serial' field. This is a clear abuse of the serial field that
    would clash with other valid usage a virt management app might have for that
    field.

    Fortunately the SMBIOS defines an "OEM Strings" table whose puporse is to allow
    exposing of arbitrary vendor specific strings to the operating system. This is
    perfect for use with cloud-init, or as a way to pass arguments to OS installers
    such as anaconda.

    This patch makes it easier to support this with QEMU. e.g.

      $QEMU -smbios type=11,value=Hello,value=World,value=Tricky,,value=test

    Which results in the guest seeing dmidecode data

      Handle 0x0E00, DMI type 11, 5 bytes
      OEM Strings
              String 1: Hello
              String 2: World
              String 3: Tricky,value=test

    It is suggested that any app wanting to make use of this OEM strings capability
    for accepting data from the host mgmt layer should use its name as a string
    prefix. e.g. to expose OEM strings targetting both cloud init and anaconda in
    parallel the mgmt app could set

      $QEMU -smbios type=11,value=cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/,\
            value=anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os

    which would appear as

      Handle 0x0E00, DMI type 11, 5 bytes
      OEM Strings
              String 1: cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/
              String 2: anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os

    Use of such string prefixes means the app won't have to care which string slot
    its data appears in.

    Signed-off-by: Daniel P. Berrange <email address hidden>
    Reviewed-by: Michael S. Tsirkin <email address hidden>
    Signed-off-by: Michael S. Tsirkin <email address hidden>

This will be in the QEMU 2.12 release due out end of April

And and equivalent patch to libvirt (released yesterday in 4.1.0) to allow it to be configured there and passed into QEMU

  commit 68eed56b2d51e66bb540062fe09f5ffd44e99f6e
  Author: Daniel P. Berrange <email address hidden>
  Date: Sat Oct 28 14:56:51 2017 +0100

    conf: add support for setting OEM strings SMBIOS data fields

    The OEM strings table in SMBIOS allows the vendor to pass arbitrary
    strings into the guest OS. This can be used as a way to pass data to an
    application like cloud-init, or potentially as an alternative to the
    kernel command line for OS installers where you can't modify the install
    ISO image to change the kernel args.

    As an example, consider if cloud-init and anaconda supported OEM strings
    you could use something like

        <oemStrings>
          <entry>cloud-init:ds=nocloud-net;s=http://10.10.0.1:8000/</entry>
          <entry>anaconda:method=http://dl.fedoraproject.org/pub/fedora/linux/releases/25/x86_64/os</entry>
        </oemStrings>

    use of a application specific prefix as illustrated above is
    recommended, but not mandated, so that an app can reliably identify
    which of the many OEM strings are targetted at it.

    Reviewed-by: John Ferlan <email address hidden>
    Signed-off-by: Daniel P. Berrange <email address hidden>

All that's missing now is a patch for cloud-init's NoCloud data source to make it look for data via the OEM strings table, in preference to the system table serial field.

Note in the above commits to QEMU/libvirt I illustrated an example of how to use an application specific prefix in the OEM strings entry to get nice namespacing.

Related bugs:
 * bug 1879294: Support fw_cfg data source
 * bug 1753558: NoCloud should use "OEM Strings" instead of
   system-serial-number
 * bug 1691772: provide a way to seed NoCloud from network without image modification.

Revision history for this message
Daniel Berrange (berrange) wrote :

Note this patch is completely *untested* so don't commit it as is ! It just meant to illustrate the a general approach to solving the bug and needs someone to validate it & provide unit tests, etc.

Scott Moser (smoser)
Changed in cloud-init:
status: New → Confirmed
importance: Undecided → Medium
Revision history for this message
Soren Hansen (soren) wrote :

Daniel, do you have any thoughts on this approach vs using fw_cfg for it? That seems more purpose built for passing configuration into guests.

Revision history for this message
Daniel Berrange (berrange) wrote :

The QEMU maintainers consider the "fw_cfg" feature to be only intended for QEMU to communicate with the firmware. While some projects have indeed used fw_cfg for general purpose data passthrough, this is discouraged by QEMU maintainers. There are a fairly small, limited number of data slots in fw_cfg, and QEMU needs to be able to use these precious free slots for its own tasks in future.

I implemented support for the "OEM strings" feature in SMBIOS for QEMU so that applications would have a mechanism which is functionally on a par with fw_cfg, and thus enable apps to avoid the precious fw_cfg slots

SMBIOS is available for x86, x64 and aarch64 targets in QEMU, which is equivalent to fw_cfg coverage IIRC.

Revision history for this message
Soren Hansen (soren) wrote :

I was going to just straight up disagree, but then I noticed that this only changed in v5.0.0 (i.e. very recently): https://github.com/qemu/qemu/commit/63d3145aadbecaa7e8be1e74b5d6b5cbbeb4e153

I think fw_cfg offers easier namespacing (e.g. /opt/io.cloud-init/user-data) than SMBIOS does, a concern you mention yourself in the commit message.

I think the ability to pass in a file instad of a string and being able to simply read that file easily inside the guest (/sys/firmware/qemu_fw_cfg/by_name/opt/io.cloud-init/user-data/raw) makes it a lot easier to integrate.

Thougts? Particularly in light of the linked recent change in QEMU's documentation.

Revision history for this message
Daniel Berrange (berrange) wrote :

I'm not sure why github mentions v5.0.0 there, as that commit is from 2016. That commit is just documenting how to avoid clashing with QEMU's usage of fw_cfg, and shouldn't be considered a recommendation / encouragement to actually use fw_cfg for application data. The QEMU maintainers still actively discourage any application usage of fw_cfg.

Scott Moser (smoser)
description: updated
Scott Moser (smoser)
description: updated
Revision history for this message
James Falcon (falcojr) wrote :
Changed in cloud-init:
status: Confirmed → Expired
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.