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

Making verifying binary optional in wasi related code path #2220

Closed
yihuaf opened this issue Jul 31, 2023 · 22 comments
Closed

Making verifying binary optional in wasi related code path #2220

yihuaf opened this issue Jul 31, 2023 · 22 comments
Assignees

Comments

@yihuaf
Copy link
Collaborator

yihuaf commented Jul 31, 2023

In the OCI container path, we do a few things to verify that the binary path pass in as part of the process block in the OCI spec exist and has the right permission. The path is usually an absolute path to a binary in the container rootfs. However, wasi and wasm have syntax that calls to a specific module of a wasm file. So the path becomes /some/path/x.wasm#module. This is not a valid path and will fail our check.

Specifically see the issue from runwasi. containerd/runwasi#194

There are two options I am contemplating:

  • Provide a optional field in the libcontainer interface to make the verification optional.
  • Move the verification logic into executor instead.

I like the simplicity of moving the verification logic into executor, but there is one down side. The executor will not be executed until youki start and youki create will no longer fail if the binary doesn't exist. This may also break some existing integration test and even break OCI compliance.

I have not decided on which path to take, but want this issue for tracking and discussion.

@yihuaf yihuaf self-assigned this Jul 31, 2023
@YJDoc2
Copy link
Collaborator

YJDoc2 commented Aug 1, 2023

I feel we should support the wasm use case in some way, but I am inclined against making any changes that will break OCI compatibility or make the integration tests fail. Is there a way to check if given entrypoint is wasm or not, and then conditionally do the check?

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 1, 2023

I am inclined against making any changes that will break OCI compatibility

Agreed. (I will do some test and reading the spec to make sure this. If it doesn't break assumptions in the spec, we can continue to explore if this is a good idea. Otherwise, this is a deal breaker.)

if given entrypoint is wasm or not, and then conditionally do the check?

Perhaps, but I also want to be careful introducing wasm specific information into the libcontainer internals. So far, we have been successfully abstracting wasm related information to outside of the libcontainer. My biggest concern is that wasm is a fast moving targets and things in this space moves quite fast and unstable. On the other hand, libcontainer do need to support OCI which is reasonably stable and mature by now.

Perhaps this means to need to introduce a configuration in the interface to skip the binary verification. At least, in this way, we surface the control knob up to the interface, instead of conceal the checking inside the implementation of libcontainer.


Another idea is to change the executor interface to split off a validate step, which runs as part of the youki create path. I am in the process of changing the executor interface back to using a struct with method, so we can easily make this changes. I think it is not too crazy of an idea to require the executor to have a validate step to validate if the input spec is good.

Sigh... designing a good interface is hard... but at least now we have a customer we can look to for usecases and hints :)

@jsturtevant
Copy link

We are also exploring using OCI Artifacts for WASM. In this case the module was loaded from containerd's content store instead of within the container. The container file system in this case is just the files required for the module to run but the module itself is loaded by the wasm runtime. I got around this by disabling verification temporarily.

@jsturtevant
Copy link

of the two options, I like the "Provide a optional field in the libcontainer interface to make the verification optional" via the builder interface becuase of the downsides of running it at create time. Maybe something like:

ContainerBuilder::new(self.id.clone(), syscall.as_ref())
            .with_executor(vec![Box::new(WasmtimeExecutor {
                stdin,
                stdout,
                stderr,
                engine,
            })])?
            .with_root_path(self.rootdir.clone())?
            .as_init(&self.bundle)
            .with_binary_verification(false)
            .with_systemd(false)
            .build()?;

@utam0k
Copy link
Member

utam0k commented Aug 2, 2023

🤦‍♂I forgot about it.

I like the simplicity of moving the verification logic into executor, but there is one down side. The executor will not be executed until youki start and youki create will no longer fail if the binary doesn't exist. This may also break some existing integration test and even break OCI compliance.

I love @jsturtevant 's idea.

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 3, 2023

@jsturtevant Yes, looks like introducing the nob in the builder interface is the better approach here. I will get this implemented soon.

@jsturtevant
Copy link

The builder approach might have the drawback that if more than one executor is running it would apply to all of them?

https://github.com/containerd/runwasi/pull/156/files#r1283810527

@Mossaka
Copy link
Contributor

Mossaka commented Aug 4, 2023

If we implement binary check logic in can_handle of the DefaultExecutor, does it achieve the same effect as calling verify_binary in the container_init_process function call?

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 8, 2023

If we implement binary check logic in can_handle of the DefaultExecutor, does it achieve the same effect as calling verify_binary in the container_init_process function call?

This is what I was hinting at to abstract the validation logic into the executor. If we head down this path, I do think we need to move where the can_handle (may be renamed to something else like validate to preserve the behavior.

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 8, 2023

The builder approach might have the drawback that if more than one executor is running it would apply to all of them?

https://github.com/containerd/runwasi/pull/156/files#r1283810527

This should be OK. I am changing the API to use a single executor and remove the executor list. The new scheme will favor composing multiple executor into a single executor. This should provider executor authors with greater control on how executors are implemented.

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 8, 2023

I will prototype adding the can_handle (or validate) to the executor interface. I think this is a more elegant way and worth at least prototyped for others maintainers to review.

@utam0k
Copy link
Member

utam0k commented Aug 8, 2023

👀

@Mossaka
Copy link
Contributor

Mossaka commented Aug 9, 2023

The new scheme will favor composing multiple executor into a single executor.

What are the implications of this change for shim authors? In particular, runwasi wasmtime | wasmedge shims are depending on the list of executors feature to enable running both Linux and wasm containers.

@utam0k
Copy link
Member

utam0k commented Aug 13, 2023

@Mossaka @yihuaf Sorry for confusing your team. This is an example to implement the following new interface.
https://github.com/containers/youki/blob/8eccb32247d1e92cbea5ec712cbac01b5cbe3724/crates/youki/src/workload/wasmedge.rs#L16

But I or @yihuaf will update the libcontainer in runwasi after the release. after releasing a new version of youki. I guess it is not hard ;)

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 13, 2023

What are the implications of this change for shim authors? In particular, runwasi wasmtime | wasmedge shims are depending on the list of executors feature to enable running both Linux and wasm containers.

That will still be possible. And as @utam0k mentioned, we will take care of any breaking changes on the runwasi side.

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 13, 2023

Prototype in #2258

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 20, 2023

As a note, the containerd integration test expects the validation to happen before the end of youki create. So we have to choose either create a validate step or make it a builder option to turn it off.

Prototype that failed: #2280

@YJDoc2
Copy link
Collaborator

YJDoc2 commented Aug 21, 2023

As a note, the containerd integration test expects the validation to happen before the end of youki create. So we have to choose either create a validate step or make it a builder option to turn it off.

In this case, I feel exposing a builder option to turn it off, and keeping it on by default would be a better idea than creating a separate validate step.

@jprendes
Copy link
Contributor

Isn't this fixed by #2258 ?

@utam0k
Copy link
Member

utam0k commented Aug 27, 2023

@yihuaf Is there anything you want to do?

@yihuaf
Copy link
Collaborator Author

yihuaf commented Aug 29, 2023

This is fixed. We just need to release and patch runwasi with the breaking changes. I am in the process to draft a PR for runwasi.

@yihuaf yihuaf closed this as completed Aug 29, 2023
@Mossaka
Copy link
Contributor

Mossaka commented Aug 29, 2023

@yihuaf oh I've also started working on using the newest libcontainer from the main branch. To not duplicate the effort, I'll let you work on it.

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

6 participants