[FreeBSD 10]OSの起動途中でずっこける件

Pocket

いつの頃からか、OSを再起動するとClamAVを起動するタイミングでひっかかって止まってしまうようになった。コンソールを眺めていると、そのタイミングでサブシェルが起動されてコマンドプロンプト”$ ” で止まっている。手動で “exit” を入力してサブシェルから抜けてやれば起動プロセスが続行する。コンソールの前にいる時ならいいが、予期せぬ再起動がかかったり、リモートで再起動したりすると詰む。これに気づいたのは、リモートで遠隔から再起動をかけたらそのまま通信が途絶えたから(笑)。応急措置としてClamAVの使用を中止していたが、時間が取れたので原因を調べてみた。

手動で起動スクリプトをたたいて clamd を起動してみる。

# sh /usr/local/etc/rc.d/clamav-clamd start
Starting clamav_clamd.
$

コマンドプロンプトが #(root) から $(一般ユーザ) に変わって止まる。誰だお前? clamavか?

$ whoami
clamav
$

正解。この時、関連のプロセスはこんな感じ。

$ ps ax | grep clamd
48701  0  I        0:00.01 sh /usr/local/etc/rc.d/clamav-clamd start
48707  0  I        0:00.01 su -m clamav -c sh -c "/usr/local/sbin/clamd  "
48708  0  I        0:00.01 _su -m -c sh -c "/usr/local/sbin/clamd  " (csh)
48715  0  S+       0:00.00 grep clamd

この時点ではまだ clamd は起動していない。
手動で抜けてみると、しばらく待たされた後に root に戻り、clamdが起動する。ちなみに、リモートでOSの再起動をかけるとこの状態で止まって入力待ちになるので、万事休す。

$ exit
exit
# ps ax | grep clamd
48717  -  Is       0:00.00 /usr/local/sbin/clamd
48719  0  S+       0:00.00 grep clamd

exit でサブシェルから抜けないと clamd が起動しないようだ。
なお、終了時も同様。

# sh /usr/local/etc/rc.d/clamav-clamd stop
Stopping clamav_clamd.
$ exit
exit
Waiting for PIDS: 48717.

とりあえず、起動スクリプトを追いかけてみた。

[/usr/local/etc/rc.d/clamav-clamd]

(略)

. /etc/rc.subr

(略)

run_rc_command "$1"

至って普通の FreeBSD 流儀の起動スクリプトで特段アヤシイところは見当たらない。

48707  0  I        0:00.01 su -m clamav -c sh -c "/usr/local/sbin/clamd  "

起動プロセスはここでひっかかっているわけだが、サービスを root 権限ではなく一般ユーザー権限で起動するのはセキュリティの常道なので、su すること自体は不自然ではない。ただ、普通はサービス起動後にサブシェルから勝手に抜けるはず。ってことはどこかしら普通ではないってことだ(たぶん)。そこで、設定ファイル (clamd.conf) も確認してみる。

[/usr/local/etc/clamd.conf]
(略)
# Run as another user (clamd must be started by root for this option to work)
# Default: don't drop privileges
User clamav

さらに、clamd.conf のマニュアルにはこう明記されている。

$ man clamd.conf
(略)
       User STRING
              Run  the daemon as a specified user (the process must be started
              by root).
              Default: disabled

clamd.conf で root 以外のユーザを指定した場合、サービスの起動自体は root で実行しないといけないって言ってないか?

48707  0  I        0:00.01 su -m clamav -c sh -c "/usr/local/sbin/clamd  "

起動でひっかかっている箇所はここ。この “su -m clamav” ってそもそもいらないんじゃね?
普通に root で起動すればよくね? という疑問がわいた。

長ったらしいので気乗りはしないが、/etc/rc.subr も覗いてみた。

[/etc/rc.subr]

(略)

run_rc_command()

(略)

$command $rc_flags $command_args"
                                if [ -n "$_user" ]; then
                                    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
                                fi

該当箇所はここ。起動時に su する条件は「変数 $_user のサイズがゼロより大きい」こと。具体的には clamav_clamd_user が定義されていること。改めて起動スクリプトを見てみると、

[/usr/local/etc/rc.d/clamav-clamd]
#!/bin/sh
#
# $FreeBSD: branches/2018Q1/security/clamav/files/clamav-clamd.in 457649 2017-12-30 22:25:18Z ler $
#

# PROVIDE: clamav_clamd
# REQUIRE: LOGIN
# BEFORE: mail
# KEYWORD: shutdown

#
# Add the following lines to /etc/rc.conf to enable clamd:
#
# clamav_clamd_enable="YES"
# clamav_clamd_flags=""
#
# See clamd(8) for flags
#

. /etc/rc.subr

name=clamav_clamd
rcvar=clamav_clamd_enable

# read settings, set default values
load_rc_config "$name"

: ${clamav_clamd_enable:=NO}
: ${clamav_clamd_socket="/var/run/clamav/clamd.sock"}
: ${clamav_clamd_pidfile="/var/run/clamav/clamd.pid"}
: ${clamav_clamd_user="clamav"}

(後略)

最後の1行の意味は「/etc/rc.conf に clamav_clamd_user が記述されていなかったら “clamav” にしとく」ということだけど、これ余計じゃね? こいつのせいで起動時に “su -m clamav” が発動してるんじゃね? ってことで、この挙動を抑止するため、rc.conf で明示的に clamav_clamd_user を空にしてみる。起動スクリプト側を削ってもいいんだけど、アップデートで上書きされたら元通りだし。

余談だが、シェルスクリプト内での : (コロン) の使い方って非常に奥が深いので、興味のある方は調べてみるのおすすめ。

[/etc/rc.conf]
clamav_clamd_enable="YES"
clamav_clamd_user=""

# sh /usr/local/etc/rc.d/clamav-clamd start
Starting clamav_clamd.
#

起動に時間がかかるものの、root のまま処理は正常に終了。

# ps ax | grep clamd
49061  -  Is       0:00.00 /usr/local/sbin/clamd
49063  0  DL+      0:00.00 grep clamd

# ps aux | grep 49061
clamav  49061   0.0 44.1 512892 450212  -  Is    5:02PM     0:00.00 /usr/local/

一般ユーザ clamav の権限で実行されていることを確認。なんか、これで解決したっぽい?

この記事にコメントする

Powered by WordPress, WP Theme designed by WSC Project. ログイン