cronjobで実行されるコマンド(logrotateなど)ではselinuxポリシーが機能しますが、コマンドラインから直接実行されるコマンドでは機能しないのはなぜですか?

cronjobで実行されるコマンド(logrotateなど)ではselinuxポリシーが機能しますが、コマンドラインから直接実行されるコマンドでは機能しないのはなぜですか?

cronjobで実行されるコマンド(logrotateなど)ではselinuxポリシーが機能しますが、コマンドラインから直接実行されるコマンドでは機能しないのはなぜですか?

コマンドラインから手動でlogrotateを実行すると、正常に動作します。しかし、cronjobで実行すると、audit.logにselinuxがwwwなどへのアクセスをブロックするというエラーが表示されます。

なぜそんなことですか?テストするためにcronjobで実行されていることをどのようにシミュレートできますか?

答え1

cronを実行すると、logrotateSELinuxはこれをlogrotate_t "type"に制限します。この「タイプ」は、他のファイルタイプを変更することを制限します(「エスケープ制限」とも呼ばれます)。

いつあなたlogrotateを実行すると、「無制限」タイプで始まる可能性が高くなります。つまり、logrotateプロセスがファイルを変更できることを意味します。プロセスを再開したり、シグナルを送信したりすることもできますlogrotate(例:postrotate)。このアクティビティはSELinuxによって制限されることがあります。

私の提案は、SELinuxに次のようにlogrotate_t型を制限外にすることを許可(「許可」)するように指示することです。

semanage permissive -a logrotate_t

これは中程度の軽い解決策です。SELinuxをオフにするそして、必要な制限エスケープを正確に許可するようにポリシーを微調整します(おそらくカスタムタグを使用)。この変更を元に戻すには、を使用しますsemanage permissive -d logrotate_t

cron実行プロセスをシミュレートする最善の方法は、タスクをcronに入れることです。そして私も知っていますruncon、私はそれを使用することに成功しませんでした。

答え2

特定の質問に関する@JeffSchallerの良い答えに追加するだけです。

テストするためにcronjobで実行されていることをどのようにシミュレートできますか?

cronjobでテストコマンドを実行することなく、ジョブの代替を共有できます。

まず、言及する価値がある微妙な詳細です。

従来の非SELinux環境でルート(有効UID = 0)で作業している場合は、通常、そのUIDの制限を「取得する」ために他のUIDに自由に切り替えることができます。

これはSELinuxとはまったく異なるコンテキストです。ルート(有効UID = 0)になると、通常は「無制限」コンテキストに置かれますが、自動的に他のコンテキストに自由に切り替えることはできません。むしろ、特定の「変換」操作を実行するために「制限されていない」コンテキスト権限を付与するには、明示的なSELinuxポリシールールが必要です。これらのルールをインストールした後、runconコマンドはそのコンテキストに正常に配置されます。

実際には、次のSELinuxポリシーが必要な場合があります。

allow unconfined_t crond_t:process transition;

(これがデーモンが実行されているSELinuxドメインであると仮定crond_tcrond

モジュール全体のコンパイルとインストールの規則は次のとおりです。

module unconfined-trans-crond 1.0;

require {
        type unconfined_t;
        type crond_t;
        class process transition;
}

allow unconfined_t crond_t:process transition;

モジュールをコンパイルしてインストールしたら、ターゲットruncon ドメインcrond_tを使用できますunconfined_t。たとえば、

# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# runcon $(ps -q $(pgrep crond) -o context --no-header) sh
# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:crond_t:s0
#

また、これを行うにはUID 0は必要なく、runcon現在のSELinuxコンテキストからターゲットSELinuxコンテキストへの移行を許可する正しいポリシールールが「単に」必要です。

実際にデーモン(例えばcrond)をテストするために通常ルートとして実行される完全なコマンドは次のとおりです。

runuser $(ps -q $(pgrep crond) -o user --no-header) -c 'runcon $(ps -q $(pgrep crond) -o context --no-header) /bin/bash'

crondユーザーとして実行されるシェルとそのSELinuxコンテキストを提供します。

テストが完了した後にポリシーを元に戻すには、カスタムモジュールを削除するだけです。

もちろん、これはさまざまな名前空間ビュー、リソース制限、cgroups、Linux機能などの他の可能な制限を考慮しません。 PAM設定がrunuser再生成された方法とある程度一致しない限り、これらの追加の制限を再生成するには、追加のコマンドを順番に実行する必要があります。

ファタイ

答え3

@Jeff_Schallerと@LL3の答えに触発され、このプロセスに適したsepolicyモジュールを見つける方法は次のとおりです。

:; sudo semanage permissive -a logrotate_t
# turn off selinux for logrotate temporarily to allow the logrotate command to go through, while still logging the denied messages in audit.log

:; sudo runcon -u system_u -r system_r -t logrotate_t logrotate -f /etc/logrotate.conf
:; sudo semanage permissive -d logrotate_t # re-enable selinux

:; sudo grep denied /var/log/audit/audit.log | audit2allow -M logrotate
# create a selinux policy based on the denied messages

:; sudo semodule -i logrotate.pp

内容はlogrotate.teこのように終わります

module logrotate 1.0;

require {
        type initrc_exec_t;
        type default_t;
        type policykit_t;
        type logrotate_t;
        class dbus send_msg;
        class file { create getattr ioctl open read setattr unlink write };
        class dir { add_name read remove_name write };
        class service reload;
}

#============= logrotate_t ==============
allow logrotate_t default_t:dir { add_name read remove_name write };

#!!!! WARNING: 'default_t' is a base type.
allow logrotate_t default_t:file { create getattr ioctl open read setattr unlink write };
allow logrotate_t initrc_exec_t:service reload;
allow logrotate_t policykit_t:dbus send_msg;

答え4

私はSElinuxについて深く理解しておらず、他の答えと同じかどうかはわかりません。私がする方法は次のとおりです。ディレクトリ内。semanage fcontext -a -t 'myCronTab' logrotate_exec_tこれにより、crontabとcronjobがlogrotate同じコンテキストに配置されるため、コマンドラインで実行されているのと同じにする必要があります。

関連情報