AppArmor で、ある特定の呼ばれ方をした時だけよりたくさんの権限を与えたいという事があります。例えばこんなシナリオを考えます。
- プログラム /tmp/cat (/bin/cat のコピー) はあるファイル /tmp/white.txt だけを読める。
- プログラム /tmp/parent は /tmp/cat を実行できる。parent は /tmp/white.txt と /tmp/red.txt の両方を読める。
- /tmp/cat も /tmp/parent もその他のファイルにアクセスできない。
つまり、/tmp/cat はファイル一つしか読めませんが、/tmp/parent 経由で読むと二つ読めるのです。これをやります。まず必要なファイルを準備します。
cp /bin/cat /tmp/cat
echo Hello white > /tmp/white.txt
echo Hello red > /tmp/red.txt
echo Hello black > /tmp/black.txt
ここで子プロセス /tmp/cat を呼び出すだけのプログラム parent.cpp を作り /tmp/parent に置きます。
#include <stdlib.h>
#include <string>
#include <iostream>
int main(int argc, char **argv)
{
if (argc != 2)
{
std::cerr << "usage: parent filename" << std::endl;
exit(1);
}
std::string command = "/tmp/cat";
int ret = system((command + " " + argv[1]).c_str());
exit((ret == 0) ? 0 : 1);
}
テストプログラムはこんなかんじ。
#!/bin/sh
set -o errexit
set -o nounset
set -o xtrace
/tmp/parent /tmp/white.txt || exit 1
/tmp/parent /tmp/red.txt || exit 1
/tmp/parent /tmp/black.txt && exit 1
/tmp/cat /tmp/white.txt || exit 1
/tmp/cat /tmp/red.txt && exit 1
/tmp/cat /tmp/black.txt && exit 1
exit 0
white.txt だけを読める /tmp/cat のプロファイル /etc/apparmor.d/tmp.cat は 前回 と同じです。
include <tunables/global>
/tmp/cat {
include <abstractions/base>
/tmp/white.txt r,
}
/tmp/parent のプロファイルの書き方は色々あるので順番に見ていきます。
ix (継承) を使うパターン
継承を使うというのは、子プロセスにも親プロセスと同じ権限を与えるというものです。この場合、親プロセスに余分な権限が必要という難点があります。これで /tmp/parent 経由で呼ぶことで /tmp/red.txt にもアクセスできるようになります。
# ix (継承) を使うパターン
include <tunables/global>
/tmp/parent {
include <abstractions/base>
/bin/dash mrix,
/tmp/cat ix,
/tmp/white.txt r,
/tmp/red.txt r,
}
cx (Child profile: 子プロファイル) を使うパターン
子プロファイル (cx) というのは、プロファイルの中に埋め込んだプロファイルの事です。これで親子別の権限を与える事が出来ます。
include <tunables/global>
/tmp/parent {
include <abstractions/base>
/bin/dash mrix,
/tmp/cat cx, // ここで cx を指定
profile /tmp/cat {
include <abstractions/base>
/tmp/cat mr,
/tmp/white.txt r,
/tmp/red.txt r,
}
}
px (Discrete profile: 独立プロファイル) を使うパターン
独立プロファイル (px) を使うと、子プロセスの権限を別のプロファイルに書くことが出来ます。矢印 -> の右側を省略すると、この場合上記 /etc/apparmor.d/tmp.cat に書いたプロファイルが選択されていまいますが、-> の右に明示的にプロファイル名を書くことで別のプロファイルを指定できます。これで、/tmp/cat を直接実行するよりも多い権限を与える事ができます。
include <tunables/global>
/tmp/parent {
include <abstractions/base>
/bin/dash mrix,
/tmp/cat px -> parent_cat, // ここで px を指定。更にプロファイル名を指定。
}
profile parent_cat {
include <abstractions/base>
/tmp/cat mr,
/tmp/white.txt r,
/tmp/red.txt r,
}
参考