OpenSUSE 15.4アップデートでPHP(php-fpm)が使用できなくなった

OpenSUSE(Leap)の15.4がリリースされ、15.3から15.4にアップグレードしたあとにapache内で実行するPHPスクリプトがことごとく動かず、「Access denied」やら「Error!」やら表示されるようになってしまった。

原因はApparmorです

調べると、原因はApparmorによってphp-fpmの動きが阻害されている模様。
よく見ると「/var/log/audit/audit.log」に詳細が記載されている。

下記のようなコマンドを実行すると、ずらっとエラーが表示されて
app armorでphp-fpmが阻害されていることがわかると思う。

# tail -n 2000 /var/log/audit/audit.log | grep 'apparmor="DENIED"'

Apparmorの例外ルールに追加

ここまででphp-fpmが動いておらず悩んでいるということは、
apparmorのルールに「php-fpm」が作られているハズなので(なければ作って)、例外を追加していく。

一般的なディレクトリであれば、「/etc/apparmor.d/php-fpm」になっているはずなので
(なければ自分でルールディレクトリ探して作って)どういう構造になっているかをチェック。

# cat /etc/apparmor.d/php-fpm

おそらくデフォでは下記のような構成になっている。

# Last Modified: Sun Feb * *:*:* 2022
abi <abi/3.0>,

include <tunables/global>

# vim: ft=apparmor


profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
  include <abstractions/base>
  include <abstractions/nameservice>
  include <abstractions/openssl>
  include <abstractions/php>
  include <abstractions/ssl_certs>
  include <abstractions/user-tmp>
  include if exists <local/php-fpm>
  include if exists <php-fpm.d>

  capability chown,
  capability dac_override,
  capability kill,
  capability net_admin,
  capability setgid,
  capability setuid,

  signal send peer=php-fpm//*,

  deny / rw,
  
  /usr/sbin/php-fpm* rix,
  /var/log/php*-fpm.log rw,
  @{PROC}/@{pid}/attr/{apparmor/,}current rw,
  @{run}/php{,-fpm}/php*-fpm.pid rw,
  @{run}/php{,-fpm}/php*-fpm.sock rwlk,
  owner /etc/ImageMagick-7-SUSE/english.xml r,
  owner /etc/ImageMagick-7-SUSE/locale.xml r,
  owner /etc/ImageMagick-7-SUSE/log.xml r,
  owner /etc/ImageMagick-7-SUSE/policy.xml r,

  change_profile -> php-fpm//*,

}

この下のほうにあるゴチャゴチャしたところ(30行目~38行目の間)に、
例外するディレクトリと許可する権限を右に書く。
今回は、/home/全ユーザー/scripts/下に設置されたすべてのスクリプトを信頼して、読み/書き/ロックを許可するように記述を追加する。

  /home/*/scripts/** rwk,

*は1個だけだとそのディレクトリにしか効果を及ぼさないため、
ディレクトリ下の階層にも波及させたい場合は**(アスタリスクを2個)を使う。
詳細なapparmorの記述ルールについては、公式マニュアル参照。

最終的な/etc/apparmor.d/php-fpmは下記の通り。

# Last Modified: Sun Feb * *:*:* 2022
abi <abi/3.0>,

include <tunables/global>

# vim: ft=apparmor


profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
  include <abstractions/base>
  include <abstractions/nameservice>
  include <abstractions/openssl>
  include <abstractions/php>
  include <abstractions/ssl_certs>
  include <abstractions/user-tmp>
  include if exists <local/php-fpm>
  include if exists <php-fpm.d>

  capability chown,
  capability dac_override,
  capability kill,
  capability net_admin,
  capability setgid,
  capability setuid,

  signal send peer=php-fpm//*,

  deny / rw,
  
  /home/*/scripts/** rwk,
  /usr/sbin/php-fpm* rix,
  /var/log/php*-fpm.log rw,
  @{PROC}/@{pid}/attr/{apparmor/,}current rw,
  @{run}/php{,-fpm}/php*-fpm.pid rw,
  @{run}/php{,-fpm}/php*-fpm.sock rwlk,
  owner /etc/ImageMagick-7-SUSE/english.xml r,
  owner /etc/ImageMagick-7-SUSE/locale.xml r,
  owner /etc/ImageMagick-7-SUSE/log.xml r,
  owner /etc/ImageMagick-7-SUSE/policy.xml r,

  change_profile -> php-fpm//*,

}

Apparmorのルールを書き換えたら、ルールを再読み込みさせなければならないので、
下記コマンドを実行する。(/etc/apparmor.d/php-fpmの部分は更新したルールファイル)

# apparmor_parser -r /etc/apparmor.d/php-fpm

このコマンドで(構文エラーさえなければ)即時リロードされ、php-fpmの実行が可能になっているはず。

は? キレそう。まだエラー出るんだけど?

原因は下記コマンド実行で探れる。

# logprof

実行すると、audit.logからブロックされている部分を拾ってきて、対話的にどうするかを聞いてくる。

対話的に指定したAllow/Denyなどは質問の最後でSaveを選ぶと特定のルールファイルにルールが追加され、ルールファイルのリロードまでを行ってくれる。

ただし、ガチでファイル一個一個に許可/拒否を聞いてくるので、WordPressのようなPHPの塊のようなシステムだとワケわからんくなる。なのでlogprofである程度原因探ってSaveせずにAbortして、自分で例外ファイルにディレクトリ指定で突っ込んだほうが早い。

参考文献

コメントを残す