Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use ring on wasm32-unknown-unknown due to a missing import (for Envoy Proxy) #1453

Closed
libbkmz opened this issue Feb 2, 2022 · 19 comments

Comments

@libbkmz
Copy link

libbkmz commented Feb 2, 2022

Hello, I'm trying to use the ring's SHA and HMAC for wasm32-unknown-unknown target. I'm building the WASM plugin for the envoy proxy. The build procedure works, but I can't load the WASM file into envoy's. Here is the reproducible source:
Cargo.toml:

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

[lib]
crate-type = ["cdylib"]

[dependencies]
log = "0.4.14"
proxy-wasm = "0.1.4"
ring = "0.16.20"

src/lib.rs:

use proxy_wasm as wasm;
use ring;


#[no_mangle]
pub fn _start() {
    proxy_wasm::set_log_level(wasm::types::LogLevel::Trace);
    proxy_wasm::set_http_context(
        |_context_id, _root_context_id| -> Box<dyn wasm::traits::HttpContext> {
            Box::new(HelloWorld {  })
        },
    )
}

struct HelloWorld {}
impl wasm::traits::Context for HelloWorld {}
impl wasm::traits::HttpContext for HelloWorld {}

Example configuration for envoy:

static_resources:
  listeners:
    - name: main
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 18000
      filter_chains:
        - filters:
            - name: envoy.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                codec_type: auto
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
                          direct_response:
                            status: 200
                            body:
                              inline_string: "example body\n"
                http_filters:
                  - name: envoy.filters.http.wasm
                    typed_config:
                      "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                      type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
                      value:
                        config:
                          vm_config:
                            runtime: "envoy.wasm.runtime.v8"
                            code:
                              local:
                                filename: ".//target/wasm32-unknown-unknown/debug/rust_wasm_test.wasm"
                  - name: envoy.filters.http.router

admin:
  access_log_path: "/dev/null"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 8001

After building via cargo build --target=wasm32-unknown-unknown and running envoy via envoy --config-path envoy.yaml --concurrency 0 -l info I'm getting this error from the envoy side:

[2022-02-02 12:24:28.468][3533850][error][wasm] [source/extensions/common/wasm/wasm_vm.cc:38] Failed to load Wasm module due to a missing import: __wbindgen_externref_xform__.__wbindgen_externref_table_grow
[2022-02-02 12:24:28.468][3533850][error][wasm] [source/extensions/common/wasm/wasm_vm.cc:38] Failed to load Wasm module due to a missing import: __wbindgen_placeholder__.__wbindgen_describe
[2022-02-02 12:24:28.468][3533850][error][wasm] [source/extensions/common/wasm/wasm_vm.cc:38] Failed to load Wasm module due to a missing import: __wbindgen_externref_xform__.__wbindgen_externref_table_set_null
[2022-02-02 12:24:28.468][3533850][error][wasm] [source/extensions/common/wasm/wasm_vm.cc:38] Failed to load Wasm module due to a missing import: __wbindgen_placeholder__.__wbindgen_throw
[2022-02-02 12:24:28.468][3533850][error][wasm] [source/extensions/common/wasm/wasm.cc:109] Wasm VM failed Failed to initialize Wasm code
[2022-02-02 12:24:28.472][3533850][critical][wasm] [source/extensions/common/wasm/wasm.cc:471] Plugin configured to fail closed failed to load
[2022-02-02 12:24:28.481][3533850][critical][main] [source/server/server.cc:117] error initializing configuration 'envoy.yaml': Unable to create Wasm HTTP filter

There are a lot of libraries that depend on the ring, however, I can't use them because of the broken dependency...

@libbkmz libbkmz changed the title Can't use ring on wasm32-unknown-unknown due to a due to a missing import Can't use ring on wasm32-unknown-unknown due to a missing import Feb 2, 2022
@briansmith
Copy link
Owner

What wasm runtime does Envoy use? Knowing this would help me make progress in diagnosing this.

Could you try to reproduce this without Envoy, using just that wasm runtime, but without the Envoy-specific stuff?

@briansmith briansmith changed the title Can't use ring on wasm32-unknown-unknown due to a missing import Can't use ring on wasm32-unknown-unknown due to a missing import (for Envoy Proxy) Mar 28, 2022
@dio
Copy link

dio commented Jul 22, 2022

Envoy uses wee8/envoy.wasm.runtime.v8 (https://www.envoyproxy.io/docs/envoy/latest/configuration/other_features/wasm) turned on by default (at least for Linux x86_64).

Testing the above code with latest envoy from envoyproxy/envoy-dev:79205cdde2dd07cd92f175b0d699b443b516fc5d the errors are reduced:

[2022-07-22 11:47:22.235][2145515][error][wasm] [source/extensions/common/wasm/wasm_vm.cc:38] Failed to load Wasm module due to a missing import: __wbindgen_placeholder__.__wbindgen_describe
[2022-07-22 11:47:22.235][2145515][error][wasm] [source/extensions/common/wasm/wasm.cc:109] Wasm VM failed Failed to initialize Wasm code

The exact SHA used for wee8, https://github.com/envoyproxy/envoy/blob/79205cdde2dd07cd92f175b0d699b443b516fc5d/bazel/repository_locations.bzl#L889-L902

@paulyoung
Copy link

I'm also targeting wasm32-unknown-unknown and trying to use a dependency that relies on ring.

The error I'm seeing is: Module imports function 'LIMBS_are_zero' from 'env' that is not exported by the runtime.

Does anyone have any advice on a possible way forward? Thanks.

@paulyoung
Copy link

It seems like maybe #1176 is relevant and perhaps would have addressed the error I'm seeing.

There was a concern at the time around signing but I'm only interested in verifying when targeting wasm32-unknown-unknown. #1440 is linked there but it sounds like there are still some issues with it when targeting Wasm.

Does anyone know anything more?

@paulyoung
Copy link

I'm trying out the tip of main.

@paulyoung
Copy link

Now running into "could not find sysrand_chunk in super" as described in #1043

@paulyoung
Copy link

Trying this: #918 (comment)

@paulyoung
Copy link

This appears to have worked: codebase-labs@11aafb0

@paulyoung
Copy link

I spoke too soon. Everything built but I'm back to the LIMBS_are_zero issue.

Module imports function 'ring_core_0_17_0_not_released_yet_LIMBS_are_zero' from 'env' that is not exported by the runtime.

@paulyoung
Copy link

paulyoung commented Oct 29, 2022

Actually I think it did work and I just ran into a stale lockfile issue.

@paulyoung
Copy link

Nope, I think the stale lockfile was giving me the impression that things were working when they weren't.

@paulyoung
Copy link

Trying this approach (env vars) next: #1483 (comment)

I've had no need for wasm-pack as of yet but maybe I need to use that or figure out what it's doing under the hood.

@paulyoung
Copy link

I think the issue may be with extern "C" being interpreted as "expect this from the environment" for Wasm modules but I'm not sure.

I tried to summarize things here: https://users.rust-lang.org/t/extern-c-and-wasm/83579

@briansmith
Copy link
Owner

The main branch of ring (pending 0.17 release) does not use wasm-bindgen at all, as we've switched to using getrandom, so the wasm-bindgen symbols shouldn't be required any longer on this branch.

@gagbo
Copy link

gagbo commented Dec 6, 2022

The main branch of ring (pending 0.17 release) does not use wasm-bindgen at all, as we've switched to using getrandom, so the wasm-bindgen symbols shouldn't be required any longer on this branch.

I just tested this, and actually, getrandom does not compile on wasm32-unknown-unknown, unless you activate the js feature, which brings back wasm-bindgen. As I'm exploring I see that you already knew it, so I'm just leaving this here for others to see

I am not sure I'm going to be able to use the other working wasm targets; probably by registering my custom randomness source (that will always fail for my case)

@paulyoung
Copy link

People will need to make their own assessment on the security implications of this but I figured I should at least share what I did in betrusted-io#2 to get a fork of ring working for wasm32-unknown-unknown.

@briansmith
Copy link
Owner

I believe that ring 0.17 implements everything needed for this, except for a random number generator.

@gagbo wrote:

I just tested this, and actually, getrandom does not compile on wasm32-unknown-unknown, unless you activate the js feature, which brings back wasm-bindgen. As I'm exploring I see that you already knew it

The main question is, how are WeebAssembly plugins for Envoy supposed to get random bytes?

When researching the answer to that question, I found proxy-wasm/proxy-wasm-rust-sdk#97 which indicates that you should use thw wasm32-wasi target instead of wasm32-unknown-unknown. That specifically will solve the random bytes issue and things will "just work." There is a PR #1568 that adds wasm32-wasi testing to ring's CI.

I'm going to close this as "not planned" because I assume everybody wlll switch to the wasm32-wasi target. LMK if that's not possible for some reason.

@briansmith briansmith closed this as not planned Won't fix, can't repro, duplicate, stale Oct 14, 2023
@gagbo
Copy link

gagbo commented Nov 1, 2023

The main question is, how are WeebAssembly plugins for Envoy supposed to get random bytes?

I'm not using "Envoy", so I wouldn't know, but our in-house (@fiberplane) plugin system gets its random bytes from the host runtime. We ship a wasmer runtime with custom bindings that allow access to a source of random bytes. And we didn't migrate to something that could target wasi as far as I know, so this wouldn't help.

On the other hand, our issue with ring was a transitive issue from trying to use the AWS SDK crate to do a plugin around those services, and I bit the bullet and just removed my SDK dependency and rewritten every API call using manual API types and request signing. So this is not an issue for me anymore.

EDIT: and sorry for the delay in the response

@briansmith
Copy link
Owner

PR #1754 will allow you to use the getrandom crate's custom feature to support wasm32-unknown-unknown.

However, in general I recommend people use a target that's not wasm32-unknown-unknown whenever practical so that such workarounds aren't necessary. (We should create wasm32-browser and similar so that people don't need to use -unknown-unknown any more.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants