ElasticSearch OSS / OpenSearch の Beats が “runtime/cgo: pthread_create failed: operation not permitted” で落ちるのを直す

どうも、みむらです。

某所の監視に Wazuh ( https://wazuh.com/ )をよく使っているのですが
内部的に ElasticSearch OSS 7.10.2 を使っているため、新しすぎる OS 上で動かそうとすると filebeat が下記のように落ちてしまうことがあります

runtime/cgo: pthread_create failed: Operation not permitted

もちろん、この問題は新しいバージョンの Beats では解決されているのですが
他方で 7.13 以降の Beats は OpenSearch 1.x や Elasticsearch OSS などで使えないという問題があります。

https://opensearch.org/docs/latest/clients/agents-and-ingestion-tools/index/

この問題については、下記のコメントにあるように elasticsearch 側もアップデートすることが推奨されていますので、公式に解決される可能性は低そうです。

https://github.com/elastic/beats/pull/26305#issuecomment-863472649

枯れたものを使え、公式でサポートしていないディストリビューションを使うな、というのは一理あるのですが、その方法で回避するのは面白くないですので、修正含めてやってみました。

(wazuh のサポートで解決している例が見当たらなかったこともあり、最初だけ英語で併記します。)

注意:

修正は自己責任でお願いします。本番用環境に対して独自ビルドを行ったものを適用したことにより問題が発生しても当方では責任を負えません。


落ちる原因 (Cause):

“clone3” のシステムコールが seccomp の許可リストに登録されていないため。
en : The systemcall “clone3” is not allowed by seccomp.

glibc 2.34 以降において、 pthread_create() を呼び出す際に clone3 システムコールが用いられるようになったことが原因となっています。

修正方法 (Solution):

libbeat/common/seccomp 以下の “policy_linux_386.go” と “policy_linux_amd64.go” に “clone3” を追記する
en: Add “clone3” to policy_linux_386.go and policy_linux_amd64.go under libbeat/common/seccomp.

具体的な追加内容については、まさしく当該する patch がありますのでこれに従います。
https://github.com/elastic/beats/commit/82507fda20bee46cee4808d388a0c809dd01ff13

また glibc 2.35 以降では “rseq” システムコールも用いるそうですので
こちらも併せて対応しておくとよいと思います。
en: It is a recommend to also add “rseq” to policy_linux_386.go and policy_linux_amd64.go under libbeat/common/seccomp, due to the syscall is used glibc >= 2.35.

https://github.com/elastic/beats/commit/f02fa32e0a37d6529983e2181b80bf62e4a16b41


実際にやってみる

実際に上記のパッチを当てて問題が解決するか確認してみました。

確認環境 : Fedora 36 x86_64

1. beats のソースコードを取ってくる

今回の例では wazuh で配信されているのが filebeat 7.10 ですのでこちらに合わせます。
(Elasticsearch OSS に対応している最新バージョンを用いる場合は 7.12 を使ってください)

git clone https://github.com/elastic/beats -b v7.10

2. パッチを当てる

下記の2つのコミットに併せてファイルを修正します。

common/seccomp: add rseq syscall (#30620)
https://github.com/elastic/beats/commit/f02fa32e0a37d6529983e2181b80bf62e4a16b41

seccomp: allow clone3 syscall for x86 (#28117)
https://github.com/elastic/beats/commit/82507fda20bee46cee4808d388a0c809dd01ff13

修正した差分としては下記の通りとなります。

diff -r -u old/libbeat/common/seccomp/policy_linux_386.go new/libbeat/common/seccomp/policy_linux_386.go
--- old/libbeat/common/seccomp/policy_linux_386.go      2022-06-10 06:19:17.664958700 +0900
+++ new/libbeat/common/seccomp/policy_linux_386.go      2022-06-10 06:20:36.020958700 +0900
@@ -35,6 +35,7 @@
                                        "chown",
                                        "clock_gettime",
                                        "clone",
+                                       "clone3",
                                        "close",
                                        "dup",
                                        "dup2",
@@ -99,6 +100,7 @@
                                        "rename",
                                        "renameat",
                                        "restart_syscall",
+                                       "rseq",
                                        "rt_sigaction",
                                        "rt_sigprocmask",
                                        "rt_sigreturn",
diff -r -u old/libbeat/common/seccomp/policy_linux_amd64.go new/libbeat/common/seccomp/policy_linux_amd64.go
--- old/libbeat/common/seccomp/policy_linux_amd64.go    2022-06-10 06:17:27.775958700 +0900
+++ new/libbeat/common/seccomp/policy_linux_amd64.go    2022-06-10 06:20:47.961958700 +0900
@@ -38,6 +38,7 @@
                                        "chown",
                                        "clock_gettime",
                                        "clone",
+                                       "clone3",
                                        "close",
                                        "connect",
                                        "dup",
@@ -111,6 +112,7 @@
                                        "recvmsg",
                                        "rename",
                                        "renameat",
+                                       "rseq",
                                        "rt_sigaction",
                                        "rt_sigprocmask",
                                        "rt_sigreturn",
diff -r -u old/libbeat/common/seccomp/seccomp-profiler-allow.txt new/libbeat/common/seccomp/seccomp-profiler-allow.txt
--- old/libbeat/common/seccomp/seccomp-profiler-allow.txt       2022-06-10 06:21:00.270958700 +0900
+++ new/libbeat/common/seccomp/seccomp-profiler-allow.txt       2022-06-10 06:21:11.876958700 +0900
@@ -3,6 +3,7 @@
 set_robust_list
 tgkill
 time
+rseq

 # cgo os/user
 access

なお上記の patch を使う場合は下記のようなコマンドで適用可能です

# beats = git clone したディレクトリ
# patch.patch = 上記の内容を記録したテキストファイル

patch -d beats -p1 < patch.patch

3. 依存するモジュールを修正する

当方で確認を進めた際、 “service” が blakerouse さんのリポジトリから上手く取得出来ませんでした。

そのため、下記のように “go.mod” 内の replace 句内にある行を1行削除します。

--- old_go.mod  2022-06-10 06:40:17.691958700 +0900
+++ go.mod      2022-06-10 06:40:27.436958700 +0900
@@ -199,7 +199,6 @@
        github.com/fsnotify/fsnotify => github.com/adriansr/fsnotify v0.0.0-20180417234312-c9bbe1f46f1d
        github.com/google/gopacket => github.com/adriansr/gopacket v1.1.18-0.20200327165309-dd62abfa8a41
        github.com/insomniacslk/dhcp => github.com/elastic/dhcp v0.0.0-20200227161230-57ec251c7eb3 // indirect
-       github.com/kardianos/service => github.com/blakerouse/service v1.1.1-0.20200924160513-057808572ffa
        github.com/tonistiigi/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
        golang.org/x/tools => golang.org/x/tools v0.0.0-20200602230032-c00d67ef29d0 // release 1.14
 )

4. ビルドする

全部をビルドしてもよいですが、
今回は wazuh 用に filebeat のみビルドしてみます。

cd filebeat
go get
make

完了すると、同じディレクトリに “filebeat” という名前の実行ファイルが生成されます。


5. 差替える

お行儀は余り良くないですが、
今回生成した filebeat を systemd から呼び出される filebeat のファイルと差替えます。

cp ./filebeat /usr/share/filebeat/bin/filebeat
cp ./filebeat /usr/bin/filebeat

差替えた後、 systemctl 等で起動すれば落ちない filebeat のできあがりです。


まとめ

glibc 2.34 以降の環境で wazuh 等の Elasticsearch-oss と合わせた beats を使う場合に、seccomp の修正が必要という内容です。

冒頭にも書きましたが、これを行うことについては自己責任となりますが
もし困っている方の助けとなりましたら幸いです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です