入り口に戻る

原文はこちら。

原文の魚拓はこちら。

dbus-daemon(1) man ページ

名前

dbus-daemon - メッセージ・バス・デーモン

書式

dbus-daemon

dbus-daemon [--version ] [--session ] [--system ] [--config-file=FILE] [ --print-address [=DESCRIPTOR]] [ --print-pid [=DESCRIPTOR]] [--fork ] [--nosyslog ] [--syslog ] [--syslog-only ] [--ready-event-handle=value]

説明

dbus-daemon は D-Bus のメッセージ・バス・デーモンである。全体像について詳しく知りたければ https://www.freedesktop.org/wiki/Software/dbus/ を見よ。D-Bus は第一に、任意の2つのアプリケーションの間における一対一通信を可能にするライブラリである。そして dbus-daemon は、このライブラリを使ってメッセージ・バス・デーモンを実装したアプリケーションである。複数のプログラムがこのメッセージ・バス・デーモンに接続する。そして、そうしたプログラムは互いにメッセージを交換することができる。

標準のメッセージ・バス・インスタンスが2つある。システム単位のメッセージ・バス(「messagebus」init サービスとして多くのシステムにインストールされているもの)とユーザ・ログイン・セッション単位のメッセージ・バス(ユーザがログインする度に起動されるもの)である。dbus-daemon はこの両方のインスタンスとして使用されるが、この2つのインスタンスは使用する設定ファイル(configuration file)を異にする。

オプション「--session」は「--config-file=/usr/share/dbus-1/session.conf」と指定するのと同じであり、オプション「--system」は「--config-file=/usr/share/dbus-1/system.conf」と指定するのと同じである。別の新しい設定ファイルを作成してオプション「--config-file」を使用することで、特別な用途のための新しいメッセージ・バス・デーモンを作成することができる。

システム単位のデーモン(systemwide daemon:システムで共有されるデーモン)は、通常 init スクリプトによって起動され、普通は単に「messagebus」(メッセージ・バス)と呼ばれる。

システム単位のデーモンは、主にシステム・イベント(例えばプリンタ・キューの変更、デバイスの追加・削除など)を広報するのに使用される。

セッション単位のデーモンは、デスクトップ・アプリケーション間の様々なプロセス間通信に使用される。但し、このデーモンはいかなる形でも X や GUI に依存するものではない。

SIGHUP を受け取ると、D-Bus デーモンは自身の設定ファイル(configuration file)を「部分的に」再度読み込み、自身のユーザ/グループの情報のキャッシュをフラッシュ(flush)することになる。設定変更の中には、全てのアプリケーションをバスから追い出す必要があるものもある。そのため、そうした変更はデーモンを再起動して初めて反映されることになる。ポリシーの変更は SIGHUP によって反映される(ものとする)。

オプション

以下のオプションを使用できる。

--config-file=FILE

指定した設定ファイル(configuration file)を使用する。

--fork

設定ファイル(configuration file)で「メッセージ・バスをフォーク(fork)してデーモンにする」ように設定してない場合であっても、強制的にメッセージ・バスをフォークしてデーモンにする。但し、大抵はそうなるように設定ファイルですでに適切な設定が為されている。このオプションは Windows では利用できない。

--nofork

設定ファイル(configuration file)で「メッセージ・バスをフォーク(fork)してデーモンにする」ように設定してある場合であっても、メッセージ・バスをフォーク(fork)させずデーモンにならないようにする。Windows では dbus-daemon は決して fork しないので、このオプションは指定することはできるけれども、それによって何かが行われることはない。

--print-address[=DESCRIPTOR]

メッセージ・バスのアドレスを標準出力もしくは指定したファイル記述子に書き込む。このオプションは、メッセージ・バスを起動するプログラムが使用する。

--print-pid[=DESCRIPTOR]

メッセージ・バスのプロセス ID を標準出力もしくは指定したファイル記述子に書き込む。このオプションは、メッセージ・バスを起動するプログラムが使用する。

--session

「ログイン・セッション単位のメッセージ・バス」の標準設定ファイル(standard configuration file)を使用する。

--system

「システム単位のメッセージ・バス」の標準設定ファイル(standard configuration file)を使用する。

--version

このデーモンのバージョンを表示する。

--introspect

D-Bus 内部インターフェイス(D-Bus internal interface)全てに対する内部調査の結果(introspection information)を表示する。

--address[=ADDRESS]

接続を待ち受けるためのアドレスを指定する。このオプション(で指定したアドレス)は、設定ファイル(configuration file)内でディレクティブ <listen> を使って指定したアドレスに優先する。詳しくは同ディレクティブのドキュメントを見よ。

--systemd-activation

systemd 方式のサービス・アクティベーション機能を有効にする。このオプションは、Linux にて systemd システムとセッション・マネージャが存在して初めて機能する。

--nopidfile

PID ファイルが設定ファイル(configuration file)で指定されていたとしても、同 PID ファイルを書き出す。

--syslog

設定ファイル(configuration file)で「システム・ログを使用する」ように設定してない場合であっても、メッセージ・バスがメッセージを出力する際に、標準エラーへの書き込みに加えて、システム・ログをも使用するようにする。Unix ではこれに syslog を使用する。Windows ではこれに OutputDebugString() を使用する。

--syslog-only

メッセージ・バスがメッセージを出力する際に強制的にシステム・ログを使用するようにし、且つ同メッセージを標準エラーへ複製しないようにする。Unix ではこれに syslog を使用する。Windows ではこれに OutputDebugString() を使用する。

--nosyslog

設定ファイル(configuration file)で「システム・ログを使用する」ように設定してある場合であっても、メッセージ・バスがメッセージを出力する際に標準エラーしか使用しないようにする。

--ready-event-handle=value

このオプションを指定した場合、dbus デーモンは、接続を処理する用意ができた時にイベントを1つ生成するようになる。ハンドル(訳註:原文は「handle」:value のハンドル)は、イベント・オブジェクトへの Windows ハンドルでなければならず、printf の書式指定子「%p」で表示できる形式のものでなければならない。親プロセスは、このイベント・オブジェクトを(関数 CreateEvent などを使って)非シグナル状態で作成しなければならず、その上で同イベント・オブジェクトが dbus-daemon プロセスによって継承されるように設定しておかなければならない。dbus-daemon は、クライアントから接続を受け入れる用意ができたとき、SetEvent を使うのと同じような形でこのイベントをシグナル状態にする。親プロセスは、WaitForSingleObject といった関数を使用することで、イベントがシグナル状態になるのを待ち受けることができる。このオプションは Windows でしか利用できない。Unix 環境で同じことを実現するには、--print-address と --print-pid の両方もしくは片方で使用するファイル記述子(親から継承したもの)に対して、アドレスとプロセス ID の両方もしくは片方が書き込まれるのを待ち受ける。

設定ファイル(configuration file)

1つのメッセージ・バス・デーモンには1つの設定ファイル(configuration file)があり、この設定ファイルによってメッセージ・バス・デーモンは固有の機能を担うアプリケーションへと変化する(specialize)。例えば、メッセージ・バスは、ある設定ファイルによってシステムで共有されるメッセージ・バスになったり、別の設定ファイルによってユーザ・ログイン・セッション毎のバスになったりする。

また、設定ファイルによって資源の制限、セキュリティのパラメータなども定まる。

設定ファイルは、相互運用性に関するどんな仕様にも含まれておらず、その後方互換性は保証されない。この文書は説明書(documentation)であり、仕様書(specification)ではない。

標準の「システム単位」のメッセージ・バスと「セッション単位」のメッセージ・バスの設定は、2つのファイル「/usr/share/dbus-1/system.conf」と「/usr/share/dbus-1/session.conf」に書かれている。これらのファイルでは通常、「/etc/dbus-1」にある system-local.conf と session-local.conf を取り込む(<include>)。ローカルの上書き設定をこの2つのファイルに書き込むことで、本来の設定ファイルを修正せずに済ますことができる。

標準システム・バスは通常、追加の XML ファイルを /usr/share/dbus-1/system.d から読み込む。サード・パーティのパッケージは、狙い通りの動作を行わせるのに必要なデフォルト・ポリシーをこのディレクトリにインストールするものとする。このディレクトリは dbus 1.10 (2015年公開)から利用できるようになっている。

また、標準システム・バスは通常、/etc/dbus-1/system.d からも XML ファイルを読み込む。このディレクトリは、システム管理者がデフォルトのポリシーを上書きしたいと考えた場合に使用するものとする。

サード・パーティのパッケージは、歴史的には XML ファイルを /etc/dbus-1/system.d にインストールしたものであったが、この慣行は今では非推奨と見做されている。このディレクトリは、システム管理者のためのものとして扱うべきである。

設定ファイルは XML 文書である。設定ファイルは以下の DOCTYPE 宣言を含んでいなければならない。



   <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
    "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

設定ファイルには以下の要素を入れることができる。

  • <busconfig>

これが根(root)となる要素である。

  • <type>

メッセージ・バスの周知の型(well-known type)である。現在周知されている値は「system」と「session」である。他の値を指定する場合、その値は D-Bus 仕様に加えられたものであるか、さもなくば名前空間を使用して管理されたものであるべきである。最後に記述されている <type> 要素が勝つ(優先される)(その前に書かれていた値は無視される)。この要素は、アクティベートされるクライアントにおいて、どの環境変数値(各種のメッセージ・バス専用の環境変数の値)が設定されるのかを定めるだけである。セッション・バスとシステム・バスの違いを生み出すポリシーの大部分は、設定ファイル中の他の要素で定まる。

メッセージ・バスの周知の型が「session」である場合、環境変数 DBUS_STARTER_BUS_TYPE の値は「session」に設定され、環境変数 DBUS_SESSION_BUS_ADDRESS の値はセッション・バスのアドレスになる。同様に、メッセージ・バスの型が「system」である場合、環境変数 DBUS_STARTER_BUS_TYPE の値は「system」に設定され、環境変数 DBUS_SYSTEM_BUS_ADDRESS の値はシステム・バスのアドレスになる(但しこのアドレスは通常は周知のものである)。

例: <type>session</type>

  • <include>

<include>filename.conf</include> という書き方で、指定したファイルをこの位置に取り込む。ファイル名が相対経路である場合、取り込むべきファイルは、取り込みを行う設定ファイルから見て「相対経路」の位置にある。

<include> には指定してもしなくてもよい属性「ignore_missing=(yes|no)」があり、指定が無い場合のデフォルト値は「no」である。この属性は、取り込もうとしたファイルが存在しなかったときに致命的なエラーとするのか否かを定めるものである。

  • <includedir>

<includedir>foo.d</includedir> という書き方で、指定したディレクトリの中にある全てのファイルをこの位置に取り込む。このディレクトリの中のファイル群を取り込む順序は不定である。「.conf」で終わるファイルだけが取り込まれる。

これは、個別のパッケージがシステム・バスを拡張できるようにすることを狙ったものである。例えば、CUPS からプリンタ・キューの変更の通知を送れるようにしたい場合、CUPS パッケージは、全てのアプリケーションにこのメッセージの受信を許可し且つプリンタ・デーモン・ユーザにこのメッセージの送信を許可するファイルを1つ作り、同ファイルを /usr/share/dbus-1/system.d にインストールすればよい。

  • <user>

デーモンのユーザ・アカウントであり、ユーザ名もしくは UID で記述する。デーモンは、起動時にこの UID へと変更できなかった場合、終了する。この要素が存在しない場合、デーモンは自身の UID を変更したり気に掛けたりしない。

設定ファイルの中で最後に記載されている <user> エントリが勝ち(優先され)、他のものは無視される。

デーモンのユーザは、バスの初期化が完了した後に変更される。そのため、ソケット等はユーザが変更される前に作成されるが、クライアントからのデータの読み込みはユーザが変更される前には行われない。これは、書き込みにルート権限が必要な場所にソケットと PID ファイルを作成できることを意味する。

  • <fork>

この要素が存在する場合、バス・デーモンは本物のデーモンになる(フォークしてバックグラウンドで実行されるようになる、などなど)。一般にはコマンド・ライン・オプション「--fork」よりもこちらを使う。

  • <keep_umask>

この要素が存在する場合、バス・デーモンはフォークする際に自身の元の umask を保持する。これは、子プロセスの動作に影響を与えることを避けるのに役立つ。

  • <syslog>

この要素が存在する場合、バス・デーモンは syslog にログを取る。コマンド・ライン・オプション「--syslog」「--syslog-only」及び「--nosyslog」はこの設定に優先する。

  • <pidfile>

この要素が存在する場合、バス・デーモンは自身の PID を指定されたファイルに書き込む。コマンド・ライン・オプション「--nopidfile」はこの設定に優先する。

  • <allow_anonymous>

この要素が存在する場合、ANONYMOUS 方式を使用して認証された「接続」が接続することを許可する。このオプションは、<auth> 要素(後ほど説明)を使用して ANONYMOUS 方式を有効にしていない限り、実際に効果は無い。

周知のシステム・バスあるいは周知のセッション・バスの設定ファイルの中でこのディレクティブを使用すると、そのバスは安全ではなくなるので、それらの設定ファイルの中で使用すべきでない。同様に、バスが独自の型のものであっても、このディレクティブを使用すると、そのバスの設定ファイルが「匿名ユーザによる損傷発生や権限昇格を防ぐ」ように特別に設計されていない限り、通常その独自バスは安全ではなくなる。

  • <listen>

バスが接続を待ち受けるべきアドレスを追加する。このアドレスは標準 D-Bus 形式(standard D-Bus format)で記述する。この記述形式にはトランスポート名と、存在すればパラメータ/オプションとが含まれる。

Windows 以外の環境では、周知のシステム・バスと周知のセッション・バスの両方において unix ベースのトランスポート(unix、systemd、launchd)がデフォルトであり、これらのトランスポートの使用が強く推奨される。

Windows では、unix ベースのトランスポートは利用できないので、TCP ベースのトランスポートを使用しなければならない。リモート X11 と同様、tcp トランスポートと nonce-tcp トランスポートには完全性と機密性の保護する機能は無いので、これらのトランスポートは通常ローカル・ループバック・インターフェイス(local loopback interface)を経由してのみ使用するようにするべきである。例えば「tcp:host=127.0.0.1」や「nonce-tcp:host=localhost」のようなアドレスを使用する。特に、周知のシステム・バスや周知のセッション・バスに対して、ループバックでない TCP アドレスで接続を待ち受けるように設定を施すのは安全ではない。

開発者は時としてデバッグ・ツールとしてリモート TCP を使う誘惑にかられることがある。しかしながら、この機能が完成品の中で有効なままになっていると、あまりにも危険な結果が生じることになる。開発者は、リモート TCP を使う代わりにSecure Shell もしくはそれに似たプロトコルを通して接続を中継するべきである。

歴史的には、リモート TCP 接続は、信頼できるローカル・エリア・ネットワーク内にある異なるマシン上の同一ユーザのログイン・セッション群の間で、1つのセッション・バスを共有するために使われてきた。その際には、暗号化されていないリモート X11、NFS (訳註:Network File System) で共有されたホーム・ディレクトリ、及び NIS (YP) 認証(訳註:Network Information Service、Yellow Pages)と合わせて使用されていた。このようなリモート TCP 接続は、同じ LAN にいる攻撃者に対して安全ではなく、明確に非推奨のものであると考えるべきであり、より正確に言うと、暗号化されいないリモート X11 と NFSv2/NFSv3 が安全でないのと同じ仕組み・同じ理由で安全でない。D-Bus の保守者らは、「ユーザ」と「マシン」の番いの1つ1つに対して、そのマシンの内側からしかアクセスできない個別のセッション・バスを使用することを推奨している。

例: <listen>unix:path=/tmp/foo</listen>

例: <listen>tcp:host=localhost,port=1234</listen>

複数の <listen> が記述されている場合、バスは複数のアドレスで接続を待ち受ける。バスは、起動されたサービスや関連する他の者たちに対して自身のアドレスを渡すにあたって、<listen> で最後に指定されたアドレスを最初に使用する。つまり、アプリケーションは先ず最後の <listen> のアドレスに接続を試みるということである。

tcp ソケットは、IPv4 のアドレス、IPv6 のアドレスもしくはホスト名の接続を受け入れることができる。ホスト名を解決した結果が複数のアドレスになる場合、サーバはそれらのアドレス全てにバインドされる(bind to:結び付けられる)。オプション「family=ipv4」もしくは「family=ipv6」を使用することで、サーバがバインドするアドレスを一部のアドレスに制限することができる。

例: <listen>tcp:host=localhost,port=0,family=ipv4</listen>

特別な場合として、ポート番号 0 を使用する場合(あるいはポート番号を省略する場合)がある。これは、オペレーティング・システムが選ぶ「利用可能なポート」を選択することを意味する。選択されたポート番号は、コマンド・ライン引数の「--print-address」で取得することができ、サーバが自分自身のアドレスを公開している場合(例えば DBUS_SESSION_BUS_ADDRESS が設定されている場合)にも知ることができる。

例: <listen>tcp:host=localhost,port=0</listen>

TCP アドレス/ノンス-TCP アドレスではオプション「bind=hostname」も利用できる。このオプションは待ち受け可能なアドレス(listenable address)で使用され、サーバが接続の待ち受けを行うインターフェイスを指定する。「hostname」の部分には次のいづれかが入る。即ち、ローカル・マシンのインターフェイスのいづれかの IP アドレス(大抵は 127.0.0.1)、あるいはそのような IP アドレスへと解決される DNS 名、あるいは IPv4 のインターフェイス全てで同時に接続を待ち受ける「0.0.0.0」、あるいは IPv6 と IPv4 のインターフェイス全てで同時に接続を待ち受ける「::」である(最後のものは OS が対応している場合に限る)。このオプションを指定しなかった場合、「host」の値と同じものがデフォルト値として使用される。

例: <listen>tcp:host=localhost,bind=0.0.0.0,port=0</listen>

  • <auth>

利用が認められている認証方式を列挙する。この要素が存在しない場合、既知の方式全ての利用が認められる。複数の <auth> 要素が存在する場合、列挙した方式全ての利用が認められる。認証方式の列挙の順序は意味を持たない。

Windows 以外のオペレーティング・システムにおいては、EXTERNAL 認証方式しか許可しないようにすることを強く勧める。これは、周知のシステム・バスと周知のセッション・バスのデフォルト設定である。

例: <auth>EXTERNAL</auth>

例: <auth>DBUS_COOKIE_SHA1</auth>

  • <servicedir>

「.service」ファイルを検索するディレクトリを追加する。この「.service」ファイルは、周知のバス名(の中の1つ)を提供することになるプログラムの起動方法を dbus-daemon に対して知らせるものである。「.service」ファイルの中身について詳しく知りたければ D-Bus 仕様を参照。

あるサービスが <servicedir> の複数のディレクトリで見つかった場合、設定ファイルの中で最初に挙げられていたディレクトリが優先される。同じディレクトリの中の2つのサービス・ファイルが同じ「周知のバス名」について定めていた場合、どちらを選択するかは任意である。後者の状況が発生するのは、サービス・ファイルの中の少なくとも1つが「推奨される名前」を使用していない場合に限られる。「推奨される名前」とは、そのサービス・ファイルが規定している「周知のバス名」の後ろに「.service」を付けたものである。

  • <standard_session_servicedirs/>

<standard_session_servicedirs/> は、セッション・サービス・ディレクトリ群の標準の集合を定めるものである。この要素の効果は、この要素で指定したディレクトリ(data directories)のそれぞれに対して、その順序で一連の <servicedir/> 要素を指定するのによく似ている。けれども、<servicedir/> では今のところディレクトリの監視を禁止したりサービス・ファイルの名付けにあたって厳格な命名規則を強制したりする方法が無いため、全く等価なものではない。

<servicedir/> 要素の場合と同様に、あるサービスが複数のサービス・ディレクトリで見つかった場合、最初に挙げられていたディレクトリが優先される。同じディレクトリの中の2つのサービス・ファイルが同じ「周知のバス名」について定めていた場合、どちらを選択するかは任意である。後者の状況が発生するのは、サービス・ファイルの中の少なくとも1つが「推奨される名前」を使用していない場合に限られる。「推奨される名前」とは、そのサービス・ファイルが規定している「周知のバス名」の後ろに「.service」を付けたものである。

Unix では、以下のものが標準のセッション・サービス・ディレクトリである。

  • 「$XDG_RUNTIME_DIR/dbus-1/services」…環境変数 XDG_RUNTIME_DIR が設定されている場合に使用できる(XDG_RUNTIME_DIR については XDG Base Directory Specification を見よ)。この場所は、systemd のジェネレータ(systemd.generator(7) を参照)、セッション・マネージャ、あるいは他のセッション・インフラストラクチャによって実行時に作成される一時的なサービス(transient service)のための場所である。これは参考実装である dbus-daemon が提供する拡張であり、D-Bus 仕様で定められたものではない。

    他の標準セッション・サービス・ディレクトリと異なり、このディレクトリではサービス・ファイルに対して厳格な命名規則が課される。即ち、ファイル名は、サービスの周知のバス名の後ろに「.service」を付けたものと完全に一致するものでなければならない。

    また、他の標準セッション・サービス・ディレクトリと異なり、このディレクトリは inotify(7) やそれに類する API によっては監視されない。dbus-daemon の実行中にこのディレクトリにセービス・ファイルを作成するプログラムは、変更を行った後は dbus-daemon の ReloadConfig() メソッドを呼び出すべきである。

  • 「$XDG_DATA_HOME/dbus-1/services」…環境変数 XDG_DATA_HOME のデフォルト値は「~/.local/share」である(XDG Base Directory Specification を見よ)。この場所は、D-Bus 仕様で規定されている場所であり、ユーザ毎のソフトウェアであって且つローカルにインストールされたもののための場所である。

  • 「directory/dbus-1/services」…directory には環境変数 XDG_DATA_DIRS に入っているディレクトリの各々が入る。環境変数 XDG_DATA_DIRS のデフォルト値は「/usr/local/share:/usr/share」である(XDG Base Directory Specification を見よ)。これらの場所は D-Bus 仕様で規定されている場所である。デフォルトの場所は、システム管理者によってローカルにインストールされたソフトウェア、もしくはオペレーティング・システムのパッケージからインストールされたソフトウェアのための場所である(前者なら「/usr/local/share」、後者なら「/usr/share」)。ユーザ毎の設定(configuration)あるいはシステムで共有される設定(configuration)の中、環境変数 XDG_DATA_DIRS の設定を行うものにおいては、デフォルトのディレクトリ以外の場所へインストールされたものを見つけられるように、この検索経路を拡張することができる。例えば、flatpak(1) を使用している場合、「~/.local/share/flatpak/exports/share/」と「/var/lib/flatpak/exports/share/」を含めることができる。

  • 「${datadir}/dbus-1/services」… ${datadir} は dbus をコンパイルした時に指定したものであり、大抵は「/usr/share」である。この場所は、参考実装である dbus-daemon が提供する拡張であり、dbus-daemon に附随してインストールされるソフトウェア群のための場所である。

XDG Base Directory Specification は、ページが移動していなければ http://freedesktop.org/wiki/Standards/basedir-spec にある。ここに無い場合、適当な検索エンジンで探してほしい。

Windows では、以下のものが標準のセッション・サービス・ディレクトリである。

  • 「%CommonProgramFiles%/dbus-1/services」…これは %CommonProgramFiles% が設定されている場合に使用できる。この場所は、システムで共有されるインストール済みソフトウェア・パッケージのための場所である。

  • 「share/dbus-1/services」というディレクトリ(dbus-daemon と同じディレクトリ階層(prefix)にある)。この場所は、dbus-daemon に附随してインストールされるソフトウェア群のための場所である。

オプション <standard_session_servicedirs/> は、/etc/dbus-1/session.conf で定義される、ユーザ単位のセッション・バス・デーモンとしか関連を持たない。この要素を他の設定ファイルの中に入れてもおそらく無意味である。

  • <standard_system_servicedirs/>

<standard_system_servicedirs/> は、「システムで共有されるアクティベーション用ディレクトリ」の標準のものを定める。このディレクトリに対してサービス・ファイルの検索を行う。セッション・サービスの場合と同様に、最初に挙げられていたディレクトリが最も優先される。

Unix では、以下のものが標準のシステム・サービス・ディレクトリである。

  • 「/etc/dbus-1/system-services」…この場所は、D-Bus 仕様で規定されており、システム管理者がローカルにインストールしたソフトウェアや、OS の一部でないサービスを展開するアセット・マネージャ(asset manager)がローカルにインストールしたソフトウェアのための場所である。「/usr/」が読み込み専用であるときなどに使用する。

  • 「/run/dbus-1/system-services」…この場所は、D-Bus 仕様で規定されており、再起動後に消える短命なサービスのための場所である。

  • 「/usr/local/share/dbus-1/system-services」…この場所は、D-Bus 仕様で規定されており、システム管理者がローカルにインストールしたソフトウェアのための場所である。

  • 「/usr/share/dbus-1/system-services」…この場所は、D-Bus 仕様で規定されており、オペレーティング・システムのパッケージがインストールしたソフトウェアのための場所である。

  • 「${datadir}/dbus-1/system-services」…この ${datadir} は dbus をコンパイルした時に指定したものであり、大抵は「/usr/share」である。この場所は、参考実装である dbus-daemon が提供する拡張であり、dbus-daemon に附随してインストールされるソフトウェア群のための場所である。

  • 「/lib/dbus-1/system-services」…この場所は D-Bus 仕様で規定されている。もともとはオペレーティング・システムのパッケージがインストールした、起動の初期段階で使用されるソフトウェアのための場所であった。しかし、参考実装の dbus-daemon は起動の初期段階で利用できるようには設計されていないので、この場所を使うのは非推奨と考えるべきである。

Windows では、標準のシステム・バスが存在しないので、標準のシステム・バス・ディレクトリも存在しない。

オプション <standard_system_servicedirs/> は、/usr/share/dbus-1/system.conf で定義される、システム毎のバス・デーモンとしか関連を持たない。この要素を他の設定ファイルの中に入れてもおそらく無意味である。

  • <servicehelper/>

<servicehelper/> は、別のユーザでシステム・デーモンを起動するのに使用する setuid ヘルパー(setuid helper:setuid ビットが立てられた補助プログラム)を指定するものである。一般的には、これは「libexec」にある実行ファイル dbus-daemon-launch-helper である。(訳註:訳者の環境では「/usr/lib/dbus-1.0/dbus-daemon-launch-helper」であった。)

オプション <servicehelper/> は、/usr/share/dbus-1/system.conf で定義される、システム毎のバス・デーモンとしか関連を持たない。この要素を他の設定ファイルの中に入れてもおそらく無意味である。

  • <limit>

<limit> はリソース量の制限を設定するものである。例を挙げる:


  <limit name="max_message_size">64</limit>
  <limit name="max_completed_connections">512</limit>

name 属性は必須である。以下に挙げる「制限名」(limit names)を利用することができる。

"max_incoming_bytes" :
単一の接続から来るメッセージ群の合計サイズ(単位はバイト)
"max_incoming_unix_fds" :
単一の接続から来るメッセージ群の unix ファイル記述子の合計数
"max_outgoing_bytes" :
単一の接続の待ち行列に入るメッセージ群の合計サイズ(単位はバイト)
"max_outgoing_unix_fds" :
単一の接続の待ち行列に入るメッセージ群の unix ファイル記述子の合計数
"max_message_size" :
単一のメッセージの最大サイズ(単位はバイト)
"max_message_unix_fds" :
単一のメッセージに含まれる unix ファイル記述子の個数の最大値
"service_start_timeout" :
起動されたサービスが接続するまでの時間(単位はミリ秒)。この時間内に接続を終えなければならない。
"auth_timeout" :
認証のために「接続」に与えられた時間(単位はミリ秒)。
"pending_fd_timeout" :
dbus-daemon へ転送されるにあたって「ファイル記述子」(FD)に与えられた時間(単位はミリ秒)。この時間を超えると接続は切断される。
"max_completed_connections" :
認証済み接続の個数の最大値。
"max_incomplete_connections" :
未認証の接続の個数の最大値。
"max_connections_per_user" :
同一ユーザから来ている認証済み接続の個数の最大値。この属性は Unix OS においてのみ有効。
"max_pending_service_starts" :
同時に進行する「サービスの起動」の個数の最大値。
"max_names_per_connection" :
1つの接続が所有できる名前の個数の最大値。
"max_match_rules_per_connection" :
単一の接続に対するマッチ規則の個数の最大値。
"max_replies_per_connection" :
接続1つが持てる未処理のメソッド・リプライの個数(進行中の呼び出しの個数)の最大値。
"reply_timeout" :
メソッド・コールが時間切れになるまでの時間(単位はミリ秒)

送信/受信のキューのサイズの最大値とは、1バイトでもこの最大値を下回っていれば新しいメッセージをキューに追加することができる、という性質のものである。したがって、実際には「max_message_size」の分だけ最大値を超過することができる。

「max_completed_connections」を「max_connections_per_user」で割った値は、システム単位のバスの全接続を使い尽くして他のすべてのユーザにサービス拒否攻撃(denial-of-service)を仕掛けるために最低限必要なユーザの数である。

各制限は通常、システム単位のバスにおいてしか意味を持たず、ユーザ・セッション・バスでは意味を持たない。

  • <policy>

<policy> という要素によって、「バスに対する接続の集合」1つに適用されるセキュリティ・ポリシーを定義する。ポリシー1つは <allow> 要素と <deny> 要素(の群)から成る。ポリシーは通常、システム単位のバスで使用される(訳註:セッション・バスでも使用される)。ポリシーは、想定通りのトラフィック(traffic)を通しつつ想定外のトラフィックを阻むという点で、ファイアウォールによく似ている。

現在システム・バスでは、メソッド・コールの送信及びバス名の所有に対する「default-deny」ポリシー(defaultコンテクストの<deny>ポリシー)と、メッセージの受信及びシグナルの送信、及び NO_REPLY フラグを持たないメソッド・コール1つ1つに対しての成功リプライ1つもしくはエラー・リプライ1つの送信に対する「default-allow」ポリシー(defaultコンテクストの<allow>ポリシー)とが定められている。想定を超える数のリプライを送信することは認められていない。

一般には、システム・サービスは、小さくて用途が絞られていて独自のプロセスで実行され且つただ1つのバス名を提供するようなプログラムとして運用するのが最も望ましい。そうすれば、あとは次の2種類の <allow> 規則を加えるだけでよい。即ち、プロセスがバス名を要求するための「own」権限に対する <allow> 規則と、全てもしくは一部の UID から自身のサービスへとトラフィックを送信することを許可するための「send_destination」規則に対する <allow> 規則とを加えるだけでよい。

<policy> 要素は次の4つの中のいづれか1つを属性として持つ。


  context="(default|mandatory)"
  at_console="(true|false)"
  user="username or useridユーザ名もしくはユーザ ID"
  group="group name or gidグループ名もしくは GID"

ポリシーは、各接続に対して以下のように適用される。

- 「context="default"」であるポリシー全てを適用する。
- 「group="接続のユーザのグループ"」であるポリシー全てを適用する。(順序は不定。)
- 「user="接続の認証ユーザ"」であるポリシー全てを適用する。(順序は不定。)
- 「at_console="true"」であるポリシー全てを適用する。
- 「at_console="false"」であるポリシー全てを適用する。
- 「context="mandatory"」であるポリシー全てを適用する。

ポリシーが重なるときは、後から適用されるものが先に適用されたものに優先する。同一の user/group/context を持つポリシーが複数存在する場合、それらは設定ファイル(config file)の中に現れた順序で適用される。

  • <deny>

  • <allow>

<deny> 要素は、<policy> 要素の下(木構造において下)に現れる要素であり、特定の動作を禁止するものである。<allow> 要素は、先行する <deny> 文に対して例外を設定するものであり、意味が逆であることを除けば <deny> と同様に機能する。

この2つの要素には以下の属性を入れることができる。


   send_interface="インターフェイス名" | "*"
   send_member="メソッドかシグナルの名前" | "*"
   send_error="エラー名" | "*"
   send_broadcast="true" | "false"
   send_destination="バス名" | "*"
   send_destination_prefix="バス名"
   send_type="method_call" | "method_return" | "signal" | "error" | "*"
   send_path="/path/name経路名" | "*"

   receive_interface="インターフェイス名" | "*"
   receive_member="メソッドかシグナルの名前" | "*"
   receive_error="エラー名" | "*"
   receive_sender="バス名" | "*"
   receive_type="method_call" | "method_return" | "signal" | "error" | "*"
   receive_path="/path/name経路名" | "*"

   send_requested_reply="true" | "false"
   receive_requested_reply="true" | "false"

   eavesdrop="true" | "false"

   own="バス名" | "*"
   own_prefix="バス名"
   user="ユーザ名" | "*"
   group="グループ名" | "*"

例:


   <deny send_destination="org.freedesktop.Service" send_interface="org.freedesktop.System" send_member="Reboot"/>
   <deny send_destination="org.freedesktop.System"/>
   <deny receive_sender="org.freedesktop.System"/>
   <deny user="john"/>
   <deny group="enemies"/>

<deny> 要素の属性は、その deny 規則が特定の動作にマッチ(match)するか否かを決めるものである。deny 規則がマッチした場合、その動作は拒否される(設定ファイル中の後の規則で許可していない限り)。

send_* 系の属性を1つ以上含む規則は、接続がメッセージの送信を試みた時に順番に照合される。メッセージにマッチした規則のうちの最後のものが送信の可否を決定する。周知のセッション・バスは通常、あらゆるメッセージの送信を許可している。周知のシステム・バスは通常、あらゆるシグナル、dbus-daemon に対する「選ばれた」メソッド・コール、及び以前に送信された各メソッド・コール(成功・失敗を問わない)に対するきっかり1つのリプライ(返答)を許可している。この2つは、どちらも設定によって変更することができる。システム・バスにおいては、メソッド・コールを受信するサービスは、自分がそのように振る舞うことを許可する設定ファイルをインストールしておかなければならない。この許可は通常 <policy context="default"><allow send_destination="…"/><policy> といった形式の規則を用いて行う。

receive_* 系の属性を1つ以上含む規則、もしくは eavesdrop 属性を含み且つ他の属性を含まない規則は、メッセージの受信者のそれぞれに対して照合が行われる(メッセージがブロードキャストである場合や接続が盗み聞き(eavesdropping)である場合は複数の受信者が存在し得る)。メッセージにマッチした規則のうちの最後のものが受信の可否を決定する。周知のセッション・バスは通常、盗み聞きも含めて、あらゆるメッセージの受信を許可している。周知のシステム・バスは通常、盗み聞きされていないメッセージ(受信者宛てのユニキャスト・メッセージ、及びブロードキャスト・メッセージ)であれば、あらゆるものの受信を許可している。

属性「eavesdrop」「min_fds」及び「max_fds」は、規則「send_*」や「receive_*」に適用できる修飾子(modifier)である。これらの属性については後ほど説明する。

規則「send_destination」と「receive_sender」は、指定した名前の所有者へのメッセージの送信あるいは同者からのメッセージの受信を許可しないという意味であり、指定した名前へのメッセージの送信を許可しないという意味ではない。つまり、ある接続がサービス A、B、C を所有しており、A への送信が拒否される場合、B や C への送信もまた機能しない。特別な場合であるが、「send_destination="*"」はあらゆるメッセージにマッチし(同メッセージが宛先指定(destination)を含んでいるか否かを問わない)、「receive_sender="*"」も同じようにあらゆるメッセージにマッチする。

規則「send_destination_prefix」は、送信に使う名前空間(whole namespace)を開いたり(訳註:<allow>)閉じたり(訳註:<deny>)する。これは、この接頭辞にマッチするあらゆる名前の所有者(その名前の筆頭所有者であるか待ち行列中の所有者であるかは問わない)にメッセージを送信することを許可したり(訳註:<allow>)許可しなかったり(訳註:<deny>)する、という意味である。例えば、「<allow send_destination_prefix="a.b"/>」という規則と「a.b」「a.b.c」「a.b.c.d」という3つの名前がバス上に存在する場合、「<allow send_destination="a.b"/>」「<allow send_destination="a.b.c"/>」及び「<allow send_destination="a.b.c.d"/>」という別々の3つの規則が定義されているのと同様に機能する。名前のマッチを行う方法は「own_prefix」の場合(後述)と同じである。接頭辞「a.b」は、名前「a.b」「a.b.c」「a.b.c.d」などとマッチするが、名前「a.bc」や「a.c」とはマッチしない。属性 send_destination_prefix は、同一規則の中で属性 send_destination と併せて使用することはできない。

「send_broadcast="true"」の指定がある規則は、宛先(destination)の無い(ブロードキャストである)シグナル・メッセージとマッチする。「send_broadcast="false"」の指定がある規則はその逆であり、ユニキャスト(unicast destination)のメッセージ全て(ユニキャストのシグナル、全てのメソッド・コール、全てのリプライ、及び全てのエラー)とマッチし、宛先の無い(ブロードキャストの)メッセージとはマッチしない。これは「send_destination="*"」と同じではない。「send_destination="*"」は、送信されるメッセージが宛先(destination)を持っているか否かとは関係なく、それら全てとマッチする。

他の「send_*」系の属性と「receive_*」系の属性は、メッセージ・ヘッダの中の該当するフィールドに対して、純粋に文字列値としてマッチを行うものである。但し、「*」による全てのメッセージへのマッチが認められている属性の場合、例外的に「*」は全てのメッセージにマッチする(この場合、該当するヘッダ・フィールドが存在するか否かは問題にならない)。例えば、「send_interface="*"」は、送信されるメッセージがインターフェイスを表すヘッダ・フィールドを持っていなくても、送信されるメッセージ全てにマッチする。「foo.bar.*」のような、より複雑なグロブ・マッチング(「*」を使ったマッチング)は認められていない。

盗み聞き(Eavesdropping)とは、アプリケーションが、自分の所有していない名前に(明示的に)宛てられたメッセージや、そうしたメッセージに対するリプライを受信することである。したがって、盗み聞きは、サービスに宛てられたメッセージと、そのようなメッセージに対するリプライ(返答)にしか適用されない(すなわちシグナルには適用されない)。

<allow> における「eavesdrop="true"」は、盗み聞きが行われている場合でもその <allow> 規則がマッチすることを意味する。「eavesdrop="false"」がデフォルトであり、この値は、その <allow> 規則ではメッセージが同メッセージで指定された受信者に向かうことしか許可しないことを意味する。<deny> における「eavesdrop="true"」は、盗み聞きが行われている場合にしかその <deny> 規則がマッチしないことを意味する。<deny> の場合でも「eavesdrop="false"」がデフォルトであるが、この場合、盗み聞きが行われていないときでもその <deny> 規則が常に適用されることを意味する。属性 eavesdrop は、send 規則と receive 規則(「send_*」属性及び「receive_*」属性を持つ規則)としか組み合わせられない。

[send|receive]_requested_reply という属性は、eavesdrop 属性と同じような形で機能する。[send|receive]_requested_reply 属性は、<deny> や <allow> が「予期されているリプライ」(先行するメソッド・コール・メッセージに対応するリプライ)にマッチするか否かを決定する。この属性は、リプライ・メッセージ(エラーとメソッドの返答)に対してしか意味を持たず、他のメッセージ型(message type)の場合は無視される。

<allow> においては [send|receive]_requested_reply="true" がデフォルトであり、これはその <allow> 規則では「要求されているリプライ」しか許可されないことを意味する。<allow> における [send|receive]_requested_reply="false" は、同 <allow> 規則ではあらゆるリプライ(予期されていないものであってもよい)が許可されることを意味する。

<deny> においては [send|receive]_requested_reply="false" がデフォルトであるが、これはその <deny> 規則が「リプライが要求されていない場合」にしかマッチしないことを意味する。[send|receive]_requested_reply="true" は、処理を待っているリプライの状態に関係なくその <deny> 規則が常に適用されることを意味する。

属性「min_fds」及び「max_fds」は、「send_*」系規則あるいは「receive_*」系規則を修飾するものである。「min_fds」属性を含む規則がメッセージとマッチするのは、同メッセージにこの属性で指定した個数以上の Unix ファイル記述子が添付されている場合だけである。逆に、「max_fds」属性を含む規則がメッセージとマッチするのは、同メッセージにこの属性で指定した個数以下のファイル記述子が添付されている場合だけである。実際には、これらの属性を含む規則は次のような形をとるのが一般的である。「<allow send_destination="…" max_fds="0"/>」、「<deny send_destination="…" min_fds="1"/>」、あるいは「<deny receive_sender="*" min_fds="1"/>」。

属性「user」や「group」を持つ規則は、メッセージ・バスに対して新たな接続を確立する時に照合されるものであり、その接続を継続して良いのか否かを決定する。この2つの属性はどちらも他の属性と併せて使用することはできない。「user="*"」と「group="*"」は特別な場合であり、どちらもあらゆる接続とマッチする。この形の規則が存在しない場合、デフォルトでは dbus-daemon プロセスを所有しているユーザ ID と同じユーザ ID からの接続を許可する。周知のセッション・バスは通常このデフォルトの動作を行うが、周知のシステム・バスは通常あらゆる接続を許可する。

属性「own」や「own_prefix」を持つ規則は、接続が周知のバス名の所有を試みた時に照合されるものである。「own="*"」は特別な場合であり、あらゆる「周知のバス名」にマッチする。周知のセッション・バスは通常、あらゆる接続に対してあらゆる名前の所有を許可するが、周知のシステム・バスは通常、追加の設定(configuration)で許可してある場合を除き、如何なる接続に対しても如何なる名前の所有も許可しない。何らかの名前を所有するつもりのシステム・サービスは、通常は「<policy user="some-system-user"><allow own="…"/></policy>」という形の規則を用いて、名前の所有を可能にする設定をインストールしなければならない。

<allow own_prefix="a.b"/> は、「a.b」という名前、あるいはドットで区切られた最初の要素が「a.b」である名前の所有を許可するものである。具体的に言うと、「a.b.c」及び「a.b.c.d」を所有することができて、「a.bc」や「a.c」を所有することはできない。これは、Telepathy や ReserveDevice といったサービスが、「org.freedesktop.Telepathy.ConnectionManager.(anything)」や「org.freedesktop.ReserveDevice1.(anything)」のような形で、周知の名前のサブツリー群(subtrees)の意味を定義するときに役に立つ。

あるユーザやグループに関する <policy> の中で同ユーザや同グループを deny (拒否)しても意味が無い。ユーザやグループの拒否は、「context="default"」あるいは「context="mandatory"」であるポリシーの内部にしか記述できない。

1つの <deny> 規則には、「send_destination」「send_interface」「send_type」などの属性を複数組み合わせたものを指定することができる。その場合、拒否が行われるのは、拒否されようとしているメッセージに対して全ての属性がマッチする場合に限られる。例えば、<deny send_interface="foo.bar" send_destination="foo.blah"/> は、指定したインターフェイスと指定したバス名の両方を持つメッセージを拒否することになる。論理和(OR)を実現するには、複数の <deny> 規則を記述する。

「send_」系の属性と「receive_」系の属性の両方を同一の規則の中に入れることはできない。なぜかというと、「メッセージを送信できるか否か」と「メッセージを受信できるか否か」は別々に評価されるからである。

「send_interface」と「receive_interface」の取り扱いには注意しなければならない。なぜかというと、メッセージの中の INTERFACE フィールドは必須ではない(optional)からである。たとえば <deny send_interface="org.foo.Bar"/> と指定してはいけない。この規則は INTERFACE フィールドの無いメッセージを全てのサービスに対してブロックしてしまうものであるが、これは意図した動作ではないはずである。必ず <deny send_interface="org.foo.Bar" send_destination="org.foo.Service"/> という形の規則を使用しなければならない。

(訳註:D-Bus 仕様によると「INTERFACE フィールドが無い場合、同一オブジェクトにある2つ以上のインターフェイスが同じ名前のメソッドを持っていると、それらのメソッドのいづれが呼び出されるのかは未定義になる。実装においては、エラーを返しても構わないし、メッセージがそれらのインターフェイスの中の任意の1つを含んでいるかのように扱って同メッセージを配送しても構わない。」)

(訳註:D-Bus 仕様の考え方:「メッセージは、遠隔オブジェクトの実装の外部にあるアクセス制御リストを通して、濾過によって取り除かれることがある(例えば周知のシステム・バスにおいて)。そのようなフィルター(濾過器)が「メッセージ中のインターフェイスが(リストに載っているもの等と)一致すること」によってメッセージを拒否する場合、あるいは、同フィルターが特定のインターフェイスへのメッセージだけを受け入れる場合、同フィルターは INTERFACE を含んでいないメッセージも拒否しなければならない。さもなければ、悪意のあるアプリケーションがそれを利用してフィルターを迂回してしまうかもしれない。」)

  • <selinux>

<selinux> という要素には Security Enhanced Linux の設定が入る。後ほど詳述。

  • <associate>

<associate> 要素は、<selinux> の下(木構造において下)に現れる要素であり、1つの対応関係(mapping)を作成する。今のところは、次のような1種類の関係しか設定できない。


   <associate own="org.freedesktop.Foobar" context="foo_t"/>

これは、ある接続が「org.freedesktop.Foobar」という名前の所有を要求した場合に、ソース・コンテクスト(source context)としてその接続のコンテクストを使用し、ターゲット・コンテクストとして「foo_t」を使用することを意味する。後述の SELinux に関する短い考察を参照。

ここでのコンテクスト(the context:訳註:context 属性?)は、名前を要求する際のターゲット・コンテクストであり、名前を所有している接続のコンテクストではないことに注意。

今のところ、あらゆる名前の所有に適用される設定を記述する手段は存在しないが、もしそのような構文を追加するとすれば次のような形式になるであろう。


   <associate own="*" context="foo_t"/>

この構文が有用である理由を思いついた場合、開発者に知らせてほしい。今のところ、(訳註:この構文においては?)デフォルトで使用されるコンテクストはバス自身のセキュリティ・コンテクストである。

2つの <associate> 要素が同一の名前を指定している場合、設定ファイルの中で後に記述された <associate> 要素が使用される。

  • <apparmor>

<apparmor> という要素を使用して、バスにおける AppArmor の中継処理(AppArmor mediation)の設定を行うことができる。この要素には属性を1つ入れることができ、それによって中継処理のモードを指定する。


   <apparmor mode="(enabled|disabled|required)"/>

デフォルトのモードは「enabled」である。「enabled」モードにおいては、カーネルで AppArmor 機能が利用可能になっていれば、AppArmor の中継処理が行われる。AppArmor 機能が利用可能でない場合、dbus-daemon は起動するが、AppArmor の中継処理は発生しない。「disabled」モードにおいては、AppArmor の中継処理機能は無効である。「required」モードにおいては、AppArmor 機能が利用可能であれば AppArmor の中継処理機能が有効になり、そうでなければ dbus-daemon は起動を拒否する。

バスの AppArmor 中継処理モード(AppArmor mediation mode)は、バスの起動後は変更できない。設定ファイルの中のモードを書き換えてデーモンに SIGHUP シグナルを送っても、中継処理のモードには何の影響ももたらさない。

セッション・サービスを組み入れる(integrating)

セッション・サービスの場合、サービスを組み入れるためのファイル(integration file)は必須ではない。セッション・バスへアクセスできるプログラムはいづれも、周知の名前を要求し、D-Bus インターフェイスを提供することができる。

多くの D-Bus セッション・サービスはサービス・アクティベーション(service activation)に対応している。サービス・アクティベーションは、要求があった時に dbus-daemon がそのサービスを起動できる仕組みであり、要求があったセッション・サービスそのものを実行する方法か、もしくは systemd --user インスタンスと通信する方法で実施される。サービス・アクティベーションの設定は、サービス・ファイル(service file)をディレクトリ「${datadir}/dbus-1/services」の中に作成することで為される。サービス・ファイルの中身は次のようなものになる。

[D-BUS Service]
Name=com.example.SessionService1
Exec=/usr/bin/example-session-service
# Optional
SystemdService=example-session-service

サービス・ファイルの内容と解釈については D-Bus 仕様 を参照。

com.example.SessionService1 というサービスのためのサービス・ファイルが存在する場合、その名前は「com.example.SessionService1.service」であるべきであるが、古いサービス(legacy service)との互換性のため、そうするのは必須ではない。

オプションの「SystemdService」を宣言するセッション・サービスは、systemd ユーザ・サービス・ユニット・ファイル(ファイル名もしくは「Alias」の値が SystemdService の値と一致するもの)をも用意しなければならない。systemd サービス・ユニットについては systemd.unit(5)、 systemd.service(5) を見よ。この systemd ユーザ・サービス・ユニット・ファイルの中身の例を挙げる。

[Unit]
Description=Example session service

[Service]
Type=dbus
BusName=com.example.SessionService1
ExecStart=/usr/bin/example-session-service

システム・サービスを組み入れる(integrating)

標準のシステム・バスでは、デフォルトではメソッド呼び出しや周知のバス名の所有は許されていない。そのため、実用的な D-Bus システム・サービスは通常、自身が適切に動作できるようにするためのデフォルトのセキュリティ・ポリシーを設定しなければならない。D-Bus システム・サービスは、同システム・サービスを機能させるのに必要なポリシー規則が書かれたデフォルトのポリシー・ファイルを ${datadir}/dbus-1/service.d にインストールするべきである。最良とされる慣行に則った(best-practice)ポリシー・ファイルは、大抵次のような形になる。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy user="_example">
    <allow own="com.example.Example1"/>
  </policy>

  <policy context="default">
    <allow send_destination="com.example.Example1"/>
  </policy>
</busconfig>

この例の中の「_example」は、システム・サービスのデーモン・プロセスを実行することになるシステム UID のユーザ名である。「com.example.Example1」は同システム・サービスの周知のバス名(well-known bus name)である。

「com.example.Example1」のためのポリシー・ファイルの名前は、通常は「com.example.Example1.conf」とすべきである。

既存のシステム・サービスの中には、そのサービスが受信できるメッセージの種類を管理するために、もっと複雑な <policy> 規則を使用しているものもある。しかしながら、dbus-daemon のポリシー言語は、粒度の細かいポリシーを記述するのに適したものではない。例えば、どんなポリシーも D-Bus インターフェイスや D-Bus メソッド名を用いて記述する必要があり、もっと高水準なドメイン固有の概念(リムーバブル・デバイスや内蔵デバイスなど)に関連付けて記述することはできない。そのため、次のようにすることが推奨される。即ち、新たなサービスは、通常はメソッド呼び出しを行う者全てからのメソッド・コール・メッセージを受け入れ、それからシステム管理者が管理できる(sysadmin-controllable)ポリシーを適用してそれらのメソッド・コール・メッセージに入っているリクエストに従うか否かを判断するようにするべきである(例えば polkit に問い合わせることによって)。

セッション・サービスと同じく、多くの D-Bus システム・サービスはサービス・アクティベーションに対応している。サービス・アクティベーションは、要求があった時に dbus-daemon がそのサービスを起動できる仕組みであり、要求があったシステム・サービスそのものを実行する方法か、もしくは systemd と通信する方法で実施される。サービス・アクティベーションの設定は、サービス・ファイルをディレクトリ「${datadir}/dbus-1/system-services」の中に作成することで為される。サービス・ファイルの中身は次のようなものになる。

[D-BUS Service]
Name=com.example.Example1
Exec=/usr/sbin/example-service
User=_example
# Optional
SystemdService=dbus-com.example.Example1.service

サービス・ファイルの内容と解釈については D-Bus 仕様を参照。

com.example.Example1 というサービスのためのサービス・ファイルが存在する場合、その名前は「com.example.Example1.service」でなければならない。

オプションの「SystemdService」を宣言するシステム・サービスは、systemd サービス・ユニット・ファイル(ファイル名もしくは「Alias」の値が SystemdService の値と一致するもの)をも用意しなければならない。systemd サービス・ユニットについては systemd.unit(5)、systemd.service(5) を見よ。この systemd サービス・ユニット・ファイルの中身の例を挙げる。

[Unit]
Description=Example service

[Service]
Type=dbus
BusName=com.example.Example1
ExecStart=/usr/sbin/example-service

[Install]
WantedBy=multi-user.target
Alias=dbus-com.example.Example1.service

SELinux

SELinux の詳細情報は http://www.nsa.gov/selinux/ を参照。その中から役に立つ情報をいくつか抜粋する。

システムにある全てのサブジェクト(プロセス)とオブジェクト(ファイル、ソケット、IPC オブジェクトなど)にはそれぞれ、セキュリティ属性を組み合わせたもの1つ(a collection of security attributes)が割り当てられる。この「セキュリティ属性を組み合わせたもの」はセキュリティ・コンテクスト(security context)と呼ばれる。セキュリティ・コンテクスト1つには、セキュリティ・ポリシーに関連のあるサブジェクトやオブジェクトに結び付けられたセキュリティ属性全てが入る。

セキュリティ・コンテクストをより上手くカプセル化するため、また一層高い効率性を得るため、SELinux のポリシー適用を実現するコードでは大抵、セキュリティ・コンテクストそのものではなくセキュリティ識別子(SID)を使用する。SID は整数であり、セキュリティ・サーバによって実行時にセキュリティ・コンテクストへと対応付けられるものである(1つの SID が1つのセキュリティ・コンテクストに対応する)。

セキュリティに関する判断が必要になったとき、ポリシー適用を実現するコードは SID の対1つ(大抵はサブジェクトの SID とオブジェクトの SID から成るものであるが、時にはサブジェクト SID 同士の対であることやオブジェクト SID 同士の対であることもある)と、オブジェクト・セキュリティ・クラス1つとをセキュリティ・サーバへ渡す。オブジェクト・セキュリティ・クラスはオブジェクトの種類を表す(例えばプロセス、通常のファイル、ディレクトリ、TCP ソケットなど)。

アクセスの判断とは、指定された SID の対とクラスに対して、あるパーミッション(a permission:ある種類の操作の許可)を与えるのか否かを決定することである。1つ1つのオブジェクト・クラスには、そのオブジェクトと結びつくパーミッション(permission:許可される操作:そのクラスに属するオブジェクトに対して行われうる操作の種類を管理するために定義されたもの)の集合がある。

D-Bus は SELinux のセキュリティ・チェックを2つの場所で行う。

第1に、ある接続から別の接続へメッセージが配送される時は、バス・デーモンは毎回パーミッションの照合を行なう。その際には、送信元の接続のセキュリティ・コンテクストをソース(source)とし、送信先の接続のセキュリティ・コンテクストをターゲット(target)とし、オブジェクト・クラスを「dbus」とし、且つ要求するパーミッションを「send_msg」として照合を行なう。

ある接続に関して手に入らないセキュリティ・コンテクストがある場合(UNIX ドメイン・ソケットを使用している場合には起こり得ない)、ターゲット・コンテクストとして使用するのはバス・デーモン自身のコンテクストになる。今のところ、このデフォルト設定を変更する手段は存在しない。なぜかというと、システム単位のバスへの接続には UNIX ドメイン・ソケットしか使用されないと想定しているからである。この点が変わる場合、おそらくデフォルトの接続コンテクストを設定する方法を追加することになろう。

第2に、接続が名前の所有を要求する時も、バス・デーモンは毎回パーミッションの照合を行なう。その際には、その接続のセキュリティ・コンテクストをソース(source)とし、設定ファイル(config file)の中でその名前に対して指定されているセキュリティ・コンテクストをターゲット(target)とし、オブジェクト・クラスを「dbus」とし、且つ要求するパーミッションを「acquire_svc」として照合を行なう。

バス名のセキュリティ・コンテクストは、本文書にて先に説明した <associate> 要素で指定する。設定ファイル(configuration file)の中において、ある名前にセキュリティ・コンテクストが紐付けられていない場合、(その名前に関しては)バス・デーモン自身のセキュリティ・コンテクストを使用する。

AppArmor

AppArmor の制約コンテキスト(confinement context:訳註:SELinux のコンテキストとは関係ない)は、アプリケーションがバスへ接続したときに記憶される。制約コンテキストは、ラベル1つと制約モード1つから成る。セキュリティ上の判断が必要になった時、デーモンはこの制約コンテクストを使用して AppArmor ポリシーと照合を行い(query the AppArmor policy)、その動作を許可するのか拒否するのか、及びその動作の監査ログをとるのかどうかを決定する。

デーモンは、AppArmor のセキュリティ・チェックを3つの場所で行なう。

第1に、ある接続から別の接続へメッセージが配送される時は、バス・デーモンは毎回パーミッションの照合を行なう。その際には、送信元の接続のラベルをソース(source)とし、送信先の接続のラベルと接続名の両方もしくは片方をターゲット(target)とし、バス名、経路名(path name)、インターフェイス名及びメンバ名も添えて照合を行なう。リプライ・メッセージ(method_return やエラー・メッセージ)は、既に許可されたメッセージに対する返答である場合、暗黙のうちに許可される。

第2に、接続が名前の所有を要求する時も、バス・デーモンは毎回パーミッションの照合を行なう。その際には、その接続のラベルをソース(source)とし、要求する名前をターゲット(target)とし、バス名を添えて照合を行なう。

第3に、接続が盗み聞き(eavesdrop)を試みようとする時も、バス・デーモンは毎回パーミッションの照合を行なう。その際には、その接続のラベルをソースとし、バス名を添えて照合を行なう。

バスの中継処理のための AppArmor 規則は、バスの設定ファイル(configuration file)には記録されていない。この AppArmor 規則はアプリケーションの AppArmor プロファイルの中に書かれている。詳しくは apparmor.d(5) を参照。

DEBUGGING

自分のメッセージがどこへ行こうとしているのか、あるいは何故自分のところにメッセージが届かないのかを知りたい場合、いくつか試すべき手段がある。

システム・バスは厳重に封鎖されており、自分のメッセージを通過させるためのセキュリティ・ポリシー・ファイルをインストールしていない場合、うまく動作しないということを覚えておく必要がある。セッション・バスの場合、このような心配は不要である。

バス上で何が起きているのかを知るための最も単純な方法は、D-Bus パッケージに付属しているプログラム dbus-monitor を実行することである。また、dbus-send を使って試験的なメッセージを送信することもできる。この2つのプログラムは、それぞれ独立した man ページを持っている。

デーモンそのものが何をしているのか知りたい場合、デーモンの独立したコピー(別インスタンス)を起動して、それに対してテストを行なう方法がある。これによって、実際のセッション・デーモンとシステム・デーモンを駄目にすることなく、デーモンをデバッガの管理下で実行したり、デーモンに詳細な出力を行わせたりすることが可能になる。

デーモンの独立した試験用コピーを実行するには、例えば端末を開き次のように打ち込む。


  DBUS_VERBOSE=1 dbus-daemon --session --print-address

試験用デーモンのアドレスは、同デーモンが起動した時に出力される。試験対象のアプリケーションを起動する時は、このアドレスをコピー・アンド・ペーストして環境変数 DBUS_SESSION_BUS_ADDRESS の値として使用する必要がある。これによって、試験対象のアプリケーションが実際のセッション・バスの DBUS_SESSION_BUS_ADDRESS にではなく試験用バスに接続するようになる。

用意した D-Bus のコピーが詳細出力モード(verbose mode)を有効にしてコンパイルされたものでない限り、環境変数の設定「DBUS_VERBOSE=1」は何の効果ももたらさない。製品としてビルドするにあたっては、実行効率への影響ゆえに、このようにコンパイルすることは推奨されない。用意したコピーがデバッグ作業を念頭に置いてビルドされたものでない場合、D-Bus を再構築する必要があろう。環境変数 DBUS_VERBOSE は D-Bus ライブラリにも影響を与え、したがって D-Bus を利用するアプリケーションにも影響を与える。これは、クライアント側とデーモン側の両方の詳細出力を見るのに役に立つ。

高度なことをしたい場合、試験用のバスのために独自のバス設定ファイルを作成することもできる(2つのデフォルト設定を定めている session.conf と system.conf が例として参考になる)。これによって、「.service」ファイルを置く場所として別のディレクトリを指定するといったことができるようになる。

著者

https://dbus.freedesktop.org/doc/AUTHORS を参照。

バグ

バグの報告は D-Bus のメーリング・リストかバグ・トラッカーへ送ってほしい。https://www.freedesktop.org/wiki/Software/dbus/ を参照。

入り口に戻る