Windows10+WSL2+dockerにてseccompで、はまる
はじめに
ネバ―・フレンズ・Tです。Windows10+WSL2を使っていてGUIを無性に使いたくなるときってありません?
今回はWindows10+WSL2+ubuntu 20.04+VNC+docker(moby版)でdebian unstableのGUI環境を動かしてはまったことを書きます。
なお、未確認ですが、現在最新のubuntu 22.04では本ブログで語る問題は全部治っているハズ…なのでそこはご了承ください。dockerdまわりではまったらこうやってデバッグすることもある…ということで生暖かくみていただければと思います!
Windows10+WSL2+ubuntu 20.04にdockerを手早く用意
Windows10+WSL2上のubuntu 20.04にdockerをさらっと用意します。apt一発でインストール完了、systemdを起動してsystemdのpidにnsenterしてからdockerdを起動するだけなので、超簡単ですね!1
$ uname -a
Linux your-machine 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -dirc
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
$ sudo apt install systemd docker.io daemonize util-linux
$ sudo usermod -a -G docker $USER
$ sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
$ SYSTEMD_PID_OUTER=$(ps -auxww | fgrep '/lib/systemd/systemd' | fgrep system-unit | fgrep -v unshare | awk '{print $2}' )
$ sudo nsenter --target $SYSTEMD_PID_OUTER --all su - $LOGNAME
$ ps -auxww | fgrep '/lib/systemd/systemd' | fgrep system-unit | fgrep -v unshare
root 1 0.0 0.0 174152 11640 ? Ss 20:15 0:00 /lib/systemd/systemd --system-unit=basic.target
$ sudo sytemctl start docker
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナでらくらくVNC+GUI
GUI環境はVNC、debian sidのコンテナイメージ使って用意します。個人利用なのでセキュリティは少々度外視で、VNCの接続パスワードだけで接続許可することにします。
$ mkdir debian-gui
$ cd docker-gui
$ cat > DockerFile
FROM debian:unstable
LABEL application=debian-gtkblog
ARG DEBIAN_FRONTEND=noninteractive
RUN sed -i "s/$/ contrib non-free/" /etc/apt/sources.list && \
apt update && apt full-upgrade -y && \
apt install -y apt-utils debconf sudo procps man && \
apt install -y locales tigervnc-standalone-server xfonts-75dpi xfonts-100dpi fonts-ipafont xfce4 xfce4-goodies gnome-flashback-common dbus-x11 && \
useradd -m -s /bin/bash yours && \
echo "yours ALL=(ALL:ALL) NOPASSWD:ALL" | tee /etc/sudoers.d/yours && \
chmod 600 /etc/sudoers.d/yours && \
sed -i -e 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \
dpkg-reconfigure locales && \
update-locale LANG=ja_JP.UTF-8
COPY start_xfce.sh /home/yours
ENV LANG ja_JP.UTF-8
USER yours
CMD ["/bin/sh","/home/yours/start_xfce.sh"]
<CTRL+D押下>
$ cat > start_xfce.sh
#!/bin/sh
PATH=/bin:/usr/bin
VNC_DIR=${HOME}/.vnc
PASSWD_FILE=${VNC_DIR}/passwd
STARTUP_FILE=${VNC_DIR}/Xvnc-session
[ -d $VNC_DIR ] || mkdir $VNC_DIR
: ${VNCPASS:="1234"}
echo "$VNCPASS" | vncpasswd -f > ${PASSWD_FILE}
cat >${STARTUP_FILE} <<__HERE
#!/bin/sh
xfce4-session --display=:1
__HERE
chmod 755 ${STARTUP_FILE}
: ${RESOLUTION:="1280x1024"}
tigervncserver -fg -localhost no -geometry "${RESOLUTION}" -PasswordFile ${PASSWD_FILE} -xstartup ${STARTUP_FILE} 2>&1
<CTRL+D押下>
$ docker build --no-cache -t debian-sid-gui .
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
debian-sid-gui latest 035d280628a4 37 minutes ago 1.33GB
$ docker run --rm -d -e VNCPASS="hogefuga" -e RESOLUTION="1920x1200" -p :5901:5901 debian-sid-gui:latest
次にWindows10に、UltraVNC梱包のVNC Viewerを導入しておきます。
早速Windows10側で、UltraVNC Viewerを立ちあげ、接続先に"127.0.0.1:5901"、パスワードを聞かれたら"hogefuga"と入力します。すると図の通り、あっさり無事debian unstableによるxfce4のデスクトップ画面が出てきました!
xfce4-terminalでbashの起動に失敗するぞ!?
なんだ楽勝じゃんって思ったそこのあなた!序盤はほのぼの・ゆるゆる系で大安心、でも早速修羅場に叩き込むのはアニメも漫画もお約束です!
基本のxfce4-terminalを立ちあげてみましょう!
bashの起動に失敗しました…ときました。よくもだましたアアアアア!!
使い物になりませんねw。動かないなら直すしかありませんよね、仕方ないですよね、早速調査開始デス!
--security-opt="seccomp=uncofined"
で解決するが…
画面には、“Failed to fdwalk"とありますので、“docker Failed to fdwalk xfce4-terminal"とまずgoogle検索します。ばっちり全く同じ症状の人がいるじゃないですか。
Failed to fdwalk: Operation not permitted
こちらのissueを見ると、--security-opt="seccomp=unconfined"
をつけて起動するといいよとあります。issueはx11dockerというソフトウェアですが、dockerにも同じようなオプションがあるので実験してみます。
早速やってみましょう!
$ docker run --rm -d -e VNCPASS="hogefuga" -e RESOLUTION="1920x1200" --security-opt="seccomp=unconfined" -p :5901:5901 debian-sid-gui:latest
vncを繋いでxfce4-terminalを立ちあげてみます。
何の問題もなく立ち上がりました。xfce4-terminalもbashも動いてヨカッタヨカッタ!
seccompの調査を開始
今回は簡単にGUIを用意するお話をしました!問題もググったら一発解決!次回もサービス、サービスう!とは弊社ではならないところがお約束です。
なぜ動かないのか?を調べないとこのブログは終わりません。これが弊社サービスだったりすると、seccompを外したままでいいのか?という各方面からのツッコミにも答えないといけない時がきちゃいます2。
先ほどつけた--security-opt="seccomp=unconfined"
は、dockerにlinux kernelの機能であるseccompを利用しないで欲しいと指定するものです。少なくともseccompが何かをおかしくするわけです。google検索して見つかったissueにはclose_rangeシステムコールがおかしくなるようなことが示唆されています。
seccompのはたらきについてlibseccompを利用した前提で図示すると図の通りです。
つまりは、ユーザプロセスが何かシステムコールを発行しようとするとブロックされたりするわけです。じゃあ、今回何がブロックされたの?ということを知らないと調査も対策も打てません。
dockerではseccompのログが取れないぞ??
seccompはsystem callに対してなにかが発動すると、ログを残す能力があります。早速auditdを立ち上げて3、seccompのログを確認してみましょう。
$ sudo systemctl start auditod
$ ausearch -ua $(id -u) #<- authlogを検索してみて直前の操作のログが出てるか?を見る
----
time->Thu Mar 17 22:37:15 2022
type=USER_AUTH msg=audit(1647524235.362:787): pid=883147 uid=1000 auid=4294967295 ses=4294967295 msg='op=PAM:authenticat
ion grantors=pam_permit,pam_cap acct="yours" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/2 res=success'
----
time->Thu Mar 17 22:37:15 2022
type=USER_ACCT msg=audit(1647524235.362:788): pid=883147 uid=1000 auid=4294967295 ses=4294967295 msg='op=PAM:accounting
grantors=pam_permit acct="yours" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/2 res=success'
$ docker run --rm -d -e VNCPASS="hogefuga" -e RESOLUTION="1920x1200" -p :5901:5901 debian-sid-gui:latest
...vncでxfce4-terminalを動かしてbashの起動が失敗と出ることを確かめる...
$ ausearch -m seccomp #<- seccompにひっかかったログを検索。
...何も出てこない...
authlogには何も記録されてません。自分でlibseccomp使って簡単なテストプログラムを作ってみればわかるのですが、seccompにfilterアクションに対してログを残しましょうという手続きを追加しないと、一部のfilterアクションを除いてログを出してくれません。具体的には、
API int seccomp_attr_set(scmp_filter_ctx ctx,
enum scmp_filter_attr attr, uint32_t value)
に、attr=SCMP_FLTATR_CTL_LOGと、value=1を指定すれば良いだけの簡単なお仕事です。
このままでも何か謎を解く方策があるのでは?とdockerのマニュアルひっくり返しますが、seccompのログを出せ!といったことは一切触れられていないようです。困りました。
kernelのdebug機能も使えないぞ!?
seccompで引っかかったsystem callを何とかしてログに出す方法をいろいろ考えましたが、kernelの内部構造上、seccompのフィルタを設定すると通常のsystem callの応答をsystem callのエントリ内部でさっさと決めてしまう動作なので、kernelの簡易なdebugインターフェースを利用しても有意な情報を取り出せません。つまり、kernelのdebugインターフェースをもってしても、特定のsystem callが突然-EPERMとかのエラーを返すようになってしまうようにしか見えない(引っかかったらkernel内部の特定の関数に飛んでいくわけでもない)という感じなので役にたちません。
こうなったら意地でもログが出るように改造しかありません。さらなる改造を望むか?改造!改造!改造!と声がします。
runc改造したら、close_rangeシステムコールが原因だー
改造する場所をまずは決めます。有名FOSSに数行改造して己のいう事を聞かせた時など胸がすくような気持ちがするわけですから、そういう場所を探します。
dockerがコンテナを生成・管理する際に連携するソフトウェアは、ubuntu 20.04付属のdockerの場合、dockerd、containerd群、runcとなります。このどれがlibseccompを吸い込んでいるか?を引き当てます。
$ for cmd in dockerd containerd runc ;do ldd $(command -v $cmd) | fgrep seccomp |
sed -e "s/^/${cmd}:/";done
runc: libseccomp.so.2 => /lib/x86_64-linux-gnu/libseccomp.so.2 (0x00007f6494abb000)
runcのみのようです。runcの改造箇所をさがします。
$ sudo apt install silversearcher-ag
$ apt-get source runc
$ ag seccomp -G '\.go$'
...中略...
runc-1.0.1/libcontainer/standard_init_linux.go
14: "github.com/opencontainers/runc/libcontainer/seccomp"
146: // Seccomp rules have been applied, because we need to be able to read and
155: // Without NoNewPrivileges seccomp is a privileged operation, so we need to
158: if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges {
159: if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
...中略...
いかにも初期化部分であるようなファイル名(standard_init_linux.go)と、僕が初期化部分だよ!といいたげなseccomp.InitSeccomp()が見つかります。今度はInitSeccomp()はどこだ?と探してみます。
$ ag InitSeccomp -G '\.go$'
...中略...
runc-1.0.1/libcontainer/seccomp/seccomp_linux.go
34:func InitSeccomp(config *configs.Seccomp) error {
...中略...
seccomp_linux.goが見つかります。中を確認します。
$ less runc-1.0.1/libcontainer/seccomp/seccomp_linux.go
...中略...
func InitSeccomp(config *configs.Seccomp) error {
if config == nil {
return errors.New("cannot initialize Seccomp - nil config passed")
}
defaultAction, err := getAction(config.DefaultAction, config.DefaultErrnoRet)
if err != nil {
return errors.New("error initializing seccomp - invalid default action")
}
filter, err := libseccomp.NewFilter(defaultAction)
if err != nil {
return fmt.Errorf("error creating filter: %s", err)
}
..中略...
// Unset no new privs bit
if err := filter.SetNoNewPrivsBit(false); err != nil {
return fmt.Errorf("error setting no new privileges: %s", err)
}
おおっと、すでにlibseccompのfilter attributeを調整している箇所(filter.SetNoNewPrivsBit(false))があるじゃありませんか。余談ですが、他にfilter attributeを調整している箇所がruncになさそうであることもわかって、seccompのログが出ないわけじゃん!と軽く絶望しました。
早速改造します。本来はdch -i して、debian/changelogでruncのパッケージバージョンを"1.0.1-0ubuntu2~20.04.1oreore1"に設定、 quiltあたりを使ってdebian(ubuntu)側のpatch形式にしてdebian/patch/以下に収めるとかしますが、書くと長いのでここではパスしますw。
なお、libseccompのseccomp_attr_set()に、attr=SCMP_FLTATR_CTL_LOGと、value=1を設定するには、go言語だとlibseccomp-golangモジュールのfilter.SetLogBit(true)となります。
今回は出来上がったものを見せます。
$ head -n 10 runc-1.0.1/debian/changelog
runc (1.0.1-0ubuntu2~20.04.1oreore1) UNRELEASED; urgency=medium
* Add Log capability of seccomp.
-- Your Name <your@mail.address> Tue, 15 Mar 2022 21:10:51 +0900
runc (1.0.1-0ubuntu2~20.04.1) focal; urgency=medium
* Backport version 1.0.1-0ubuntu2 from Impish (LP: #1938908).
$ cat runc-1.0.1/debian/patches/series
test--skip-Hugetlb.patch
test--skip_TestFactoryNewTmpfs.patch
test--skip-fs-related-cgroups-tests.patch
add-log-feature-seccomp-violation.patch
$ # ↑add-log-feature-seccomp-violation.patch が今回追加のpatch
$ cat runc-1.0.1/debian/patches/add-log-feature-seccomp-violation.patch
Add feature of logging when syscall is vaiolate in seccomp.
--- a/libcontainer/seccomp/seccomp_linux.go
+++ b/libcontainer/seccomp/seccomp_linux.go
@@ -11,6 +11,7 @@
libseccomp "github.com/seccomp/libseccomp-golang"
"golang.org/x/sys/unix"
+ "github.com/sirupsen/logrus"
)
var (
@@ -46,6 +47,13 @@
return fmt.Errorf("error creating filter: %s", err)
}
+ // Add log feature of seccomp when syscall is violation
+ err = filter.SetLogBit(true)
+ if err != nil {
+ return fmt.Errorf("error set log bit to the attribute of seccomp filter: %s", err)
+ }
+ logrus.Infof("Successfly enabling logging seccomp to auditd")
+
// Add extra architectures
for _, arch := range config.Architectures {
scmpArch, err := libseccomp.GetArchFromString(arch)
早速パッケージにしてインストールします。
$ sudo apt install ubuntu-dev-tools
$ sudo apt build-dep runc
$ cd runc-1.0.1
$ dpkg-build -us -uc | tee ../build.log
$ cd ..
$ dpkg -i runc_1.0.1-0ubuntu2~20.04.1oreore1_amd64.deb
それでは、ログが出るか?を確かめます。
$ docker run --rm -d -e VNCPASS="hogefuga" -e RESOLUTION="1920x1200" -p :5901:5901 debian-sid-gui:latest
...vncでxfce4-terminalを動かしてbashの起動が失敗と出ることを確かめる...
$ ausearch -m seccomp
Error opening config file (Permission denied)
NOTE - using built-in logs: /var/log/audit/audit.log
----
time->Wed Mar 16 23:15:13 2022
type=SECCOMP msg=audit(1647440113.559:720): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=881840 comm="xfce4-term
inal" exe="/usr/bin/xfce4-terminal" sig=0 arch=c000003e syscall=436 compat=0 ip=0x7ff19e041f79 code=0x50000
おお!ばっちりログが記録されるようになりました。なになに?syscall=436がダメとな。436番目のsyscallって何だ?というわけで調べます。
ここでauditdに詳しい方は、ausyscall 436でわかるじゃん!とつかさずツッコまれるとおもいますが、大変残念なことにubuntu 20.04付属のausyscallは、auditd-1.0.1/lib/x86_64_table.hというauditdに梱包された独自作成のsystem call名と値のテーブルからひっぱってくるだけなので、当然のように載っていません。少々愚痴ると、kernelの機能にて、system call名(string)とsystem call番号(int)の表を動いているkernelから直接引っ張ってくるようなI/Fがないのでこんなことになってます。ちなみにこれがどんな問題を引き起こすかというと…
- auditのログのsystem callが番号でしかkernelもログに残せないw あくまでkernelが知っているのはsystem call番号に対する処理への関数のアドレスだけ(sys_call_table[]というkernel内部変数が対応表としてあるだけです)
- strace/ausyscall/libseccomp等の有用なソフトウェアは、system call名からsystem call 番号を引いたりその逆をやるためのテーブルを各自で独自に持つしかないです。なので、kernelのアップデートが行われたらこれらも合わせて追従しつづけなければならないという呪いがかかったまま
kernelが/proc/ksymsにsys_call_table[]をシンボルとして露出してくれれば、そこからアドレスを読みだして/proc/ksymsで引き当てれば表を自動で生成できるかなーと一瞬思ったのですが、そもそも露出してないのでどうにもなりません。さらに悪いことに、昨今ではKASLRなんて機能もあってそもそもkernel内部のアドレスって外部から読みだして役に立つんだっけ?など疑問が尽きません。
とにかく既存のコマンドとかが先の2の理由により役に立たないので、kernelのソースから調べるしかありません。
$ sudo apt install git
$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
$ egrep '^436' WSL2-Linux-Kernel/arch/x86/entry/syscalls/syscall_64.tbl
436 common close_range sys_close_range
というわけで、close_rangeシステムコールがseccompではじかれてしまったということが判りました。
close_rangeシステムコールが動かないのは、全部libseccompが悪い
さあ、close_rangeシステムコールがruncのseccompで許可されないのなら、許可されるようにするまでです。どうもdocker/dockerd/containerdも、デフォルトのseccomp向け設定を持っているので、そこから正しいか?を調べる必要があります。ここでとても運がいいことに、containerdは現在稼働中のコンテナに対する起動に必要な情報を/run/containerd以下に書きだしているということがわかります。
$docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
f33ac998279a debian-sid-gui:latest "/bin/sh /home/yours…" 8 seconds ago Up 7 seconds 0.0.0.0:5901->5901/tcp, :
::5901->5901/tcp keen_hertz
$ sudo -su root -H
# cd /run/containerd/io.containerd.runtime.v2.task/moby/f33ac998279a*/
# ls
address config.json init.pid log log.json options.json rootfs runtime work
# less config.json
{"ociVersion":"1.0.2-dev","process":{"user":{"uid":1000,"gid":1000},"args":["/bin/sh","/home/yours/start_xfce.sh"],"env
":["PATH=/usr/l
...中略...
早速containerdがコンテナに設定しているseccompの値を調べます。
# apt install jq
# jq '.linux.seccomp.syscalls[].names' < config.json | less
[
"accept",
"accept4",
"access",
"adjtimex",
"alarm",
"bind",
"brk",
"capget",
"capset",
"chdir",
"chmod",
...中略...
"clock_nanosleep_time64",
"close",
"close_range",
"connect",
...中略...
docker/dockerd/containerdはclose_rangeをruncのlibssecompに許可をおねがいしているではありませんか。そうするとdocker/dockerd/containerdは問題なさそうです。では最後のlibseccompがclose_rangeに対応できているか?を調べるしかありません。ここでは、runcがgo言語なので、簡単なgo言語のプログラムを叩いてlibseccompがcontainerdの指定するseccompの許可リストをきちんと許可できるか?を調べます。
$ mkdir ~/work/
$ cd ~/work
$ cat > seccomp-validate.go
package main
import (
"fmt"
"os"
libseccomp "github.com/seccomp/libseccomp-golang"
"flag"
"io/ioutil"
"encoding/json"
)
func main() {
flag.Parse()
if flag.NArg() <1 {
panic("Usage: seccomp-validate config.json")
}
bufRawJson,err := ioutil.ReadFile(flag.Arg(0))
var parsedJson interface{}
err = json.Unmarshal(bufRawJson, &parsedJson)
if err != nil {
panic(err)
}
// try parsing
sysCalls := parsedJson.(map[string]interface{})["linux"].
(map[string]interface{})["seccomp"].
(map[string]interface{})["syscalls"].
([]interface{})
for _,syscallBlk := range sysCalls {
for _,syscallName := range syscallBlk.
(map[string]interface{})["names"].
([]interface{}) {
syscallNameStr := syscallName.(string)
_,err := libseccomp.GetSyscallFromName(syscallNameStr)
if err != nil {
fmt.Printf("%s is not supported\n",syscallNameStr)
}
}
}
os.Exit(0)
}
<CTRL+Dを押す>
$ go mod init main
$ go get github.com/seccomp/libseccomp-golang
$ go build seccomp-validate.go
$ sudo -s -u root -H
# cd /run/containerd/io.containerd.runtime.v2.task/moby/f33ac998279a*/
# /home/yours/work/seccomp-validate ./config.json
close_range is not supported
epoll_pwait2 is not supported
なんということでしょう。WSL2+ubuntu 20.04では、kernelはclose_rangeシステムコールを対応しているのにもかかわらず、libseccomp側がサポートしていません。どうもこれが今回の原因のようです。
今回runcがやっている方法にできるだけ近い環境を作り出してconfig.jsonをチェックしたかったので、わざわざgo言語でサポートチェッカーをささっと作りましたが、簡単に特定のシステムコールをサポートしているか?だけを調べるなら、seccompパッケージ梱包のツールを入れるだけで確認できます。
$ sudo apt install seccomp
$ scmp_sys_resolver 3
close #<- system call番号3はcloseであることがわかる。サポートしている。
$ scmp_sys_resolver 436
UNKNOWN #<- システムのlibseccompでサポートしてないとUNKNOWNと出る。
libseccompに差分を取り込んで直す
大詰めです。ubuntu 20.04のlibseccompを治さないといけません。
$ dpkg -l libseccomp2
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=================-======================-============-============================================
ii libseccomp2:amd64 2.5.1-1ubuntu1~20.04.2 amd64 high level interface to Linux seccomp filter
ですので、upstreamのlibseccompのバージョンは2.5.1です。なので、githubの機能つかって即席のpatchをあててclose_rangeシステムコールをマージしてしまいます。例によってdebian/changelogはdch -iで編集が要るのですが、長いので出来たものを見せることとします。debian/patches側は今回外部のpatch取り込みになるので、quiltは使わず直接作るという方針にします。
また、v2.5.1~close_rangeサポート(commit:ac849e7960547d418009a783da654d5917dbfe2d.patch) までの差分のうち、ubuntuのソースに含まれないCI用のファイルがあるのでそのファイルの変更をスキップさせる形で差分を取り込みます。
$ apt-get source libseccomp2
$ cd libseccomp-2.5.1/
$ quilt pop -a #<- 適用されたubuntu側patchをいったん外す。
$ cd libseccomp-2.5.1/debian
$ head -n 10 changelog
libseccomp (2.5.1-1ubuntu1~20.04.2oreore1) UNRELEASED; urgency=medium
* accept close_range system call.
-- <yours@mail.address> Wed, 16 Mar 2022 21:28:08 +0900
libseccomp (2.5.1-1ubuntu1~20.04.2) focal-security; urgency=medium
* No change rebuild in the -security pocket.
$ cd patches
$ wget -O prepared_to_add_close_range.patch https://github.com/seccomp/libseccomp/compare/v2.5.1...c56a00fe173a7dd5a8326431ae28863ce432bbc1.patch
$ wget -O add_close_range.patch https://github.com/seccomp/libseccomp/commit/ac849e7960547d418009a783da654d5917dbfe2d.patch
$ cat >> series <<__HERE
prepared_to_add_close_range.patch
add_close_range.patch
__HERE
$ cd ../../
$ dpkg-buildpackage -uc -us | tee -a ../build.log
$ cd ..
$ sudo dpkg -i ./libseccomp2_2.5.1-1ubuntu1~20.04.2oreore1_amd64.deb
それではうまく動作しているか?を確認してみましょう。
$ sudo -s -u root -H
# cd /run/containerd/io.containerd.runtime.v2.task/moby/f33ac998279a*/
# /home/yours/work/seccomp-validate ./config.json
おお、何もエラーが出なくなりました!scmp_sys_resolverはどうなっているでしょう?
$ scmp_sys_resolver 436
close_range
いきなりサポートされましたw。
dockerも治ったよ!
早速稼働してみます。
$ docker run --rm -d -e VNCPASS="hogefuga" -e RESOLUTION="1920x1200" -p :5901:5901 debian-sid-gui:latest
...vncでxfce4-terminalを動かすと無事動く
$
ついに、--security-opt="seccomp=unconfined"
をつけなくても無事動くようになりました。
さいごに
今回は、dockerで何か動かそうとしたらseccompに阻まれて困ったという話です。また、将来同じような問題に遭遇した時にほいほいデバッグができるようになるための方法も記載してみました。
もしdockerで謎の挙動になったり動かないーというというコンテナを持つ人がいたら、本件にハマっているだけかもしれません。本ブログの方法をおしえてあげましょう! それでは楽しいコンテナライフを!