WSL+qemu-arm で chroot に失敗するときの対処方法

# はじめに

筆者は FPGA-SoC-Linux で ZYNQ および CycloneV SoC に対応した Debian9 rootfs を提供しています。今までは VMware に Ubuntu を載せて Debian9 rootfs をビルドしていましたが、今回 WSL(Ubunts) でビルドを試してみました。ホストマシンが x86_64 の場合、arm アーキテクチャの Debian9 rootfs をビルドするためには qemu-arm を使って chroot する必要があります。この記事では、その際でくわしたトラブルとその対処方法を説明します。

注) ただし、現時点では WSL による Debian9 rootfs のビルドは成功していません。

# failed to run command ‘/bin/bash’: Exec format error

## 症状

まず最初にでくわしたトラブル。

```console
user@host:work$ sudo chroot debian9-rootfs
chroot: failed to run command ‘/bin/bash’: Exec format error
```

## 原因

update-binfmts コマンドで qemu-arm の状態をみてみると、disable になっていました。WSL(Ubuntu) に binfmt-support をインストールした直後は disable になっているようです。

```console
user@host:work$ sudo update-binfmts --display qemu-arm
qemu-arm (disabled):
     package = qemu-user-static
        type = magic
      offset = 0
       magic = \x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
        mask = \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
 interpreter = /usr/bin/qemu-arm-static
    detector =
```

## 対処方法

update-binfmts コマンドで qemu-arm を enable にします。

```console
user@host:work$ sudo update-binfmts --enable qemu-arm
user@host:work$ sudo update-binfmts --display qemu-arm
qemu-arm (enabled):
     package = qemu-user-static
        type = magic
      offset = 0
       magic = \x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
        mask = \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
 interpreter = /usr/bin/qemu-arm-static
    detector =
```

# prepare_binprm: Bad file descriptor

## 症状

qemu-arm を enable にして再度 chroot を試みたら、次のようなエラーにでくわしました。

```console
user@host:work$ sudo chroot debian9-rootfs
prepare_binprm: Bad file descriptor
```

## 原因

Google で検索してみると、次のようなページがみつかりました。

* https://github.com/Microsoft/WSL/issues/2620

この対処方法をやってみました。

## 対処方法

まずは qemu-user-static パッケージに登録されている interpreter を取り除きます。

```console
user@host:work$ sudo update-binfmts --package qemu-user-static --remove qemu-arm /usr/bin/qemu-arm-static
```

次に特別なオプション無しに元に戻します。

```console
user@host:work$ sudo update-binfmts --install qemu-arm /usr/bin/qemu-arm-static \
  --magic '\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00' \
  --mask  '\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
```

すると次のようになります。

```console
user@host:work$ sudo update-binfmts --display qemu-arm
qemu-arm (enabled):
     package = <local>
        type = magic
      offset = 0
       magic = \x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00
        mask = \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff
 interpreter = /usr/bin/qemu-arm-static
    detector = 
```

```console
user@host:work$ sudo chroot debian9-rootfs
root@host:/#
```

成功しました。


## 注意

この方法で update-binfmts の設定を変更したままだと、update-binfmts のアンインストールや再インストールに失敗します。使用後は元に戻しておいた方が良いでしょう。

```console
user@host:work$ sudo update-binfmts --remove qemu-arm /usr/bin/qemu-arm-static
user@host:work$ sudo update-binfmts --package qemu-user-static \
  --install qemu-arm /usr/bin/qemu-arm-static \
  --magic '\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00' \
  --mask  '\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
```