この文書では、リムーバブルストレージ、ケーパビリティ、ファイルシステムの場所、画像の合成、ELF シンボルバージョンという、いくつかの独立した管理作業を扱います。各セクションでは、自動化で重要となる運用上の境界を示します。
リムーバブルデバイスを安全に操作する #
リムーバブルメディアの電源を切る前に、マウントされているすべてのファイルシステムをアンマウントしてください。udisksctl は UDisks サービスを使用するため、デスクトップセッションの認可を適用し、デバイスに対する未仲介のコマンドを発行するのではなく、操作を調整します。
lsblk -o NAME,PATH,TYPE,FSTYPE,MOUNTPOINTS
udisksctl unmount -b /dev/sdb1
udisksctl power-off -b /dev/sdbunmount には /dev/sdb1 のようなパーティションを渡しますが、power-off には /dev/sdb のようなドライブ全体を渡します。後者はバッファをフラッシュし、カーネルによるデバイスの使用を解除し、ハードウェアが対応している場合はドライブの電源を切ります。デバイス名は接続イベントのたびに変わる可能性があるため、コマンドを実行する直前に確認してください。アンマウントが成功しただけでは、USB エンクロージャの電源が切れたことは保証されません。
ケーパビリティによる権限委譲 #
Linux のケーパビリティは、従来の、すべての権限を持つ root 権限を、個別に検査される単位へ分割します。プロセスには permitted、effective、inheritable、bounding、ambient のケーパビリティセットがあり、ファイルには permitted および inheritable のケーパビリティマスクと effective ビットを持たせることもできます。各ケーパビリティが対象とするカーネルチェックは異なるため、capabilities(7) を参照してください。
たとえば、システムクロックを設定する必要がある専用バイナリには CAP_SYS_TIME を付与できます。
sudo setcap cap_sys_time=ep /opt/example/bin/clock-setter
getcap /opt/example/bin/clock-setter=ep はケーパビリティをファイルの permitted セットに追加し、実行されたプロセスの effective セットに入るよう要求します。ケーパビリティは、対象を限定した、書き込み不可の実行ファイルに対して最小限のセットだけを付与してください。コピー、パッケージング、または必要な拡張属性をサポートしないファイルシステムによって、ファイルケーパビリティが除去されることがあります。そのため、デプロイ時のチェックでは getcap を実行してください。
ケーパビリティだけでは完全なサンドボックスにはなりません。特に CAP_SYS_ADMIN は互いに無関係な多数の操作を許可し、特権バイナリにメモリ安全性の問題やコマンドインジェクションのバグがあると、システム侵害につながる可能性があります。委譲内容を監査済みの単一コマンドとして表現できる場合は、制約した sudoers ルールのほうが検査しやすいことがあります。
ファイルシステムの場所を選ぶ #
Filesystem Hierarchy Standard と hier(7) は、永続性と目的に応じてデータを分離します。
/runには、起動以降の揮発性ランタイム状態が格納されます。この階層は起動時に消去されます。サービスは、PID ファイル、UNIX ドメインソケット、ロック、その他のランタイムメタデータ用に、/run/example/のような専用サブディレクトリを作成してください。サービスマネージャーは、systemd のRuntimeDirectory=などの機能を使ってこれを作成できます。/varには、ログ、キュー、キャッシュ、データベース、アプリケーション状態など、再起動後も保持される可変データが格納されます。永続状態には/var/lib/example、再生成可能なデータには/var/cache/exampleのような定義済みのサブツリーを選択してください。/tmpには一時ファイルが格納され、ポリシーまたは起動時に消去されることがあります。永続性を前提にしてはいけません。予測困難な名前と制限された権限を使用して、ファイルをアトミックに作成してください。シェルスクリプトではmktempを使用し、プログラムでは同等の安全な API を使用します。
名前空間付きのサブディレクトリによって衝突を回避し、所有権を一単位として管理できる場合は、アプリケーションファイルを /run や /var に直接配置しないでください。/run はデーモンへの接続に使用するソケットに適しています。永続的なデーモンデータは、そのソケットの隣ではなく /var 配下に置きます。
画像のリサイズと連結 #
ImageMagick 7 では magick コマンドを使用します。! を付けないジオメトリはアスペクト比を維持します。
# Fit within a width of 25 pixels, with unconstrained height.
magick src.png -resize 25x out.png
# Fit within a height of 25 pixels, with unconstrained width.
magick src.png -resize x25 out.png
# Scale both dimensions to 70 percent.
magick input.jpg -resize 70% output.jpg25x25 は「このボックス内に収める」という意味であり、「正確に 25 x 25 に強制する」という意味ではありません。意図的に歪ませる場合にだけ ! を追加し、正確な長方形を埋めて切り抜く必要がある場合は ^ と -extent を使用してください。
append 演算子は入力順序を維持します。
magick 1.jpg 2.jpg -append vertical.jpg
magick 1.jpg 2.jpg +append horizontal.jpg-append は上から下へ画像を積み重ね、+append は左から右へ画像を配置します。出力では、交差軸における最大の入力幅または高さが使用されます。-gravity は配置を制御し、-background は露出する空間を制御します。
magick -background '#202020' -gravity center 1.jpg 2.jpg +append row.jpgELF シンボルバージョンを調査する #
ELF シンボルバージョニングを使用すると、共有オブジェクトはシンボルについて複数世代の ABI を公開できます。リンカのバージョンスクリプトは、エクスポートされる名前をバージョンノードに割り当てることができ、.symver ディレクティブまたはライブラリのビルド機構は実装をそれらのノードにバインドできます。1 つの定義には @@ を付けてデフォルトとしてマークし、古い互換定義には @ を使用します。たとえば、memcpy@@GLIBC_2.14 は新しい未バージョンの参照に対して選択されるデフォルト定義であり、古いバイナリは memcpy@GLIBC_2.2.5 を要求することがあります。
バージョニングは、1 つの SONAME 内で後方互換の実装をサポートします。ただし、より新しいバージョンに対してビルドされたバイナリを、ライブラリに必要なノードがないシステムで実行可能にするものではありません。両方を調査してください。
readelf --dyn-syms --wide ./program
readelf --version-info ./program
objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep ' GLIBC_'readelf --version-info は、バージョン定義、要件、シンボルバージョンテーブルを表示します。objdump -T は、動的シンボルとそのバージョンを結合して表示します。ランタイムローダーは、選択された依存関係から、要求されたすべてのバージョンノードを解決する必要があります。診断中は LD_DEBUG=versions ./program を使用して、そのチェックを追跡できます。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)