14
17

More than 5 years have passed since last update.

systemdはどうやってコンテナ・仮想化環境を判別しているのか

Last updated at Posted at 2014-09-28

systemdにはコンテナやハイパーバイザの検出用関数detect_virtualizationが存在する。v230現在では、まずコンテナを判別するdetect_containerを実行して、判別できなければ仮想化環境を判別するdetect_vmを実行する。

detect_container

OpenVZ, LXC, LXC (libvirt), Docker, RKT, systemd nspawnを判別できる。

  • OpenVZ
    • /proc/vzが存在して、/proc/bcが存在しない
      • ルートコンテキストには両方存在する
  • それ以外
    • 自分がPID=1であれば、containerという環境変数を調べる
    • PID!=1であれば、/run/systemd/containerの中を調べる
      • PID=1のsystemdプロセスが当該ファイルを生成する
    • それもなければ、PID=1のプロセスのcontainer環境変数を調べる

detect_vm

KVM, QEMU, Bochs, Xen, UML, VMware, VirtualBox, Microsoft Azure, IBM z/VM, Parallels Desktopを判別できる。

systemdは仮想化環境を判別する方法をいくつか持っており、それらを順次実行していく。

detect_vm_dmi

DMIはDesktop Management Interfaceのことで、シリアル番号やBIOSのリビジョンといったハードウェア情報を取得するためのインタフェースである。Linuxでは、sysfsで以下のような情報が手に入る。

$ ls /sys/class/dmi/id/
bios_date     board_asset_tag  board_vendor       chassis_serial  chassis_version  product_name    product_version  uevent
bios_vendor   board_name       board_version      chassis_type    modalias         product_serial  subsystem
bios_version  board_serial     chassis_asset_tag  chassis_vendor  power            product_uuid    sys_vendor

systemdは以下のDMIを順番に調べる。

  • /sys/class/dmi/id/product_name
  • /sys/class/dmi/id/sys_vendor
  • /sys/class/dmi/id/board_vendor
  • /sys/class/dmi/id/bios_vendor

最近のVMMだと、これらのファイルのいずれかに識別のための文字列が入っている。

  • KVM
  • QEMU
  • VMware, VMW
  • innotek GmbH (VirtualBox)
  • Xen
  • Bochs
  • Parallels

detect_vm_cpuid

CPUIDの調べ方は後述するが、これもDMIと同様に設定されている文字列を元に仮想化環境を判別する。

  • XenVMMXenVMM
  • KVMKVMKVM
  • VMwareVMware
  • Microsoft Hv

detect_vm_xen

/proc/xen/capabilitiesが存在しているかチェックする。とりあえず、ここでXenであると判別するが、後でDom0のチェックを行なう(後述)。

detect_vm_hypervisor

/sys/hypervisor/typeを調べてxenと書かれていればXenと判別する。

detect_vm_device_tree

ARM, AArch64, PPC, PPC64の場合はデバイスツリーを調べる。

  • /proc/device-tree/hypervisor/compatibleが存在する場合
    • linux,kvmと書かれていればKVMと判別する
    • xenと書かれていればXenと判別する
  • 存在しない場合
    • /proc/device-treeのディレクトリを調べて、fw-cfgというファイルが存在すればQEMUと判別する

detect_vm_uml

/proc/cpuinfo\nvendor_id\t: User Mode Linux\nという文字列が含まれていればUMLと判別する。

detect_vm_zvm

s390の場合、/proc/sysinfoVM00 Control Programというエントリを調べる。

  • z/VMと書かれていればz/VMと判別する
  • そうでなければKVMと判別する

detect_vm_xen_dom0

もしこの段階でXenと判別されていた場合Dom0か否かを調べる。

/proc/xen/capabilitiesの機能リストにcontrol_dが存在していれば、Dom0だと判断し、仮想化環境ではないと判別する。

CPUIDの調べ方

ハイパーバイザ用のCPUIDについては、CPUID usage for interaction between Hypervisors and Linux. [LWN.net]に詳しい説明が書かれている。CPUID命令は、EAXレジスタに欲しい情報のIDを入れてCPUID命令を呼び出すと、情報毎に決められた特定のレジスタに情報が設定される (CPUID - Wikipedia, the free encyclopedia)。EAX=1がプロセッサ情報に対応し、EAXにプロセッサモデルやファミリ、EDXとECXにプロセッサの個々の機能が設定される。ECXの31ビット目はハイパーバイザ向けに予約されており、ハイパーバイザは1にセットして返すことになっている。ハイパーバイザが存在することがわかると、今度はEAX=0x40000000を入れてCPUID命令を呼ぶことで、ハイパーバイザ用ベンダIDを取得することができる。

14
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17