WSL2 でパーミッション変更できるかやってみた

# はじめに

以下の設定を `/etc/wsl.conf` に追加して再起動すると、WSL2 から Windows 内のファイルに対してパーミッションの変更ができるようになるそうです。これを試していきましょう。

```conf:/etc/wsl.conf
[automount]
options="metadata,umask=22,fmask=11"
```

https://qiita.com/cabbage_lettuce/items/acecfaf270b564d8c5aa

# TL;DR（この記事の要約）

なお、結論としては上記の通り `/etc/wsl.conf` に `options="metadata,umask=22,fmask=11"` という設定を入れるのが良いようでした。そのような結論に至った理由を以下に記します。

# 環境
環境は Windows11 / WSL2 Ubuntu 22.04.01

# 今回使用するスクリプト

各環境で以下のスクリプトを実行しました。`chmod XXX` を行い、結果がどのようになるか `ls -alh` で確認します。

```bash:chmod_test.sh
#!/bin/bash

rm -rf wsl_chmod_test/
mkdir -p wsl_chmod_test/
cd wsl_chmod_test/

touch "touch.txt"

for i in 001 002 004 010 020 040 100 200 400; do
  touch $i.txt
  chmod $i $i.txt
done

for i in 0 7; do
  for j in 0 7; do
    for k in 0 7; do
      touch $i$j$k.txt
      chmod $i$j$k $i$j$k.txt
    done
  done
done

# chmod の結果を確認
ls -alh .
```

# Linux から Linux ファイルシステムに対して実行

- 実行元：Linux (WSL2 Ubuntu 22.04)
- ファイルシステム：ext4

```bash
$ ./chmod_test.sh 
total 8.0K
drwxr-xr-x 2 yuinore yuinore 4.0K Feb 12 00:57 .
drwxr-xr-x 3 yuinore yuinore 4.0K Feb 12 00:57 ..
---------- 1 yuinore yuinore    0 Feb 12 00:57 000.txt
---------x 1 yuinore yuinore    0 Feb 12 00:57 001.txt
--------w- 1 yuinore yuinore    0 Feb 12 00:57 002.txt
-------r-- 1 yuinore yuinore    0 Feb 12 00:57 004.txt
-------rwx 1 yuinore yuinore    0 Feb 12 00:57 007.txt
------x--- 1 yuinore yuinore    0 Feb 12 00:57 010.txt
-----w---- 1 yuinore yuinore    0 Feb 12 00:57 020.txt
----r----- 1 yuinore yuinore    0 Feb 12 00:57 040.txt
----rwx--- 1 yuinore yuinore    0 Feb 12 00:57 070.txt
----rwxrwx 1 yuinore yuinore    0 Feb 12 00:57 077.txt
---x------ 1 yuinore yuinore    0 Feb 12 00:57 100.txt
--w------- 1 yuinore yuinore    0 Feb 12 00:57 200.txt
-r-------- 1 yuinore yuinore    0 Feb 12 00:57 400.txt
-rwx------ 1 yuinore yuinore    0 Feb 12 00:57 700.txt
-rwx---rwx 1 yuinore yuinore    0 Feb 12 00:57 707.txt
-rwxrwx--- 1 yuinore yuinore    0 Feb 12 00:57 770.txt
-rwxrwxrwx 1 yuinore yuinore    0 Feb 12 00:57 777.txt
-rw-r--r-- 1 yuinore yuinore    0 Feb 12 00:57 touch.txt
```
当然パーミッションの変更は反映されますよね。

# Linux から Windows に対して実行（初期状態）

ここからが本題です。

- 実行元：Linux (WSL2 Ubuntu 22.04)
- 実行先：Windows ファイルシステム
- ファイルシステム：DrvFs (NTFS)
- wsl.conf：**metadata設定なし**

```bash
$ ./chmod_test.sh 
total 0
drwxrwxrwx 1 yuinore yuinore 512 Feb 12  2023 .
drwxrwxrwx 1 yuinore yuinore 512 Feb 12  2023 ..
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 000.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 001.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 002.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 004.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 007.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 010.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 020.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 040.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 070.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 077.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 100.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 200.txt
-r-xr-xr-x 1 yuinore yuinore   0 Feb 12  2023 400.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 700.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 707.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 770.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 777.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12  2023 touch.txt
```

パーミッションがほとんど何も変更されていません。これでは困りますね。

# Linux から Windows に対して実行（metadata あり）

- 実行元：Linux (WSL2 Ubuntu 22.04)
- 実行先：Windows ファイルシステム
- ファイルシステム：DrvFs (NTFS)
- wsl.conf：**metadata設定あり** (`"metadata,umask=22,fmask=11"`)

```bash
$ ./chmod_test.sh 
total 0
drwxr-xr-x 1 yuinore yuinore 512 Feb 12 01:02 .
drwxr-xr-x 1 yuinore yuinore 512 Feb 12 01:02 ..
---------- 1 yuinore yuinore   0 Feb 12 01:02 000.txt
---------x 1 yuinore yuinore   0 Feb 12 01:02 001.txt
--------w- 1 yuinore yuinore   0 Feb 12 01:02 002.txt
-------r-- 1 yuinore yuinore   0 Feb 12 01:02 004.txt
-------rwx 1 yuinore yuinore   0 Feb 12 01:02 007.txt
------x--- 1 yuinore yuinore   0 Feb 12 01:02 010.txt
-----w---- 1 yuinore yuinore   0 Feb 12 01:02 020.txt
----r----- 1 yuinore yuinore   0 Feb 12 01:02 040.txt
----rwx--- 1 yuinore yuinore   0 Feb 12 01:02 070.txt
----rwxrwx 1 yuinore yuinore   0 Feb 12 01:02 077.txt
---x------ 1 yuinore yuinore   0 Feb 12 01:02 100.txt
--w------- 1 yuinore yuinore   0 Feb 12 01:02 200.txt
-r-------- 1 yuinore yuinore   0 Feb 12 01:02 400.txt
-rwx------ 1 yuinore yuinore   0 Feb 12 01:02 700.txt
-rwx---rwx 1 yuinore yuinore   0 Feb 12 01:02 707.txt
-rwxrwx--- 1 yuinore yuinore   0 Feb 12 01:02 770.txt
-rwxrwxrwx 1 yuinore yuinore   0 Feb 12 01:02 777.txt
-rw-r--r-- 1 yuinore yuinore   0 Feb 12 01:02 touch.txt
```

正しくパーミッションの変更が適用されていることがわかります。また、touch で作成したファイルや mkdir で作成したディレクトリのパーミッションも最初の例と一致しています。これで git も安心して使えますね！

# 解説

Linux にはパーミッションという仕組みがあり、ファイルごとにアクセス許可を設定することができます。しかし、Windows で使用されているファイルシステムにはこの仕組みがありません。

> WSL のファイルのアクセス許可 | Microsoft Learn
> https://learn.microsoft.com/ja-jp/windows/wsl/file-permissions

ですが、上記のように WSL 側から `$LXMOD` などの NTFS 拡張属性をファイルに追加することで、`/mnt/c/` 以下のファイルでも Linux のパーミッション情報が記録できるようになるみたいです。

また、Linux では新規ファイル・新規ディレクトリは umask の値に従ってパーミッションが設定されます。umask の値は umask コマンドで確認できます。たとえば自分が使っている Ubuntu Server では以下のようになります。

```bash
$ umask
0002
```

新規ファイルであれば `0666 & ~umask` が、新規ディレクトリであれば `0777 & ~umask` がパーミッションとして設定されるようです。

```bash
$ touch newfile
$ mkdir newdir
$ ls -alh -d newfile newdir
drwxrwxr-x 2 yuinore yuinore 4.0K Feb 14 14:24 newdir
-rw-rw-r-- 1 yuinore yuinore    0 Feb 14 14:24 newfile
```

ただ、Linux 内でファイルを新規作成した場合は wsl.conf で設定した `umask=22,fmask=11` の設定が影響せず、Linux 内の umask 値が優先されるようです。Windows で作成した新規ファイルであれば `0777 & ~(umask | fmask)` が、Windows で作成した新規ディレクトリであれば `0777 & ~(umask | dmask)` がパーミッションとして設定される感じです。

```bash
$ umask 000
$ touch newfile
$ mkdir newdir
$ ls -alh
total 8.0K
drwxrwxrwx 1 yuinore yuinore  512 Feb 14 14:53  .
drwxr-xr-x 1 yuinore yuinore  512 Feb 14 14:51  ..
drwxrwxrwx 1 yuinore yuinore  512 Feb 14 14:53  newdir
-rw-rw-rw- 1 yuinore yuinore    0 Feb 14 14:53  newfile
drwxr-xr-x 1 yuinore yuinore  512 Feb 14 14:53  新しいフォルダー
-rwxr--r-- 1 yuinore yuinore 6.5K Feb 14 14:52 '新規 Microsoft Excel ワークシート.xlsx'
```

ファイルに実行権限はデフォルトでは必要ないので、`fmask=111` でも良いような気がしましたが、そのように設定すると、`/mnt/c/Windows/System32/` 以下の .exe ファイル（PowerShell.exe など）に実行権限が付与されず、`yarn start` などがエラーになってしまうことがあるので、最初に示したような設定になっているのかもしれません。

> drvfs fmask=111 breaks (e.g.) cmd.exe without workarounds? · Issue #3267 · microsoft/WSL · GitHub
> https://github.com/microsoft/WSL/issues/3267

Windows で作成したファイルを git にコミットする際は（不必要な実行権限がファイルに付与されないように）注意が必要かもしれませんね。