virtio-fs (Linux passthrough): debug log in do_lookup panics the fs worker on non-UTF-8 file names

クローズ 初心者向け
#919 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 4 日以内に返信

関連するプルリクエストがすでにマージされています。

  • #920 @zcl-g5 による — マージ済み

評価

難易度
1/5
見積もり時間
1時間未満
初心者へのやさしさ
85/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
rust
領域
backend

調査の方向性

パニックを起こしている呼び出しは、src/devices/src/virtio/fs/linux/passthrough.rs の do_lookup 内の debug!(main ブランチの 1009 行目)です。その直前の lookup() 内の debug! は、すでに CStr を安全にフォーマットしています。name.to_str().unwrap() を lossy 形式または Debug 形式のフォーマットに置き換えたうえで、debug レベルで非 UTF-8 の名前を lookup しても src/devices/src/virtio/fs/worker.rs の fs ワーカーがパニックしないことを確認してください。0xff を含む名前を Debug レベルで lookup するユニットテストが通れば完了です。

索引モデルが issue の本文から書いたものです。

説明

Summary

In the Linux virtio-fs passthrough, do_lookup logs the looked-up name with name.to_str().unwrap() inside a debug! statement. File names are arbitrary bytes on Linux, so whenever the log level allows debug, the first lookup of a name that is not valid UTF-8 panics the fs worker thread. That thread is never restarted, so the virtio-fs device stops answering: every guest process that touches the share afterwards blocks forever (uninterruptible sleep), and nothing inside the guest can recover.

  • v1.18.1 (b7e43f04): src/devices/src/virtio/fs/linux/passthrough.rs:602
    debug!("do_lookup: {}, inode: {:?}", name.to_str().unwrap(), inode);
    
  • main today, same file, line 1009:
    debug!("lookup: {}, inode: {:?}", name.to_str().unwrap(), inode);
    

The debug!("do_lookup: {name:?}") a few lines earlier in lookup() is fine (it formats the CStr with Debug); only the line above assumes UTF-8.

How the log level gets there

Anything that raises the log max level to debug triggers it, because the macro evaluates its arguments before the per-target filter runs:

  • krun_set_log_level(0) builds its logger with env_logger::Builder::from_env(...), so a RUST_LOG=debug (or any directive at debug/trace, even for an unrelated target) in the embedding process's environment overrides the requested level;
  • krun_init_log(..., level = 4 or 5, ...) requests it explicitly.
Reproduction
  1. Start a VM with a virtio-fs share (the root filesystem is enough) with the VMM's log level at debug, e.g. RUST_LOG=debug in the environment of a process that calls krun_set_log_level.
  2. In the guest: touch "/share/x$(printf '\377')" (or mkdir, or a git checkout of a repository that contains such a path; test suites also create them).
  3. Host stderr:
    thread 'fs worker' (2667) panicked at src/devices/src/virtio/fs/linux/passthrough.rs:602:60:
    called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 9, error_len: Some(1) }
    
    The file has already been created on the host (the panic happens while building the reply), the guest's touch never returns, and every later operation on that share hangs. The VMM process keeps running with the other devices.

Observed with libkrun 1.18.1 on Linux hosts (KVM, x86_64 and aarch64 guests) with the share served from an XFS directory; the macOS passthrough is not affected because its name_to_path already produces a lossy path.

Fix

Format the name without assuming UTF-8:

debug!("do_lookup: {}, inode: {:?}", name.to_string_lossy(), inode);

(or {:?} on the CStr). We carry exactly this one-line change as a downstream source patch together with a unit test that looks up cache-\xff with log::set_max_level(LevelFilter::Debug) and fails on the current line; happy to send it as a PR if that helps.

Related robustness note

A panic in the fs worker thread currently leaves the device silently dead (the thread is spawned once in src/devices/src/virtio/fs/worker.rs with no supervision), which is what turns a logging bug into a hung guest. Converting a per-request panic into an EIO reply, or aborting the VMM, would make any future bug of this kind visible instead of a permanent hang. That is a separate change; this issue is about the unwrap().

主要言語
Rust
スター
2.8k
フォーク
279
平均マージ
5日 18時間
マージ済み PR(30日)
29

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

libkrun/libkrun のほかの issue

libkrun/libkrun の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。