turbolent / w2c2

Translates WebAssembly modules to portable C
MIT License
709 stars 37 forks source link

call_indirect not sandboxed properly #76

Open zyedidia opened 1 year ago

zyedidia commented 1 year ago

I noticed that the translation of call_indirect has no dynamic checking needed to enforce sandboxing. For example, this program causes a segmentation fault:

(module
    (memory (;0;) 2)
    (export "memory" (memory 0))
    (type $fntype (func (result i32)))
    (table 32 funcref)
    (func (export "_start") (type $fntype)
        (call_indirect (type $fntype) (i32.const 33))
    )
)

The indirect call gets translated to this:

#define TF(table, index, t) ((t)((table).data[index]))
U32 f0(testInstance*i) {
U32 si0;
si0=33U;
si0=TF(i->t0,si0,U32 (*)(testInstance*))(i);
L0:;
return si0;
}

which directly accesses the function in the table at the requested index and calls it without any checking.

I think there should be several checks:

I think the indirect call tests may be getting skipped due to an unsupported global export, but haven't looked into it.

If w2c2 is intended to be used for sandboxing then this is a vulnerability (if not, then the readme should clearly indicate that this tool is not safe to use for sandboxing).

It also looks like w2c2 does not support indirect calls across multiple modules, even in multi-module mode. Is that correct?

Thanks!

turbolent commented 1 year ago

At the moment, w2c2 just translates WebAssembly to C, it does not (yet) have any support for sandboxing translated modules.

Support for sandboxing is not intentionally unavailable, but so far I have not needed it yet – support for sandboxing could be added, and PRs are very welcome! wasm2c employs some techniques that could be ported to w2c2.

turbolent commented 1 year ago

It also looks like w2c2 does not support indirect calls across multiple modules, even in multi-module mode. Is that correct?

How would that look like? Do you have an example?

zyedidia commented 1 year ago

I don’t have an example on hand at the moment but I think it’s possible to import a function from another module and then put it in an indirect function table. I was mostly looking at the differences between w2c2 and wasm2c and noticed that in wasm2c indirect function calls may use a different target module than the current module.