proot-me / proot

chroot, mount --bind, and binfmt_misc without privilege/setup for Linux
https://proot-me.github.io
GNU General Public License v2.0
1.96k stars 369 forks source link

deno panic #363

Open sigmaSd opened 1 year ago

sigmaSd commented 1 year ago

Expected Behavior

deno works with no error on x86_64 linux via proot

Actual Behavior

deno panics inside tokio

Steps to Reproduce the Problem

  1. proot-distro install debian
  2. proot-distro login debian
  3. curl -fsSL https://deno.land/x/install/install.sh | sh
  4. .deno/bin/deno

Specifications

Command Output

Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.

Platform: linux x86_64
Version: 1.35.3
Args: [".deno/bin/deno"]

thread '<unnamed>' panicked at 'unexpected error when polling the I/O driver: Os { code: 38, kind: Unsupported, message: "Function not implemented" }', /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.28.1/src/runtime/io/mod.rs:180:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I'm assuming that there is a syscall that tokio is using that it isn't handled, strace doesn't show anything suspicious

The motivation is I want to use deno on termux on waydroid, the easiest way seemed to use proot

sigmaSd commented 1 year ago

it boils down to mio trying to use an unspported syscall, here is a minimum reproduction

main.rs

use mio::{Events, Poll};
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut poll = Poll::new()?;
    let mut events = Events::with_capacity(1024);
    poll.poll(&mut events, None)?;
    Ok(())
}

Cargo.toml

[package]
name = "lab"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mio = { version = "0.8.8", features = ["os-poll"] }

[profile.release]
strip = true

panics with Function not implemented when run inside x86_64 proot

oxr463 commented 1 year ago

Wow, thank you for the reproduction code.

sigmaSd commented 1 year ago

I debugged a bit and it seems like epoll_wait implementation is the problem, it shows up like this in strace

epoll_wait(3, [{events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, {events=0, data={u32=0, u64=0}}, ...], 1024, -1) = 232

which seems very suspicious it seems like its receiving events instead of a pointer to events

sigmaSd commented 1 year ago

Actually I'm not sure about my epoll_wait assumption maybe its just how strace formatting.

But I did follow the code with gdb and that seems the last syscall it uses in mio

sigmaSd commented 1 year ago

turns out its indeed epoll_wait that's failing https://github.com/tokio-rs/mio/blob/2856112500284f83dcdfa6de20dda2516caa59fb/src/sys/unix/selector/epoll.rs#L97

If I change that to use epoll_pwait instead the minimal example does work

sigmaSd commented 1 year ago

I tried to reproduce with a simple c program

#include <sys/epoll.h>

int main() {
    int epoll_fd = epoll_create1(0);                                                                                                                                         
    struct   epoll_event events[10];                                                                                                                                                
    epoll_wait(epoll_fd, events, 10, -1);        
}

but this works and strace shows its making a call to epoll_pwait instead epoll_wait

So it seems like proot make this translation somewhere ? not sure why the same thing doesn't happen with rust

sigmaSd commented 1 year ago

somehow this bug doesn't happen on proot aarch64 , deno seems to work there https://github.com/denoland/deno/issues/4862#issuecomment-1049502951

sigmaSd commented 1 year ago

I'm using termux on waydroid to test, it just occured to me that maybe its waydroid (or the image it uses) issue

Or a waydroid/proot interaction, compiling the minimal example does work on waydroid termux without proot (compiled to android-x86-64)

sigmaSd commented 1 year ago

I tried with a different x86-64 android emulator (https://appetize.io) and it errors the same way

sigmaSd commented 1 year ago

Using deno with patched mio that uses pwait indeed works correctly