mirakc / mirakc

A Mirakurun-compatible PVR backend written in Rust
https://mirakc.github.io/dekiru-mirakc/
Apache License 2.0
210 stars 17 forks source link

mirakc-timeshift-fsのファイルが、実行したユーザーしかアクセスできない。-o allow_otherも効果がない #680

Closed vroad closed 1 year ago

vroad commented 1 year ago

できるmirakcではDocker上でmirakc-timeshift-fsを動かしていますが Docker上でなくても正常に動くでしょうか? 私の環境ではNixOSのsystemdで動かしていますが、systemd unitのユーザーがrootだとroot以外ではアクセス不可能になります。マウントしたディレクトリの親ディレクトリでlsすらできません。 mirakc-timeshift-fsに -o allow_otherをつけて実行しても同じでした。

ls: cannot access 'mirakc-timeshift-fs-src': Permission denied

systemd unitを一般ユーザーで動かすとそのユーザーはファイルを見れますが、root含む他ユーザーはファイルを見れないようです。 /etc/fuse.confuser_allow_other を追加の上、mirakc-timeshift-fsに -o allow_otherをつけて実行しても同じです。

systemd unit内では明示的にパスを通さないと動かないコマンドが多く、一般ユーザーで動かすのには手間がかかりました。結局、他ユーザーはファイルを参照できなかったですが。

一般ユーザーでの動作にはPATHにfusermountが必要でした。ないと、Error: IoError(Os { code: 2, kind: NotFound, message: "No such file or directory" } のエラーが出ます。(何が見つからなかったのかはログに出ない) さらに、setuidを設定したバイナリでないと一般ユーザーでfusermount動かないらしく (Error: IoError(Custom { kind: Other, error: "fusermount: mount failed: Operation not permitted\n" })のエラーが起きる)、NixOSではsetuidが設定されたfusermountのラッパーが/run/wrappers/binに存在するのでそちらにパスを通すようにしました。

rootユーザーは何故かfusermountがPATHに無くても動きます。

今のところはbindfsを -u username -g groupname オプション付きで起動して、ユーザー、グループを変更した同じディレクトリを別の場所に作って問題を回避していますが、 bindfs(またはDocker)を使わずに動かす方法はありますか?

masnagam commented 1 year ago

報告ありがとうございます.

基本的にdockerを使わない場合の動作確認はしていません.私自身がdocker環境しか実際に使っていないため,それ以外の環境で動作確認する必要性がないためです.

これは私個人の話であり,mirakc自体をdocker以外で使用することを阻害するものではありません.ただ,問題が出た場合には自力で解決してもらう必要があります.

問題を解決したら,PRを送っていただければ(余程のことがない限り)基本マージします.これはドキュメントについても同じです.

議論することを拒否しているわけではありません.自身が困っていることは,多くの場合他の人も困ることが多いと考えています.

fuseのマウントオプションについては,少し確認に時間が必要です.fuserというcrateを使っているのですが,これは私が書いたものではないため,どういう動作だったのかすぐには思い出せないためです.fusermountの動作についても,おそらくfuserの実装に依存するものと思われます.

masnagam commented 1 year ago

-o allow_otherが動作しないのは,mirakc-timeshift-fsのオプション処理に問題があるからかもしれません.

現実装では,すべてfuser::MountOption::CUSTOMとして追加しているのですが,

cberner/fuserでは

parse_options_from_args()を使っています.また,allow_otherに対応するMountOption::AllowOtherというenumがあります.

parse_options_from_args()&[&OsStr]を処理するようなので,この関数を使うならOpt::optionsの型を変更したほうが良さそうな気がしますね.

masnagam commented 1 year ago

rootユーザーは何故かfusermountがPATHに無くても動きます。

この辺の実装を見れば,理解できそうな気がします. https://github.com/cberner/fuser/tree/master/src/mnt

vroad commented 1 year ago

さっき MountOption::AllowOther を追加して試してみたら実行ユーザー以外もアクセスできるようになったので、allow_otherが効かないのは 全てCUSTOMオプションとして渡しているせいかと思います。

https://github.com/vroad/mirakc/commit/aab6775ce7283ff3bd1f8b2b152a9cfd294c22d7

masnagam commented 1 year ago

parse_options_from_args()を使えば解決ですが,これ外から呼べないですね..pub(crate)になっていますね..

mirakc-timeshift-fsfuser::mount2()を呼び出していますが,fuser::mount()を呼び出すようにしないといけないですね.この場合,fuser::MountOption::FSNameなども文字列化して渡す必要がありますね.

masnagam commented 1 year ago

-o allow_otherが動けば,なんとかなりそうですか?

masnagam commented 1 year ago

確かリンク時の問題を回避するために,libfuseを使わないようにしました. https://github.com/mirakc/mirakc/commit/7f9d58085a8e78c34e247109a1eaf9824f36c12c

なので,fusermount (or fusermount3)を常に利用するようになっていた気がします.

この場合 https://github.com/cberner/fuser/blob/master/src/mnt/fuse_pure.rs の実装に入りますが,detect_fusermount_bin()でコマンドを探しています.

rootユーザーは何故かfusermountがPATHに無くても動きます

多分これが原因ではないかと思います.この関数は一般ユーザーでも同様に呼び出されるので,rootでコマンドが見つかっているなら一般ユーザーでも見つかっているはず.

mirakc/timeshift-fsイメージではfuser3をインストールしています.

vroad commented 1 year ago

-o allow_otherが動けば,なんとかなりそうですか?

これはなんとかなりそうです。 uidやgidを設定していないからか、 一般ユーザーでmirakc-timeshift-fsを起動してもファイルシステム内のファイルのユーザーとグループがrootになるのはちょっと変に見えますが、 ファイルへのアクセスがbindfsなしで出来るようにするのは達成できて、今の所は実用上問題なさそうです。

多分これが原因ではないかと思います.この関数は一般ユーザーでも同様に呼び出されるので,rootでコマンドが見つかっているなら一般ユーザーでも見つかっているはず.

これはどういう意味でしょうか? 一般ユーザーの場合しかfusemountコマンドの検索はしてないんじゃないかと思います。rootユーザーの場合、bash上で export PATH= して手動実行しても動きます。

PATHからだけでなく、 /bin/fusemount/bin/fusemount3 も探すようですが NixOSはこの場所にはコマンドが置かれていないですね。

https://github.com/cberner/fuser/issues/126 に、Linux上でrootでfuseを使う場合はlibfuseは不要と書かれているので Linuxでrootの場合は実行のされ方が変わるのではないかと思います。

masnagam commented 1 year ago

NixOSはこの場所にはコマンドが置かれていないですね

確かに,/bin/に置かれていることは稀みたいですね.普通は/usr/bin/ですか.

Linuxでrootの場合は実行のされ方が変わるのではないかと思います

直接開くパスもあるみたいですね. https://github.com/cberner/fuser/blob/6b76fd1f9cc8caef0ffa057f3e0879c940c9aab8/src/mnt/fuse_pure.rs#L316

masnagam commented 1 year ago

uidやgidを設定していないからか

即値で0を指定していますね. https://github.com/mirakc/mirakc/blob/main/mirakc-timeshift-fs/src/filesystem.rs#L238

mirakc-timeshift-fsを実行しているユーザーのuid/gidを設定したほうが良さそうですね.

masnagam commented 1 year ago

今までの内容をまとめると..

追加があればお願いします

masnagam commented 1 year ago

追加

vroad commented 1 year ago
  • uid/gidをmirakc-timeshift-fsを実行したユーザーのuid/gid (or euid/egid? このあたりはfusermountなど既存実装を調べて決める)

goofysはファイルのユーザー・グループの初期値が実行ユーザーのuid、gidですね。こちらがデフォルトでも良いかと思います。 https://github.com/kahing/goofys/blob/5661a83f953a6a2352b13e782fbcf99e92089d3a/internal/perms.go#L25 s3fs-fuseは初期値はrootでした。

mirakc-timeshift-fsの実行ファイル自体にsetuidビットを設定しなければeuid/egidは同じではないでしょうか? fusermountにはsetuidビットは必要ですが、 mirakc-timeshift-fs自体は通常rootしかアクセスできないファイルを扱う必要があるわけではないので、setuidビットは使われず、EUID/EGIDは同じになるかと思います。

↓のsetuid設定してない場合の動作と同じになります https://mudongliang.github.io/2020/09/17/ruid-euid-suid-usage-in-linux.html

$ ./test
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied

ドキュメントに書いたほうがよい

  • fusermount (or fusermount3)が必要

エラー内容(Error: IoError(Os { code: 2, kind: NotFound, message: "No such file or directory" })も書いたほうが良いと思います。fuser側の問題かと思いますが、このエラーメッセージでは何が見つからないか分かりにくいです。

masnagam commented 1 year ago

mirakc-timeshift-fsの実行ファイル自体にsetuidビットを設定しなければeuid/egidは同じではないでしょうか?

確かにmirakc-timeshift-fsにsetuidビットを設定するわけではないですね.

fuser側の問題かと思いますが、このエラーメッセージでは何が見つからないか分かりにくいです。

了解です.これを表示しているのはmirakc-timeshift-fsなので,可能ならメッセージを書き換えることにします.

masnagam commented 1 year ago

以下,対応済み

chunk-sizeの既定値の変更も別途行う

masnagam commented 1 year ago

@vroad 対応内容に不足がなければ,クローズしてください.関連する別問題があるなら,クローズ後に再オープンしても問題ありません.

masnagam commented 1 year ago

chnun-size変更. 875ec95b0e95ff235d6e4a85f505d367f71fc33a

vroad commented 1 year ago

timeshift-fsの修正内容は問題ないと思います。

ドキュメントの言い回しは少し変えても良いかと思いますが、このissueのタイトルで示した問題は解決したので 別のissueにしようかと思います。 ありがとうございました。

masnagam commented 1 year ago

ドキュメントのPRも受け付けているので,直接修正してPRを送ってくれるとありがたいです.