Skip to content

call_indirect not sandboxed properly #76

@zyedidia

Description

@zyedidia

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:

  • The index must be in the bounds of the table.
  • The function at the requested index must not be null.
  • The type of the function being called must match the requested call_indirect signature.

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions