スクエニ ITエンジニア ブログ

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が起動した様子

xfce4-terminalでbashの起動に失敗するぞ!?

なんだ楽勝じゃんって思ったそこのあなた!序盤はほのぼの・ゆるゆる系で大安心、でも早速修羅場に叩き込むのはアニメも漫画もお約束です!

基本のxfce4-terminalを立ちあげてみましょう!

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が正常に動作した様子

何の問題もなく立ち上がりました。xfce4-terminalもbashも動いてヨカッタヨカッタ!

seccompの調査を開始

今回は簡単にGUIを用意するお話をしました!問題もググったら一発解決!次回もサービス、サービスう!とは弊社ではならないところがお約束です。

なぜ動かないのか?を調べないとこのブログは終わりません。これが弊社サービスだったりすると、seccompを外したままでいいのか?という各方面からのツッコミにも答えないといけない時がきちゃいます2

 先ほどつけた--security-opt="seccomp=unconfined"は、dockerにlinux kernelの機能であるseccompを利用しないで欲しいと指定するものです。少なくともseccompが何かをおかしくするわけです。google検索して見つかったissueにはclose_rangeシステムコールがおかしくなるようなことが示唆されています。

seccompのはたらきについてlibseccompを利用した前提で図示すると図の通りです。

seccompの動作

つまりは、ユーザプロセスが何かシステムコールを発行しようとするとブロックされたりするわけです。じゃあ、今回何がブロックされたの?ということを知らないと調査も対策も打てません。

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がないのでこんなことになってます。ちなみにこれがどんな問題を引き起こすかというと…

  1. auditのログのsystem callが番号でしかkernelもログに残せないw あくまでkernelが知っているのはsystem call番号に対する処理への関数のアドレスだけ(sys_call_table[]というkernel内部変数が対応表としてあるだけです)
  2. 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で謎の挙動になったり動かないーというというコンテナを持つ人がいたら、本件にハマっているだけかもしれません。本ブログの方法をおしえてあげましょう! それでは楽しいコンテナライフを!


  1. WSL2用のubuntu 22.04ではクリーンインストールの場合、最初からsystemdが稼働するようになったと聞いたので、手動でsystemdを立ち上げる必要はもう無いかもしれません。 ↩︎

  2. 弊社ではこういった事態に直面して本気で困ると、あらゆる方面から救いの手が伸びてきますのでご安心ください!一人悶々と放置されるということはありません(断言)弊社はサステナブル!ピュアホワイトな職場です!ご安心ください! ↩︎

  3. Windows10+WSL2+ubuntu 20.04はそのままではauditdは動かないので(ズギャーン!)、動かす方法はこのブログ記事を参照下さい。 ↩︎

この記事を書いた人

SQUARE ENIXでは一緒に働く仲間を募集しています!
当社に興味がある方は是非下記の採用情報ページをご覧下さい!